@@ -51,6 +51,8 @@ def _status(msg: str) -> None:
5151 try :
5252 iso_size = os .path .getsize (iso_path )
5353 _status (f"File size: { iso_size :,} bytes ({ iso_size / (1024 ** 3 ):.2f} GiB)" )
54+ if progress_cb :
55+ progress_cb (2 )
5456
5557 if iso_path .lower ().endswith (".iso" ):
5658 _status (f"Validating ISO9660 signature for: { iso_path } " )
@@ -62,8 +64,15 @@ def _status(msg: str) -> None:
6264 else :
6365 _status (f"Not an ISO file ({ os .path .basename (iso_path )} ), skipping ISO signature check" )
6466
67+ if progress_cb :
68+ progress_cb (5 )
69+
6570 _status ("Checking if image contains installation markers..." )
66- if is_windows_iso (iso_path ):
71+ iso_type = detect_iso_type (iso_path )
72+ if progress_cb :
73+ progress_cb (8 )
74+
75+ if iso_type == IsoType .WINDOWS :
6776 _status ("Windows Installation media detected, routing to flash_windows (ISO mode)" )
6877 return flash_windows (
6978 device ,
@@ -73,12 +82,14 @@ def _status(msg: str) -> None:
7382 status_cb = status_cb ,
7483 )
7584
76- iso_type = detect_iso_type (iso_path )
7785 if iso_type == IsoType .LINUX :
7886 _status ("Linux Installation media detected, will use dd for flashing" )
7987 else :
8088 _status ("Generic or unknown image, will use dd for flashing" )
8189
90+ if progress_cb :
91+ progress_cb (10 )
92+
8293 dd_args = [
8394 "dd" ,
8495 f"if={ iso_path } " ,
@@ -93,7 +104,11 @@ def _status(msg: str) -> None:
93104 _status (f"Writing { iso_size :,} bytes to { shlex .quote (device )} , this may take several minutes..." )
94105
95106 try :
96- process = subprocess .Popen (dd_args , stderr = subprocess .PIPE , stdout = subprocess .DEVNULL )
107+ # Use LC_ALL=C to ensure "bytes" is the keyword for progress parsing
108+ # and set a consistent output format across different locales.
109+ env = os .environ .copy ()
110+ env ["LC_ALL" ] = "C"
111+ process = subprocess .Popen (dd_args , stderr = subprocess .PIPE , stdout = subprocess .DEVNULL , env = env )
97112 except FileNotFoundError :
98113 log .error ("Flash failed: 'dd' utility not found. Install coreutils." )
99114 _status ("Flash failed: 'dd' utility not found. Install coreutils." )
@@ -104,27 +119,43 @@ def _status(msg: str) -> None:
104119 buf = b""
105120 last_pct = - 1
106121 while True :
107- chunk = process .stderr .readline ()
122+ # Read in small chunks to handle \r progress updates from dd without blocking
123+ # until a newline (\n) is received. status=progress usually emits \r.
124+ try :
125+ chunk = process .stderr .read (128 )
126+ except Exception as e :
127+ log .warning ("Error reading dd stderr: %s" , e )
128+ break
129+
108130 if not chunk :
109131 break
110132 buf += chunk
133+ # Split by \r or \n to catch all progress updates
111134 parts = re .split (rb"[\r\n]" , buf )
135+ # The last part might be incomplete, keep it in the buffer
112136 buf = parts [- 1 ]
137+
113138 for line in parts [:- 1 ]:
114139 line = line .strip ()
115140 if not line :
116141 continue
117142 m = re .match (rb"^(\d+)\s+bytes" , line )
118143 if m and iso_size > 0 :
119144 bytes_done = int (m .group (1 ))
120- pct = min (int (bytes_done * 100 / iso_size ), 99 )
145+ # Scale progress to 10-95% range to leave room for early steps and final sync
146+ pct_raw = min (int (bytes_done * 100 / iso_size ), 100 )
147+ pct = 10 + int (pct_raw * 0.85 )
148+
121149 if pct != last_pct :
122- _status (f"dd progress: { bytes_done :,} / { iso_size :,} bytes ({ pct } %)" )
150+ _status (f"dd progress: { bytes_done :,} / { iso_size :,} bytes ({ pct_raw } %)" )
123151 last_pct = pct
124152 if progress_cb :
125153 progress_cb (pct )
126154 else :
127- log .warning ("dd stderr: %s" , line .decode ("utf-8" , errors = "replace" ))
155+ # Filter out common dd output lines to avoid logging noise
156+ line_str = line .decode ("utf-8" , errors = "replace" )
157+ if not any (x in line_str for x in ["records in" , "records out" , "copied" ]):
158+ log .warning ("dd stderr: %s" , line_str )
128159
129160 process .wait ()
130161 _status (f"dd process exited with return code { process .returncode } " )
0 commit comments