Transfer-Laufwerke: exFAT als Vorgabe, Bezeichnungen kuerzen

exFAT kann Windows wie Linux nativ, und anders als FAT32 gibt es keine
4-GB-Grenze je Datei. Damit ist es die richtige Vorgabe fuer ein Medium, das
zwischen Host und beliebigen Gaesten pendelt. Fehlt der Formatierer, faellt
die Wahl auf ext4 zurueck.

Dabei ein eigener Fehler aufgefallen: exFAT und FAT lassen nur 11 Zeichen
Datentraegerbezeichnung zu, "PVESNAP-DUMPS" waeren 13 gewesen - mkfs haette
abgebrochen. Die Bezeichnung ist jetzt schlicht der Name in Grossbuchstaben,
je Dateisystem gekuerzt. Im Gast genuegt damit:

    mount /dev/disk/by-label/DUMPS /mnt

Geprueft: GPT-Partition mit msftdata-Kennung (dafuer vergibt Windows sofort
einen Laufwerksbuchstaben), blkid meldet TYPE="exfat" LABEL="DUMPS".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
duffyduck
2026-07-31 20:26:19 +02:00
co-authored by Claude Opus 5
parent f44ad0e34a
commit 46ffc54059
+28 -6
View File
@@ -90,11 +90,22 @@ FILESYSTEMS = {
},
}
# Ohne Partitionstabelle zeigt Windows den Datentraeger als "nicht
# initialisiert" - erst danach gibt es einen Laufwerksbuchstaben.
DEFAULT_FS = "ext4"
# Wie lang die Datentraegerbezeichnung sein darf. exFAT und FAT lassen nur
# 11 Zeichen zu - laenger, und mkfs bricht ab.
LABEL_MAX = {"vfat": 11, "exfat": 11, "xfs": 12, "ext4": 16, "ntfs": 32}
# exFAT als Vorgabe: Windows und Linux koennen beide damit umgehen, und anders
# als FAT32 gibt es keine 4-GB-Grenze je Datei. Fehlt der Formatierer, faellt
# die Wahl auf ext4 zurueck.
DEFAULT_SIZE = "20G"
def default_filesystem():
return "exfat" if have("mkfs.exfat") else "ext4"
DEFAULT_FS = "exfat"
README = """Transfer-Laufwerk von pvesnap
Dieses Laufwerk gehoert zu keiner Maschine. Es dient nur dazu, Dateien
@@ -197,7 +208,7 @@ class Volume:
name: str
image: str = ""
size: int = 0
fs: str = DEFAULT_FS
fs: str = "ext4"
label: str = ""
note: str = ""
created: int = 0
@@ -383,7 +394,7 @@ def get(name):
# Anlegen
# ---------------------------------------------------------------------------
def create(name, size=DEFAULT_SIZE, fs=DEFAULT_FS, note="", partitioned=True,
def create(name, size=DEFAULT_SIZE, fs=None, note="", partitioned=True,
progress=None):
"""Ein neues Transfer-Laufwerk anlegen und formatieren."""
def step(text):
@@ -398,6 +409,7 @@ def create(name, size=DEFAULT_SIZE, fs=DEFAULT_FS, note="", partitioned=True,
if any(v.name == name for v in _index_load()):
raise TransferError("Ein Transfer-Laufwerk namens %r gibt es schon." % name)
fs = fs or default_filesystem()
if fs not in FILESYSTEMS:
raise TransferError("Unbekanntes Dateisystem %r (%s)"
% (fs, ", ".join(sorted(FILESYSTEMS))))
@@ -412,7 +424,7 @@ def create(name, size=DEFAULT_SIZE, fs=DEFAULT_FS, note="", partitioned=True,
"als 'nicht initialisiert'.")
size_bytes = parse_size(size)
label = ("PVESNAP-%s" % name.upper().replace("_", "-"))[:11 if fs == "vfat" else 32]
label = _label_for(name, fs)
image = os.path.join(TRANSFER_DIR, "%s.img" % name)
os.makedirs(TRANSFER_DIR, exist_ok=True)
@@ -493,6 +505,16 @@ def partition_of(device):
return device
def _label_for(name, fs):
"""Datentraegerbezeichnung - so, dass man sie im Gast wiederfindet.
Kurz gehalten, weil exFAT und FAT nur 11 Zeichen zulassen. Im Gast reicht
damit: mount /dev/disk/by-label/<NAME> /mnt
"""
clean = re.sub(r"[^A-Z0-9_-]", "", name.upper())
return clean[:LABEL_MAX.get(fs, 11)] or "PVESNAP"
def _place_readme(device, fs, label):
mountpoint = os.path.join(MOUNT_ROOT, ".neu-%d" % os.getpid())
try: