feat: offline_note sur partitions NTFS verrouillées

Distingue volume verrouillé (Windows hibernate/Fast Startup)
de ntfsresize absent. Champ offline_note dans le payload JSON.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gilles Soulier
2026-05-28 20:45:26 +02:00
parent 2ac5a3b2de
commit 29a63be483
+43 -25
View File
@@ -428,24 +428,37 @@ def _ext4_space(dev):
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
try:
r = subprocess.run(
["ntfsresize", "--info", "--force", dev],
capture_output=True, text=True, timeout=15,
)
combined = r.stdout + r.stderr
if r.returncode != 0:
locked_markers = ("hibernated", "fast restart", "Windows is", "hiberfil",
"unclean", "Refusing to operate")
if any(m in combined for m in locked_markers):
note = "Volume NTFS verrouillé — Windows en veille ou Fast Startup actif"
else:
note = "Lecture NTFS impossible (ntfsresize indisponible ou erreur)"
dprint(f"NTFS {dev} : {note}")
return {"offline_note": note}
total = used = None
for line in combined.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 {"offline_note": "Taille NTFS non déterminée"}
except FileNotFoundError:
return {"offline_note": "ntfsresize non installé — sudo apt install ntfs-3g"}
except Exception as e:
return {"offline_note": f"Erreur lecture NTFS : {e}"}
def _btrfs_space(dev):
out = run(["btrfs", "filesystem", "show", dev])
@@ -484,6 +497,7 @@ def build_partitions(children, df_map, lvm_map, home_done):
"free_bytes": None, "free_human": None,
"used_percent": None,
"mountpoint": mountpoint,
"offline_note": None,
"home_users": None,
"lvm": None,
}
@@ -504,13 +518,17 @@ def build_partitions(children, df_map, lvm_map, home_done):
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']}%)")
if "offline_note" in space:
part["offline_note"] = space["offline_note"]
dprint(f" partition {name} : {space['offline_note']}")
else:
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]: