parent
b750432381
commit
c3ec690318
2 changed files with 33 additions and 5 deletions
|
|
@ -23,15 +23,18 @@ AUTO_PASS_THRESHOLDS = {
|
||||||
DDRESCUE_SETTINGS = {
|
DDRESCUE_SETTINGS = {
|
||||||
'Default': {
|
'Default': {
|
||||||
'--binary-prefixes': {'Selected': True, 'Hidden': True, },
|
'--binary-prefixes': {'Selected': True, 'Hidden': True, },
|
||||||
|
'--complete-only': {'Selected': True, 'Hidden': True, },
|
||||||
'--data-preview': {'Selected': True, 'Value': '5', 'Hidden': True, },
|
'--data-preview': {'Selected': True, 'Value': '5', 'Hidden': True, },
|
||||||
'--idirect': {'Selected': True, },
|
'--idirect': {'Selected': True, },
|
||||||
'--odirect': {'Selected': True, },
|
'--odirect': {'Selected': True, },
|
||||||
|
'--input-position': {'Selected': False, 'Value': '0', },
|
||||||
'--max-error-rate': {'Selected': True, 'Value': '100MiB', },
|
'--max-error-rate': {'Selected': True, 'Value': '100MiB', },
|
||||||
'--max-read-rate': {'Selected': False, 'Value': '1MiB', },
|
'--max-read-rate': {'Selected': False, 'Value': '1MiB', },
|
||||||
'--min-read-rate': {'Selected': True, 'Value': '64KiB', },
|
'--min-read-rate': {'Selected': True, 'Value': '64KiB', },
|
||||||
'--reopen-on-error': {'Selected': True, },
|
'--reopen-on-error': {'Selected': True, },
|
||||||
'--retry-passes': {'Selected': True, 'Value': '0', },
|
'--retry-passes': {'Selected': True, 'Value': '0', },
|
||||||
'--reverse': {'Selected': False, },
|
'--reverse': {'Selected': False, },
|
||||||
|
'--skip-size': {'Selected': True, 'Value': '0.0001,0.01', }, # Percentages of source size
|
||||||
'--test-mode': {'Selected': False, 'Value': 'test.map', },
|
'--test-mode': {'Selected': False, 'Value': 'test.map', },
|
||||||
'--timeout': {'Selected': True, 'Value': '30m', },
|
'--timeout': {'Selected': True, 'Value': '30m', },
|
||||||
'-vvvv': {'Selected': True, 'Hidden': True, },
|
'-vvvv': {'Selected': True, 'Hidden': True, },
|
||||||
|
|
@ -46,6 +49,7 @@ DDRESCUE_SETTINGS = {
|
||||||
'--max-read-rate': {'Selected': True, 'Value': '64MiB', },
|
'--max-read-rate': {'Selected': True, 'Value': '64MiB', },
|
||||||
'--min-read-rate': {'Selected': True, 'Value': '1KiB', },
|
'--min-read-rate': {'Selected': True, 'Value': '1KiB', },
|
||||||
'--reopen-on-error': {'Selected': True, },
|
'--reopen-on-error': {'Selected': True, },
|
||||||
|
'--skip-size': {'Selected': True, 'Value': '0.001,0.05', }, # Percentages of source size
|
||||||
'--timeout': {'Selected': False, 'Value': '30m', },
|
'--timeout': {'Selected': False, 'Value': '30m', },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ DDRESCUE_LOG_REGEX = re.compile(
|
||||||
r'.*\(\s*(?P<percent>\d+\.?\d*)%\)$',
|
r'.*\(\s*(?P<percent>\d+\.?\d*)%\)$',
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
)
|
)
|
||||||
|
INITIAL_SKIP_MIN = 64 * 1024 # This is ddrescue's minimum accepted value
|
||||||
REGEX_REMAINING_TIME = re.compile(
|
REGEX_REMAINING_TIME = re.compile(
|
||||||
r'remaining time:'
|
r'remaining time:'
|
||||||
r'\s*((?P<days>\d+)d)?'
|
r'\s*((?P<days>\d+)d)?'
|
||||||
|
|
@ -1202,7 +1203,7 @@ def build_block_pair_report(block_pairs, settings):
|
||||||
return report
|
return report
|
||||||
|
|
||||||
|
|
||||||
def build_ddrescue_cmd(block_pair, pass_name, settings):
|
def build_ddrescue_cmd(block_pair, pass_name, settings_menu):
|
||||||
"""Build ddrescue cmd using passed details, returns list."""
|
"""Build ddrescue cmd using passed details, returns list."""
|
||||||
cmd = ['sudo', 'ddrescue']
|
cmd = ['sudo', 'ddrescue']
|
||||||
if (block_pair.destination.is_block_device()
|
if (block_pair.destination.is_block_device()
|
||||||
|
|
@ -1216,8 +1217,30 @@ def build_ddrescue_cmd(block_pair, pass_name, settings):
|
||||||
elif pass_name == 'scrape':
|
elif pass_name == 'scrape':
|
||||||
# Allow trimming and scraping
|
# Allow trimming and scraping
|
||||||
pass
|
pass
|
||||||
cmd.extend(settings)
|
|
||||||
cmd.append(f'--size={block_pair.size}')
|
# Fix domain size based on starting position
|
||||||
|
domain_size = block_pair.size
|
||||||
|
if settings_menu.options['--input-position']['Selected']:
|
||||||
|
settings_menu.options['--reverse']['Selected'] = False
|
||||||
|
input_position = std.string_to_bytes(
|
||||||
|
settings_menu.options['--input-position']['Value'],
|
||||||
|
)
|
||||||
|
domain_size -= input_position
|
||||||
|
cmd.append(f'--size={domain_size}')
|
||||||
|
|
||||||
|
# Determine skip sizes
|
||||||
|
if settings_menu.options['--skip-size']['Selected']:
|
||||||
|
skip_sizes = settings_menu.options['--skip-size']['Value'].split(',')
|
||||||
|
skip_sizes = [float(s) for s in skip_sizes]
|
||||||
|
initial_skip = min(INITIAL_SKIP_MIN, int(block_pair.size * skip_sizes[0]))
|
||||||
|
max_skip = min(int(block_pair.size * skip_sizes[1]), domain_size)
|
||||||
|
cmd.append(f'--skip-size={initial_skip},{max_skip}')
|
||||||
|
cmd.extend(get_ddrescue_settings(settings_menu))
|
||||||
|
|
||||||
|
# Add source physical sector size (if possible)
|
||||||
|
cmd.append(f'--sector-size={block_pair.source.details.get("phy-sec", 512)}')
|
||||||
|
|
||||||
|
# Add block pair and map file
|
||||||
if PLATFORM == 'Darwin':
|
if PLATFORM == 'Darwin':
|
||||||
# Use Raw disks if possible
|
# Use Raw disks if possible
|
||||||
for dev in (block_pair.source, block_pair.destination):
|
for dev in (block_pair.source, block_pair.destination):
|
||||||
|
|
@ -1569,6 +1592,8 @@ def get_ddrescue_settings(settings_menu):
|
||||||
|
|
||||||
# Check menu selections
|
# Check menu selections
|
||||||
for name, details in settings_menu.options.items():
|
for name, details in settings_menu.options.items():
|
||||||
|
if name == '--skip-size':
|
||||||
|
continue
|
||||||
if details['Selected']:
|
if details['Selected']:
|
||||||
if 'Value' in details:
|
if 'Value' in details:
|
||||||
settings.append(f'{name}={details["Value"]}')
|
settings.append(f'{name}={details["Value"]}')
|
||||||
|
|
@ -2130,7 +2155,6 @@ def run_recovery(state, main_menu, settings_menu, dry_run=True):
|
||||||
if 'Retry' in name and details['Selected']:
|
if 'Retry' in name and details['Selected']:
|
||||||
details['Selected'] = False
|
details['Selected'] = False
|
||||||
state.retry_all_passes()
|
state.retry_all_passes()
|
||||||
settings = get_ddrescue_settings(settings_menu)
|
|
||||||
|
|
||||||
# Start SMART/Journal
|
# Start SMART/Journal
|
||||||
state.panes['SMART'] = tmux.split_window(
|
state.panes['SMART'] = tmux.split_window(
|
||||||
|
|
@ -2158,7 +2182,7 @@ def run_recovery(state, main_menu, settings_menu, dry_run=True):
|
||||||
attempted_recovery = True
|
attempted_recovery = True
|
||||||
state.mark_started()
|
state.mark_started()
|
||||||
try:
|
try:
|
||||||
run_ddrescue(state, pair, pass_name, settings, dry_run=dry_run)
|
run_ddrescue(state, pair, pass_name, settings_menu, dry_run=dry_run)
|
||||||
except (FileNotFoundError, KeyboardInterrupt, std.GenericAbort):
|
except (FileNotFoundError, KeyboardInterrupt, std.GenericAbort):
|
||||||
is_missing_source_or_destination(state)
|
is_missing_source_or_destination(state)
|
||||||
abort = True
|
abort = True
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue