feat: espace offline pour partitions non montées

tune2fs pour ext4, ntfsresize pour NTFS, btrfs partiel.
Utile pour dual-boot et partitions de données non montées.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gilles Soulier
2026-05-28 20:39:30 +02:00
parent ac51959eb2
commit 2ac5a3b2de
+75
View File
@@ -394,6 +394,71 @@ def get_proxmox_role(dev_name):
return None
# -- Espace offline (partitions non montées) ----------------------------------
def get_offline_space(dev, fstype):
"""Lit l'espace d'une partition non montée selon son type de filesystem."""
if fstype in ("ext2", "ext3", "ext4"):
return _ext4_space(dev)
if fstype == "ntfs":
return _ntfs_space(dev)
if fstype == "btrfs":
return _btrfs_space(dev)
return None
def _ext4_space(dev):
out = run(["tune2fs", "-l", dev])
if not out:
return None
vals = {}
for line in out.splitlines():
for key in ("Block count", "Free blocks", "Block size"):
if line.startswith(key + ":"):
try:
vals[key] = int(line.split(":", 1)[1].strip().replace(",", ""))
except ValueError:
pass
try:
total = vals["Block count"] * vals["Block size"]
free = vals["Free blocks"] * vals["Block size"]
used = total - free
return {"size_bytes": total, "used_bytes": used, "free_bytes": free,
"used_percent": int(used / total * 100) if total else 0}
except KeyError:
return None
def _ntfs_space(dev):
# ntfsresize -i indique la taille minimale ≈ espace utilisé
out = run(["ntfsresize", "--info", "--force", dev])
if not out:
return None
total = used = None
for line in out.splitlines():
if "Current volume size:" in line:
m = re.search(r"(\d+)\s+bytes", line)
if m:
total = int(m.group(1))
if "You might resize at" in line:
m = re.search(r"(\d+)\s+bytes", line)
if m:
used = int(m.group(1))
if total and used:
return {"size_bytes": total, "used_bytes": used, "free_bytes": total - used,
"used_percent": int(used / total * 100) if total else 0}
return None
def _btrfs_space(dev):
out = run(["btrfs", "filesystem", "show", dev])
if not out:
return None
# "Total devices 1 FS bytes used 10.00GiB"
m = re.search(r"FS bytes used\s+([\d.]+)(\w+)", out)
if m:
# approximation seulement, pas de total fiable sans montage
dprint(f"btrfs {dev} : espace utilisé approximatif")
return None # trop imprecis sans montage
# -- Construction des partitions ----------------------------------------------
def build_partitions(children, df_map, lvm_map, home_done):
@@ -436,6 +501,16 @@ def build_partitions(children, df_map, lvm_map, home_done):
f"{part['used_human']} / {part['size_human']} ({part['used_percent']}%)")
else:
dprint(f" partition {name} : fstype={fstype}, non montee")
if fstype in ("ext2", "ext3", "ext4", "ntfs", "btrfs"):
space = get_offline_space(f"/dev/{name}", fstype)
if space:
part["used_bytes"] = space["used_bytes"]
part["used_human"] = bytes_human(space["used_bytes"])
part["free_bytes"] = space["free_bytes"]
part["free_human"] = bytes_human(space["free_bytes"])
part["used_percent"] = space["used_percent"]
dprint(f" partition {name} offline : "
f"{part['used_human']} / {part['size_human']} ({part['used_percent']}%)")
# /home users sur cette partition
if mountpoint == "/home" and not home_done[0]: