diff --git a/scripts/wk/hw/ddrescue.py b/scripts/wk/hw/ddrescue.py index f9b0d023..e3433598 100644 --- a/scripts/wk/hw/ddrescue.py +++ b/scripts/wk/hw/ddrescue.py @@ -82,7 +82,9 @@ PANE_RATIOS = ( ) PLATFORM = std.PLATFORM RECOMMENDED_FSTYPES = re.compile(r'^(ext[234]|ntfs|xfs)$') -RECOMMENDED_MAP_FSTYPES = re.compile(r'^(cifs|ext[234]|ntfs|vfat|xfs)$') +RECOMMENDED_MAP_FSTYPES = re.compile( + r'^(apfs|cifs|ext[234]|hfs.?|ntfs|vfat|xfs)$' + ) SETTING_PRESETS = ( 'Default', 'Fast', @@ -725,6 +727,8 @@ class State(): self.update_progress_pane('Idle') self.confirm_selections('Start recovery?') + # TODO: Unmount source and/or destination under macOS + # Prep destination if self.mode == 'Clone': self.prep_destination(source_parts, dry_run=docopt_args['--dry-run']) @@ -1194,7 +1198,6 @@ def build_directory_report(path): line = f'{path:<{width}}{line}' report.append(line) else: - # TODO Get dir details under macOS report.append(std.color_string('PATH', 'BLUE')) report.append(str(path)) @@ -1447,8 +1450,11 @@ def fstype_is_ok(path, map_dir=False): # Get fstype if PLATFORM == 'Darwin': - # TODO: Determine fstype under macOS - pass + try: + fstype = get_fstype_macos(path) + except (IndexError, TypeError, ValueError): + # Ignore for now + pass elif PLATFORM == 'Linux': cmd = [ 'findmnt', @@ -1515,6 +1521,24 @@ def get_etoc(): return etoc +def get_fstype_macos(path): + """Get fstype for path under macOS, returns str. + + NOTE: This method is not very effecient. + """ + cmd = ['df', path] + + # Get device based on the path + proc = exe.run_program(cmd, check=False) + dev = proc.stdout.splitlines()[1].split()[0] + + # Get device details + dev = hw_obj.Disk(dev) + + # Done + return dev.details['fstype'] + + def get_object(path): """Get object based on path, returns obj.""" obj = None diff --git a/scripts/wk/hw/obj.py b/scripts/wk/hw/obj.py index a8719358..0c33296e 100644 --- a/scripts/wk/hw/obj.py +++ b/scripts/wk/hw/obj.py @@ -321,6 +321,7 @@ class Disk(BaseObj): self.details['bus'] = str(self.details.get('bus', '???')).upper() self.details['bus'] = self.details['bus'].replace('IMAGE', 'Image') self.details['bus'] = self.details['bus'].replace('NVME', 'NVMe') + self.details['fstype'] = self.details.get('fstype', 'Unknown') self.details['log-sec'] = self.details.get('log-sec', 512) self.details['model'] = self.details.get('model', 'Unknown Model') self.details['name'] = self.details.get('name', self.path) @@ -655,12 +656,15 @@ def get_disk_details_macos(path): dev['label'] = dev.pop('VolumeName', '') dev['model'] = dev.pop('MediaName', 'Unknown') dev['mountpoint'] = dev.pop('MountPoint', '') + dev['name'] = dev.get('name', str(dev['path'])) dev['phy-sec'] = dev.pop('DeviceBlockSize', 512) dev['serial'] = get_disk_serial_macos(dev['path']) dev['size'] = dev.pop('Size', -1) dev['ssd'] = dev.pop('SolidState', False) dev['vendor'] = '' - if not dev.get('WholeDisk', True): + if dev.get('WholeDisk', True): + dev['parent'] = None + else: dev['parent'] = dev.pop('ParentWholeDisk', None) # Done diff --git a/scripts/wk/kit/ufd.py b/scripts/wk/kit/ufd.py index 9c792b3b..483e2fbb 100644 --- a/scripts/wk/kit/ufd.py +++ b/scripts/wk/kit/ufd.py @@ -50,14 +50,11 @@ def build_ufd(): args = docopt(DOCSTRING) log.update_log_path(dest_name='build-ufd', timestamp=True) try_print = std.TryAndPrint() + try_print.add_error(FileNotFoundError) try_print.catch_all = False + try_print.verbose = True try_print.indent = 2 - # Check if running with root permissions - if not linux.running_as_root(): - std.print_error('This script is meant to be run as root') - std.abort() - # Show header std.print_success(KIT_NAME_FULL) std.print_warning('UFD Build Tool') @@ -195,6 +192,7 @@ def confirm_selections(update=False): def copy_source(source, items, overwrite=False): """Copy source items to /mnt/UFD.""" is_image = source.is_file() + items_not_found = False # Mount source if necessary if is_image: @@ -207,17 +205,20 @@ def copy_source(source, items, overwrite=False): try: io.recursive_copy(i_source, i_dest, overwrite=overwrite) except FileNotFoundError: - # Going to assume (hope) that this is fine - pass + items_not_found = True # Unmount source if necessary if is_image: linux.unmount('/mnt/Source') + # Raise exception if item(s) were not found + raise FileNotFoundError('One or more items not found') + def create_table(dev_path, use_mbr=False): """Create GPT or DOS partition table.""" cmd = [ + 'sudo', 'parted', dev_path, '--script', '--', @@ -254,6 +255,7 @@ def find_first_partition(dev_path): def format_partition(dev_path, label): """Format first partition on device FAT32.""" cmd = [ + 'sudo', 'mkfs.vfat', '-F', '32', '-n', label, @@ -287,13 +289,14 @@ def hide_items(ufd_dev, items): # Hide items for item in items: - cmd = [f'yes | mattrib +h "U:/{item}"'] - run_program(cmd, check=False, shell=True) + cmd = [f'yes | sudo mattrib +h "U:/{item}"'] + run_program(cmd, shell=True) def install_syslinux_to_dev(ufd_dev, use_mbr): """Install Syslinux to UFD (dev).""" cmd = [ + 'sudo', 'dd', 'bs=440', 'count=1', @@ -306,6 +309,7 @@ def install_syslinux_to_dev(ufd_dev, use_mbr): def install_syslinux_to_partition(partition): """Install Syslinux to UFD (partition).""" cmd = [ + 'sudo', 'syslinux', '--install', '--directory', @@ -335,6 +339,7 @@ def is_valid_path(path_obj, path_type): def set_boot_flag(dev_path, use_mbr=False): """Set modern or legacy boot flag.""" cmd = [ + 'sudo', 'parted', dev_path, 'set', '1', 'boot' if use_mbr else 'legacy_boot', @@ -410,6 +415,7 @@ def update_boot_entries(): # Use UUID instead of label cmd = [ + 'sudo', 'sed', '--in-place', '--regexp-extended', @@ -428,6 +434,7 @@ def update_boot_entries(): # Entry found, update config files cmd = [ + 'sudo', 'sed', '--in-place', f's/#{b_comment}#//', @@ -476,6 +483,7 @@ def verify_ufd(dev_path): def zero_device(dev_path): """Zero-out first 64MB of device.""" cmd = [ + 'sudo', 'dd', 'bs=4M', 'count=16', diff --git a/scripts/wk/std.py b/scripts/wk/std.py index b25b7b9f..c715706a 100644 --- a/scripts/wk/std.py +++ b/scripts/wk/std.py @@ -388,6 +388,7 @@ class Menu(): class TryAndPrint(): + # pylint: disable=too-many-instance-attributes """Object used to standardize running functions and returning the result. The errors and warning attributes are used to allow fine-tuned results @@ -396,11 +397,12 @@ class TryAndPrint(): def __init__(self, msg_bad='FAILED', msg_good='SUCCESS'): self.catch_all = True self.indent = INDENT - self.msg_bad = msg_bad - self.msg_good = msg_good - self.width = WIDTH self.list_errors = ['GenericError'] self.list_warnings = ['GenericWarning'] + self.msg_bad = msg_bad + self.msg_good = msg_good + self.verbose = False + self.width = WIDTH def _format_exception_message(self, _exception): """Format using the exception's args or name, returns str.""" @@ -525,13 +527,13 @@ class TryAndPrint(): def run( self, message, function, *args, - catch_all=None, msg_good=None, verbose=False, **kwargs): + catch_all=None, msg_good=None, verbose=None, **kwargs): # pylint: disable=catching-non-exception """Run a function and print the results, returns results as dict. If catch_all is True then (nearly) all exceptions will be caught. Otherwise if an exception occurs that wasn't specified it will be - re-raised. If passed it will override self.catch_all for this call. + re-raised. If the function returns data it will be used instead of msg_good, msg_bad, or exception text. @@ -542,6 +544,9 @@ class TryAndPrint(): If verbose is True then exception names or messages will be used for the result message. Otherwise it will simply be set to result_bad. + If catch_all and/or verbose are passed it will override + self.catch_all and/or self.verbose for this call. + args and kwargs are passed to the function. """ LOG.debug('function: %s.%s', function.__module__, function.__name__) @@ -558,6 +563,8 @@ class TryAndPrint(): result_msg = 'UNKNOWN' if catch_all is None: catch_all = self.catch_all + if verbose is None: + verbose = self.verbose # Build exception tuples e_exceptions = tuple(self._get_exception(e) for e in self.list_errors) diff --git a/setup/linux/include_x/airootfs/etc/skel/.config/openbox/menu.xml b/setup/linux/include_x/airootfs/etc/skel/.config/openbox/menu.xml index 2d560235..2e8fd4a2 100644 --- a/setup/linux/include_x/airootfs/etc/skel/.config/openbox/menu.xml +++ b/setup/linux/include_x/airootfs/etc/skel/.config/openbox/menu.xml @@ -234,7 +234,7 @@ - oblogout + wk-exit