Generate test maps at runtime in ddrescue-tui

This commit is contained in:
2Shirt 2023-07-09 13:58:59 -07:00
parent 840008d8cd
commit 7c16d13f65
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
2 changed files with 36 additions and 2 deletions

View file

@ -37,7 +37,7 @@ DDRESCUE_SETTINGS = {
'--retry-passes': {'Selected': True, 'Value': '0', },
'--reverse': {'Selected': False, },
'--skip-size': {'Selected': True, 'Value': '0.001,0.02', }, # Percentages of source size
'--test-mode': {'Selected': False, 'Value': 'test.map', },
'--test-mode': {'Selected': False, },
'--timeout': {'Selected': True, 'Value': '30m', },
'-vvvv': {'Selected': True, 'Hidden': True, },
},

View file

@ -14,6 +14,7 @@ import shutil
import subprocess
import time
from random import randint
from typing import Any
import psutil
@ -125,6 +126,7 @@ class BlockPair():
'trim': 'Pending',
'scrape': 'Pending',
}
self.test_map: pathlib.Path | None = None
self.view_map: bool = 'DISPLAY' in os.environ or 'WAYLAND_DISPLAY' in os.environ
self.view_proc: subprocess.Popen | None = None
@ -1196,6 +1198,16 @@ def build_ddrescue_cmd(block_pair, pass_name, settings_menu) -> list[str]:
# Add source physical sector size (if possible)
cmd.append(f'--sector-size={block_pair.sector_size}')
# Generate test map if needed
if '--test-mode' in cmd:
cmd.remove('--test-mode')
if not block_pair.test_map:
block_pair.test_map = block_pair.map_path.with_stem(
f'{block_pair.map_path.stem}-testing'
)
generate_test_map(map_path=block_pair.test_map, size=domain_size)
cmd.append(f'--test-mode={block_pair.test_map}')
# Add block pair and map file
if PLATFORM == 'Darwin':
# Use Raw disks if possible
@ -1484,6 +1496,28 @@ def fstype_is_ok(path, map_dir=False) -> bool:
return is_ok
def generate_test_map(map_path: pathlib.Path, size: int) -> None:
"""Generate test map with roughly 20% of the space marked as bad."""
chunk = 2*1024**2
output = [
'# Mapfile. Created by WizardKit',
'0x0 ? 1',
]
position = 0
# Generate "holes"
steps, remainder = divmod(size, chunk)
for _ in range(steps):
bad = randint(1, 5) % 5 == 0
output.append(f'{hex(position)} {hex(chunk)} {"-" if bad else "+"}')
position += chunk
if remainder:
output.append(f'{hex(position)} {hex(remainder)} +')
# Save map
map_path.write_text('\n'.join(output), encoding='utf-8')
def get_ddrescue_settings(settings_menu) -> list:
"""Get ddrescue settings from menu selections, returns list."""
settings = []
@ -2238,7 +2272,7 @@ def zero_fill_destination(state: State, dry_run: bool = True) -> None:
# Prep zero-fill map file
zero_map_path = block_pair.map_path.with_stem(
f'{block_pair.map_path.name}_zero-fill',
f'{block_pair.map_path.stem}_zero-fill',
)
io.copy_file(block_pair.map_path, zero_map_path, overwrite=True)
if larger_destination: