Added limited support for converting MBR/GPT types

This commit is contained in:
2Shirt 2020-01-02 19:54:18 -07:00
parent 6dc887b04e
commit 9702d7665f
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
2 changed files with 79 additions and 24 deletions

View file

@ -49,6 +49,18 @@ DDRESCUE_SETTINGS = {
'--timeout': {'Selected': False, 'Value': '30m', },
},
}
PARTITION_TYPES = {
'GPT': {
'NTFS': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', # Basic Data Partition
'VFAT': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', # Basic Data Partition
'EXFAT': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', # Basic Data Partition
},
'MBR': {
'EXFAT': 7, # 0x7
'NTFS': 7, # 0x7
'VFAT': 11, # 0xb
},
}
if __name__ == '__main__':

View file

@ -621,11 +621,6 @@ class State():
# Bail early
if not settings['Needs Format']:
return
print(f'{source_parts=}')
print(f'{working_dir=}')
print(f'{dry_run=}')
print(settings)
std.pause()
# Add partition table settings
if settings['Table Type'] == 'GPT':
@ -640,39 +635,46 @@ class State():
if settings['Table Type'] == 'GPT':
part_num += 1
sfdisk_script.append(
f'{dest_prefix}{part_num} : '
f'size=384MiB, type={esp_type}, name="EFI System"',
build_sfdisk_partition_line(
table_type='GPT',
dev_path=f'{dest_prefix}{part_num}',
size='384MiB',
details={'parttype': esp_type, 'partlabel': 'EFI System'},
),
)
part_num += 1
sfdisk_script.append(
f'{dest_prefix}{part_num} : '
f'size=16MiB, type={msr_type}, name="Microsoft Reserved"',
build_sfdisk_partition_line(
table_type=settings['Table Type'],
dev_path=f'{dest_prefix}{part_num}',
size='16MiB',
details={'parttype': msr_type, 'partlabel': 'Microsoft Reserved'},
),
)
elif settings['Table Type'] == 'MBR':
part_num += 1
sfdisk_script.append(
f'{dest_prefix}{part_num} : '
f'size=100MiB, type=7, name="System Reserved"',
build_sfdisk_partition_line(
table_type='MBR',
dev_path=f'{dest_prefix}{part_num}',
size='100MiB',
details={'parttype': '0x7', 'partlabel': 'System Reserved'},
),
)
# Add selected partition(s)
for part in source_parts:
line = ''
num_sectors = part.details['size'] / self.destination.details['log-sec']
num_sectors = math.ceil(num_sectors)
part_num += 1
# Build sfdisk line for part
# TODO: Move to separate function to support both DOS/GPT types
line = f'{dest_prefix}{part_num} : '
line += f'size={num_sectors}, type={part.details["parttype"].upper()}'
if part.details['partlabel']:
line += f', name="{part.details["partlabel"]}"'
if part.details['partuuid']:
line += f', uuid={part.details["partuuid"].upper()}'
# Add line to script
sfdisk_script.append(line)
sfdisk_script.append(
build_sfdisk_partition_line(
table_type=settings['Table Type'],
dev_path=f'{dest_prefix}{part_num}',
size=num_sectors,
details=part.details,
),
)
# Save sfdisk script
script_path = f'{working_dir}/sfdisk_{self.destination.path.name}.script'
@ -1129,6 +1131,47 @@ def build_settings_menu(silent=True):
return menu
def build_sfdisk_partition_line(table_type, dev_path, size, details):
"""Build sfdisk partition line using passed details, returns str."""
line = f'{dev_path} : size={size}'
dest_type = ''
source_filesystem = str(details.get('fstype', '')).upper()
source_table_type = ''
source_type = details.get('parttype', '')
# Set dest type
if re.match(r'^0x\w+$', source_type):
# Both source and dest are MBR
source_table_type = 'MBR'
if table_type == 'MBR':
dest_type = source_type.replace('0x', '').lower()
elif re.match(r'^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$', source_type):
# Source is a GPT type
source_table_type = 'GPT'
if table_type == 'GPT':
dest_type = source_type.upper()
if not dest_type:
# Assuming changing table types, set based on FS
if source_filesystem in cfg.ddrescue.PARTITION_TYPES[table_type]:
dest_type = cfg.ddrescue.PARTITION_TYPES[table_type][source_filesystem]
line += f', type={dest_type}'
# Safety Check
if not dest_type:
std.print_error(f'Failed to determine partition type for: {dev_path}')
raise std.GenericAbort()
# Add extra details
if details.get('partlabel', ''):
line += f', name="{details["partlabel"]}"'
if details.get('partuuid', '') and source_table_type == table_type:
# Only add UUID if source/dest table types match
line += f', uuid={details["partuuid"].upper()}'
# Done
return line
def clean_working_dir(working_dir):
"""Clean working directory to ensure a fresh recovery session.