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 # Wie lang die Datentraegerbezeichnung sein darf. exFAT und FAT lassen nur
# initialisiert" - erst danach gibt es einen Laufwerksbuchstaben. # 11 Zeichen zu - laenger, und mkfs bricht ab.
DEFAULT_FS = "ext4" 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" DEFAULT_SIZE = "20G"
def default_filesystem():
return "exfat" if have("mkfs.exfat") else "ext4"
DEFAULT_FS = "exfat"
README = """Transfer-Laufwerk von pvesnap README = """Transfer-Laufwerk von pvesnap
Dieses Laufwerk gehoert zu keiner Maschine. Es dient nur dazu, Dateien Dieses Laufwerk gehoert zu keiner Maschine. Es dient nur dazu, Dateien
@@ -197,7 +208,7 @@ class Volume:
name: str name: str
image: str = "" image: str = ""
size: int = 0 size: int = 0
fs: str = DEFAULT_FS fs: str = "ext4"
label: str = "" label: str = ""
note: str = "" note: str = ""
created: int = 0 created: int = 0
@@ -383,7 +394,7 @@ def get(name):
# Anlegen # 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): progress=None):
"""Ein neues Transfer-Laufwerk anlegen und formatieren.""" """Ein neues Transfer-Laufwerk anlegen und formatieren."""
def step(text): 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()): if any(v.name == name for v in _index_load()):
raise TransferError("Ein Transfer-Laufwerk namens %r gibt es schon." % name) raise TransferError("Ein Transfer-Laufwerk namens %r gibt es schon." % name)
fs = fs or default_filesystem()
if fs not in FILESYSTEMS: if fs not in FILESYSTEMS:
raise TransferError("Unbekanntes Dateisystem %r (%s)" raise TransferError("Unbekanntes Dateisystem %r (%s)"
% (fs, ", ".join(sorted(FILESYSTEMS)))) % (fs, ", ".join(sorted(FILESYSTEMS))))
@@ -412,7 +424,7 @@ def create(name, size=DEFAULT_SIZE, fs=DEFAULT_FS, note="", partitioned=True,
"als 'nicht initialisiert'.") "als 'nicht initialisiert'.")
size_bytes = parse_size(size) 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) image = os.path.join(TRANSFER_DIR, "%s.img" % name)
os.makedirs(TRANSFER_DIR, exist_ok=True) os.makedirs(TRANSFER_DIR, exist_ok=True)
@@ -493,6 +505,16 @@ def partition_of(device):
return 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): def _place_readme(device, fs, label):
mountpoint = os.path.join(MOUNT_ROOT, ".neu-%d" % os.getpid()) mountpoint = os.path.join(MOUNT_ROOT, ".neu-%d" % os.getpid())
try: try: