Skip to content

Commit 159e24e

Browse files
committed
Started to remove subprocessees, starting 207 and 171.
Please enter the commit message for your changes. Lines starting with '' will be ignored, and an empty message aborts the commit. On branch dev Your branch is up to date with 'origin/dev'. Changes to be committed: new file: src/lufus/block_ops.py modified: src/lufus/drives/find_usb.py modified: src/lufus/drives/formatting.py modified: src/lufus/drives/get_usb_info.py modified: src/lufus/gui/gui.py new file: src/lufus/iso9660.py modified: src/lufus/writing/flash_usb.py modified: src/lufus/writing/install_ventoy.py modified: src/lufus/writing/windows/detect.py modified: src/lufus/writing/windows/flash.py modified: src/lufus/writing/windows/tweaks.py modified: tests/test_find_usb.py modified: tests/test_flash_usb_and_find_usb_fixes.py modified: tests/test_formatting.py modified: tests/test_get_usb_info.py modified: tests/test_get_usb_info_and_detect_windows_fixes.py modified: tests/test_linux_iso_detection.py
1 parent 5fc894f commit 159e24e

17 files changed

Lines changed: 1159 additions & 539 deletions

src/lufus/block_ops.py

Lines changed: 494 additions & 0 deletions
Large diffs are not rendered by default.

src/lufus/drives/find_usb.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import psutil
22
import os
3-
import subprocess
43
import getpass
54
from lufus import state
65
from lufus.lufus_logging import get_logger
6+
from lufus.block_ops import get_device_label
77

88
log = get_logger(__name__)
99

@@ -51,16 +51,7 @@ def find_usb() -> dict[str, str]:
5151
if not device_node:
5252
continue
5353

54-
label = None
55-
try:
56-
label = subprocess.check_output(
57-
["lsblk", "-d", "-n", "-o", "LABEL", device_node],
58-
text=True,
59-
timeout=5,
60-
).strip()
61-
except (subprocess.CalledProcessError, subprocess.TimeoutExpired):
62-
pass
63-
54+
label = get_device_label(device_node)
6455
if not label:
6556
label = os.path.basename(mount_path)
6657

src/lufus/drives/formatting.py

Lines changed: 25 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
from lufus.drives import find_usb as fu
1111
from lufus.utils import strip_partition_suffix, require_root, get_mount_and_drive
1212
from lufus.lufus_logging import get_logger
13+
from lufus.block_ops import (
14+
mount as block_mount,
15+
umount as block_umount,
16+
umount_lazy,
17+
get_logical_block_size,
18+
write_single_partition_table,
19+
reread_partitions,
20+
)
1321

1422
log = get_logger(__name__)
1523

@@ -59,23 +67,12 @@ def unmount(drive: str = None) -> bool:
5967
targets = glob.glob(f"{drive}*")
6068
log.info("Unmounting %s...", drive)
6169
for target in targets:
62-
try:
63-
subprocess.run(["umount", "-l", target], check=True)
70+
if umount_lazy(target):
6471
time.sleep(0.5)
6572
log.info("Unmounted %s successfully.", target)
66-
except subprocess.CalledProcessError as e:
67-
# exit 32 = "not mounted" on Linux — acceptable when clearing a drive
68-
if e.returncode == 32:
69-
log.info("Unmounted %s (was already unmounted).", target)
70-
continue
71-
log.error("umount -l %s exited with code %d", target, e.returncode)
72-
unmount_fail()
73-
return False
74-
except Exception as e:
75-
log.error("(UMNTFUNC) Unexpected error type: %s — %s", type(e).__name__, e)
76-
log_unexpected_error()
77-
return False
78-
subprocess.run(["udevadm", "settle"])
73+
else:
74+
# Target may already be unmounted — not a fatal error
75+
log.info("Unmounted %s (was already unmounted or not a mount).", target)
7976
time.sleep(0.5)
8077
return True
8178

@@ -98,10 +95,9 @@ def remount(drive: str = None) -> bool:
9895
return False
9996
log.info("Remounting %s -> %s...", drive, mount)
10097
try:
101-
subprocess.run(["mount", drive, mount], check=True)
102-
log.info("Remounted %s -> %s successfully.", drive, mount)
103-
return True
104-
except subprocess.CalledProcessError:
98+
if block_mount(drive, mount):
99+
log.info("Remounted %s -> %s successfully.", drive, mount)
100+
return True
105101
format_fail()
106102
return False
107103
except Exception as e:
@@ -212,27 +208,13 @@ def check_device_bad_blocks() -> bool:
212208
# device geometry. Fall back to 4096 bytes if detection fails.
213209
logical_block_size = 4096
214210
try:
215-
probe = subprocess.run(
216-
[_find_tool("blockdev"), "--getss", drive],
217-
capture_output=True,
218-
text=True,
219-
check=False,
220-
)
221-
if probe.returncode == 0:
222-
probed = probe.stdout.strip()
223-
if probed.isdigit():
224-
logical_block_size = int(probed)
225-
else:
226-
log.warning(
227-
"Unexpected blockdev output for %r: %r. Using default block size.",
228-
drive,
229-
probed,
230-
)
211+
probed = get_logical_block_size(drive)
212+
if probed is not None:
213+
logical_block_size = probed
231214
else:
232215
log.warning(
233-
"blockdev failed for %s (exit %d). Using default block size.",
216+
"Could not probe sector size for %s. Using default block size.",
234217
drive,
235-
probe.returncode,
236218
)
237219
except Exception as exc:
238220
log.warning(
@@ -388,41 +370,13 @@ def _apply_partition_scheme(drive: str) -> None:
388370
scheme_name = "GPT" if scheme == 0 else "MBR"
389371
log.info("Applying %s partition scheme to %s...", scheme_name, raw_device)
390372
try:
391-
if scheme == 0:
392-
# GPT — used for UEFI targets
393-
subprocess.run([_find_tool("parted"), "-s", raw_device, "mklabel", "gpt"], check=True)
394-
subprocess.run(
395-
[
396-
_find_tool("parted"),
397-
"-s",
398-
raw_device,
399-
"mkpart",
400-
"primary",
401-
"1MiB",
402-
"100%",
403-
],
404-
check=True,
405-
)
373+
scheme_key = "gpt" if scheme == 0 else "mbr"
374+
if write_single_partition_table(raw_device, scheme=scheme_key):
375+
log.info("Partition scheme %s applied to %s.", scheme_name, raw_device)
406376
else:
407-
# MBR — used for BIOS/legacy targets
408-
subprocess.run([_find_tool("parted"), "-s", raw_device, "mklabel", "msdos"], check=True)
409-
subprocess.run(
410-
[
411-
_find_tool("parted"),
412-
"-s",
413-
raw_device,
414-
"mkpart",
415-
"primary",
416-
"1MiB",
417-
"100%",
418-
],
419-
check=True,
420-
)
421-
log.info("Partition scheme %s applied to %s.", scheme_name, raw_device)
377+
log.error("(PARTITION) Failed to apply partition scheme.")
422378
except FileNotFoundError:
423379
log.error("'parted' not found. Install parted.")
424-
except subprocess.CalledProcessError as e:
425-
log.error("(PARTITION) Failed to apply partition scheme: %s", e)
426380
except Exception as e:
427381
log.error("(PARTITION) Unexpected error: %s: %s", type(e).__name__, e)
428382
log_unexpected_error()
@@ -433,17 +387,15 @@ def drive_repair() -> None:
433387
# add smartctl check if possible
434388
# use fsck to prevent deletion of files for repair
435389
# use testdisk for partition recovery if possible
436-
# do dd if=/dev/zero of=/dev/sdX bs=1M count=10 conv=notrunc before sfdisk use
437390
_, drive, _ = _get_mount_and_drive()
438391
if not drive:
439392
log.error("No drive node found. Cannot repair.")
440393
return
441394
raw_device = strip_partition_suffix(drive)
442-
cmd = [_find_tool("sfdisk"), raw_device]
443395
log.info("Attempting drive repair on %s (raw: %s)...", drive, raw_device)
444396
try:
445-
subprocess.run(["umount", drive], check=True)
446-
subprocess.run(cmd, input=b",,0c;\n", check=True)
397+
block_umount(drive)
398+
write_single_partition_table(raw_device, scheme="mbr")
447399
subprocess.run([_find_tool("mkfs.vfat"), "-F", "32", "-n", "REPAIRED", drive], check=True)
448400
log.info("Successfully repaired drive %s (FAT32).", drive)
449401
except Exception as e:

src/lufus/drives/get_usb_info.py

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import psutil
22
import os
3-
import subprocess
43
from typing import TypedDict
54
from lufus.lufus_logging import get_logger
5+
from lufus.block_ops import get_device_size, get_device_label
66

77
log = get_logger(__name__)
88

@@ -25,20 +25,12 @@ def get_usb_info(usb_path: str) -> USBDeviceInfo | None:
2525
log.warning("Could not find device node for USB path: %s", usb_path)
2626
return None
2727

28-
size_output = subprocess.check_output(
29-
["lsblk", "-d", "-n", "-b", "-o", "SIZE", device_node],
30-
text=True,
31-
timeout=5,
32-
).strip()
33-
34-
usb_size = int(size_output) if size_output.isdigit() else 0
35-
if not size_output.isdigit():
36-
log.warning("Could not parse device size: %r", size_output)
28+
usb_size = get_device_size(device_node) or 0
3729

3830
if usb_size > 32 * 1024**3:
3931
log.warning("USB device is large (%d bytes); confirm before flashing.", usb_size)
4032

41-
label = subprocess.check_output(["lsblk", "-d", "-n", "-o", "LABEL", device_node], text=True, timeout=5).strip()
33+
label = get_device_label(device_node)
4234
if not label:
4335
label = os.path.basename(usb_path)
4436

@@ -49,15 +41,9 @@ def get_usb_info(usb_path: str) -> USBDeviceInfo | None:
4941
}
5042
log.info("USB Info: %s", usb_info)
5143
return usb_info
52-
except subprocess.TimeoutExpired as e:
53-
log.error("Timed out getting USB info for %s: %s", usb_path, e)
54-
return None
5544
except PermissionError:
5645
log.error("Permission denied when trying to get USB info: %s", usb_path)
5746
return None
58-
except subprocess.CalledProcessError as e:
59-
log.error("Error getting USB info: %s", e)
60-
return None
6147
except Exception as err:
6248
log.error("Unexpected error getting USB info: %s", err)
6349
return None

0 commit comments

Comments
 (0)