From b3b821a8689849e540350df722678431e7f01db5 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 26 Nov 2018 18:12:24 -0700 Subject: [PATCH] Allow mounting all volumes per device --- .bin/Scripts/functions/data.py | 56 +++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/.bin/Scripts/functions/data.py b/.bin/Scripts/functions/data.py index c8eec384..029c674b 100644 --- a/.bin/Scripts/functions/data.py +++ b/.bin/Scripts/functions/data.py @@ -126,11 +126,11 @@ def cleanup_transfer(dest_path): if not os.path.exists(dest_path): # Bail if dest_path was empty and removed raise Exception - + # Fix attributes cmd = ['attrib', '-a', '-h', '-r', '-s', dest_path] run_program(cmd, check=False) - + for root, dirs, files in os.walk(dest_path, topdown=False): for name in dirs: # Remove empty directories and junction points @@ -153,7 +153,7 @@ def cleanup_transfer(dest_path): except Exception: pass -def find_core_storage_volumes(): +def find_core_storage_volumes(device_path=None): """Try to create block devices for any Apple CoreStorage volumes.""" corestorage_uuid = '53746f72-6167-11aa-aa11-00306543ecac' dmsetup_cmd_file = '{TmpDir}/dmsetup_command'.format(**global_vars) @@ -162,6 +162,8 @@ def find_core_storage_volumes(): cmd = [ 'lsblk', '--json', '--list', '--paths', '--output', 'NAME,PARTTYPE'] + if device_path: + cmd.append(device_path) result = run_program(cmd) json_data = json.loads(result.stdout.decode()) devs = json_data.get('blockdevices', []) @@ -248,7 +250,9 @@ def get_mounted_volumes(): mounted_volumes.extend(item.get('children', [])) return {item['source']: item for item in mounted_volumes} -def mount_volumes(all_devices=True, device_path=None, read_write=False): +def mount_volumes( + all_devices=True, device_path=None, + read_write=False, core_storage=True): """Mount all detected filesystems.""" report = {} cmd = [ @@ -257,9 +261,10 @@ def mount_volumes(all_devices=True, device_path=None, read_write=False): if not all_devices and device_path: # Only mount volumes for specific device cmd.append(device_path) - else: - # Check for Apple CoreStorage volumes first - find_core_storage_volumes() + + # Check for Apple CoreStorage volumes first + if core_storage: + find_core_storage_volumes(device_path) # Get list of block devices result = run_program(cmd) @@ -269,11 +274,14 @@ def mount_volumes(all_devices=True, device_path=None, read_write=False): # Get list of volumes volumes = {} for dev in devs: + if not dev.get('children', []): + volumes.update({dev['name']: dev}) for child in dev.get('children', []): - volumes.update({child['name']: child}) + if not child.get('children', []): + volumes.update({child['name']: child}) for grandchild in child.get('children', []): volumes.update({grandchild['name']: grandchild}) - + # Get list of mounted volumes mounted_volumes = get_mounted_volumes() @@ -352,7 +360,7 @@ def mount_backup_shares(read_write=False): if server['Mounted']: print_warning(mounted_str) continue - + mount_network_share(server, read_write) def mount_network_share(server, read_write=False): @@ -414,12 +422,12 @@ def run_fast_copy(items, dest): """Copy items to dest using FastCopy.""" if not items: raise Exception - + cmd = [global_vars['Tools']['FastCopy'], *FAST_COPY_ARGS] - cmd.append(r'/logfile={}\FastCopy.log'.format(global_vars['LogDir'])) + cmd.append(r'/logfile={LogDir}\Tools\FastCopy.log'.format(**global_vars)) cmd.extend(items) cmd.append('/to={}\\'.format(dest)) - + run_program(cmd) def run_wimextract(source, items, dest): @@ -486,7 +494,7 @@ def list_source_items(source_obj, rel_path=None): def scan_source(source_obj, dest_path, rel_path='', interactive=True): """Scan source for files/folders to transfer, returns list. - + This will scan the root and (recursively) any Windows.old folders.""" selected_items = [] win_olds = [] @@ -563,7 +571,7 @@ def scan_source(source_obj, dest_path, rel_path='', interactive=True): '{}{}{}'.format(dest_path, os.sep, old.name), rel_path=old.name, interactive=False)) - + # Done return selected_items @@ -707,7 +715,7 @@ def select_source(backup_prefix): item.name, # Image file ), 'Source': item}) - + # Check for local sources print_standard('Scanning for local sources...') set_thread_error_mode(silent=True) # Prevents "No disk" popups @@ -747,7 +755,7 @@ def select_source(backup_prefix): ' Local', d.mountpoint, item.name), 'Sort': r'{}{}'.format(d.mountpoint, item.name), 'Source': item}) - + set_thread_error_mode(silent=False) # Return to normal # Build Menu @@ -775,7 +783,7 @@ def select_source(backup_prefix): umount_backup_shares() pause("Press Enter to exit...") exit_script() - + # Sanity check if selected_source.is_file(): # Image-Based @@ -783,7 +791,7 @@ def select_source(backup_prefix): print_error('ERROR: Unsupported image: {}'.format( selected_source.path)) raise GenericError - + # Done return selected_source @@ -791,7 +799,7 @@ def select_volume(title='Select disk', auto_select=True): """Select disk from attached disks. returns dict.""" actions = [{'Name': 'Quit', 'Letter': 'Q'}] disks = [] - + # Build list of disks set_thread_error_mode(silent=True) # Prevents "No disk" popups for d in psutil.disk_partitions(): @@ -812,11 +820,11 @@ def select_volume(title='Select disk', auto_select=True): info['Display Name'] = '{} ({})'.format(info['Name'], free) disks.append(info) set_thread_error_mode(silent=False) # Return to normal - + # Skip menu? if len(disks) == 1 and auto_select: return disks[0] - + # Show menu selection = menu_select(title, main_entries=disks, action_entries=actions) if selection == 'Q': @@ -826,12 +834,12 @@ def select_volume(title='Select disk', auto_select=True): def set_thread_error_mode(silent=True): """Disable or Enable Windows error message dialogs. - + Disable when scanning for disks to avoid popups for empty cardreaders, etc """ # Code borrowed from: https://stackoverflow.com/a/29075319 kernel32 = ctypes.WinDLL('kernel32') - + if silent: kernel32.SetThreadErrorMode(SEM_FAIL, ctypes.byref(SEM_NORMAL)) else: