diff --git a/udib/modiso.py b/udib/modiso.py index 7400077..23a754a 100644 --- a/udib/modiso.py +++ b/udib/modiso.py @@ -9,11 +9,49 @@ local filesystem. from pathlib import Path import gzip +import hashlib import re import shutil import subprocess +def _find_all_files_under(parent_dir): + """Recursively finds all files anywhere under the specified directory. + + Returns a list of absolute Path objects. Symlinks are ignored. + + Parameters + ---------- + parent_dir : str or pathlike object + The directory under which to recursively find files. + + Raises + ------ + NotADirectoryError + Raised if the specified parent directory is not a directory. + + Examples + -------- + config_files = _find_all_files_under("~/.config") + + """ + + parent_dir = Path(parent_dir).resolve() + + if not parent_dir.is_dir(): + raise NotADirectoryError(f"No such directory: '{parent_dir}'.") + + files = [] + + for subpath in parent_dir.iterdir(): + if subpath.is_file(): + files.append(subpath.resolve()) + elif not subpath.is_symlink() and subpath.is_dir(): + files += _find_all_files_under(subpath) + + return files + + def extract_iso(path_to_output_dir, path_to_input_file): """Extracts the contents of the ISO-file into the specified directory. @@ -174,7 +212,7 @@ def regenerate_iso_md5sums_file(path_to_extracted_iso_root): """ - path_to_extracted_iso_root = Path(path_to_extracted_iso_root) + path_to_extracted_iso_root = Path(path_to_extracted_iso_root).resolve() # check if input path exists if not path_to_extracted_iso_root.is_dir(): diff --git a/udib/udib.py b/udib/udib.py index 0cdcf1d..08e316f 100755 --- a/udib/udib.py +++ b/udib/udib.py @@ -36,14 +36,7 @@ def _assert_system_dependencies_installed(): # contains the names of all unix program dependencies which must be # installed on the local system and available in the local system's $PATH system_programs_required = [ - "chmod", "cpio", - "dd", - "find", - "gunzip", - "gzip", - "md5sum", - "xargs", "xorriso", ] @@ -110,6 +103,55 @@ def _get_argument_parser(): return parser +def _chmod_recursively(input_path, mode): + """Recursively changes file permissions on the specified path. + + The file and directory permissions for the specified path itself, + as well as any files and directories anywhere below it are set to + the specified mode. + Symlinks are ignored. + + Parameters + ---------- + input_path : str or pathlike object + Path of which to change the permissions recursively. + mode : int + Permission mode as accepted by os.chmod() + + Raises + ------ + ValueError + Raised if the specified path points to a nonexisting + filesystem node, or if the specified permission mode is + invalid. + TypeError + Raised if mode is not an integer. + + Examples + -------- + _chmod_recursively("/tmp/mydir", 0o755) + + """ + + input_path = Path(input_path) + + if not input_path.exists(): + raise ValueError(f"Path does not exist: '{input_path}'.") + + if not isinstance(mode, int): + raise TypeError("Expected type 'int' for parameter 'mode'.") + if mode not in range(0, 0o1000): + raise ValueError("Invalid mode.") + + if not input_path.is_symlink(): + input_path.chmod(mode) + for child in input_path.iterdir(): + if not child.is_symlink(): + child.chmod(mode) + if child.is_dir(): + _chmod_recursively(child, mode) + + def main(): # FIXME capture ISO filesystem name @@ -270,7 +312,9 @@ def main(): # remove temporary directories p.info("Cleaning up...") + _chmod_recursively(path_to_extracted_iso_dir, 0o755) shutil.rmtree(path_to_extracted_iso_dir) + _chmod_recursively(path_to_mbr.parent, 0o755) shutil.rmtree(path_to_mbr.parent) p.success(f"Wrote the modified ISO to '{path_to_output_file}'.")