diff --git a/melamine/shred.py b/melamine/shred.py index 370f0d3..0bf3ce5 100644 --- a/melamine/shred.py +++ b/melamine/shred.py @@ -33,7 +33,8 @@ async def main(job: argparse.Namespace) -> bool: job.paths = await get_all_hardlinks(new_paths) tasks = [path.absolute() for path in job.ignoredir] - tasks.append(AsyncPath("/proc").absolute()) + for path in ["/proc", "/dev", "/sys"]: + tasks.append(AsyncPath(path).absolute()) job.ignoredir = set(await asyncio.gather(*tasks)) # Shred all physical files including hardlinks @@ -72,10 +73,25 @@ async def main(job: argparse.Namespace) -> bool: for mount_point, inodes in inodes_in_mount_points.items(): # checking for . and .. should not be neccessary w/ rglob tasks = [] - async for item in mount_point.rglob("*"): - if any(str(item).startswith(str(path)) for path in job.ignoredir): - continue - tasks.append(check_inode_and_unlink(item, inodes)) + # scandir/glob/rglob doesn't play nice with FileNotFound errors, + # so let's avoid them entirely for now in /proc, /dev, and /sys + if any((mount_point / path).exists() for path in ("/proc", "/dev", "/sys")): + # Traverse every directory in mount_point recursively except /proc, /dev, and /sys + async for item in mount_point.glob("*"): + if await item.is_dir(): + if str(item) in ("proc", "dev", "sys"): + continue + async for subitem in item.rglob("*"): + if any(str(subitem).startswith(str(path)) for path in job.ignoredir): + continue + tasks.append(check_inode_and_unlink(subitem, inodes)) + else: + tasks.append(check_inode_and_unlink(item, inodes)) + else: + async for item in mount_point.rglob("*"): + if any(str(item).startswith(str(path)) for path in job.ignoredir): + continue + tasks.append(check_inode_and_unlink(item, inodes)) done, _ = await asyncio.wait(tasks) for task in done: e = task.exception()