mirror of
https://github.com/DarrylNixon/melamine.git
synced 2024-04-22 06:27:20 -07:00
ext2/3 is hard, use find as backup
This commit is contained in:
parent
155b3e2006
commit
068d47703a
2 changed files with 36 additions and 3 deletions
|
@ -35,6 +35,7 @@ class ShredDir(AsyncObject):
|
||||||
self.mount_points.add(self.mount_point)
|
self.mount_points.add(self.mount_point)
|
||||||
self.fs_handler = await mount_to_fs_handler(self.mount_point)
|
self.fs_handler = await mount_to_fs_handler(self.mount_point)
|
||||||
self.byte_size = sum(item.byte_size for item in self.contents)
|
self.byte_size = sum(item.byte_size for item in self.contents)
|
||||||
|
self.inode = path.stat().st_ino
|
||||||
|
|
||||||
async def _get_contents(self) -> List:
|
async def _get_contents(self) -> List:
|
||||||
contents = []
|
contents = []
|
||||||
|
@ -63,13 +64,30 @@ class ShredDir(AsyncObject):
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
return hash(self.absolute_path)
|
return hash(self.absolute_path)
|
||||||
|
|
||||||
|
async def delete_hardlinks_by_inode(self) -> None:
|
||||||
|
logger.info(f"Finding and deleting hardlinks inside {self.absolute_path.name}")
|
||||||
|
for path in self.contents:
|
||||||
|
await path.delete_hardlinks_by_inode()
|
||||||
|
|
||||||
|
proc = await asyncio.create_subprocess_exec("find", str(self.mount_point), "-inum", self.get_inode(), "-delete")
|
||||||
|
stdout, _ = await proc.communicate()
|
||||||
|
|
||||||
|
if proc.returncode != 0:
|
||||||
|
err = f"Unable to delete hardlinks for {self.absolute_path.name}"
|
||||||
|
logger.error(err)
|
||||||
|
raise RuntimeError(err)
|
||||||
|
|
||||||
|
logger.info(f"Deleted hardlink for {self.absolute_path.name}")
|
||||||
|
|
||||||
|
|
||||||
class ShredFile(AsyncObject):
|
class ShredFile(AsyncObject):
|
||||||
"""Class for tracking each file to be shredded."""
|
"""Class for tracking each file to be shredded."""
|
||||||
|
|
||||||
async def __init__(self, path: Path) -> None:
|
async def __init__(self, path: Path) -> None:
|
||||||
self.absolute_path = path.resolve().absolute()
|
self.absolute_path = path.resolve().absolute()
|
||||||
self.byte_size = path.stat().st_size
|
stat = path.stat()
|
||||||
|
self.byte_size = stat.st_size
|
||||||
|
self.inode = stat.st_ino
|
||||||
self.mount_point = find_mount(self.absolute_path)
|
self.mount_point = find_mount(self.absolute_path)
|
||||||
self.fs_handler = await mount_to_fs_handler(self.mount_point)
|
self.fs_handler = await mount_to_fs_handler(self.mount_point)
|
||||||
self.hardlinks = None
|
self.hardlinks = None
|
||||||
|
@ -145,6 +163,17 @@ class ShredFile(AsyncObject):
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
return hash(self.absolute_path)
|
return hash(self.absolute_path)
|
||||||
|
|
||||||
|
async def delete_hardlinks_by_inode(self) -> None:
|
||||||
|
proc = await asyncio.create_subprocess_exec("find", str(self.mount_point), "-inum", self.get_inode(), "-delete")
|
||||||
|
stdout, _ = await proc.communicate()
|
||||||
|
|
||||||
|
if proc.returncode != 0:
|
||||||
|
err = f"Unable to delete hardlinks for {self.absolute_path.name}"
|
||||||
|
logger.error(err)
|
||||||
|
raise RuntimeError(err)
|
||||||
|
|
||||||
|
logger.info("Deleted hardlink for {self.absolute_path.name}")
|
||||||
|
|
||||||
|
|
||||||
async def get_all_hardlinks(paths: Set[Union[ShredFile, ShredDir]]) -> None:
|
async def get_all_hardlinks(paths: Set[Union[ShredFile, ShredDir]]) -> None:
|
||||||
for path in paths:
|
for path in paths:
|
||||||
|
|
|
@ -12,7 +12,6 @@ async def main(job: argparse.Namespace) -> bool:
|
||||||
It is called by the CLI and builds a job queue based on the arguments passed.
|
It is called by the CLI and builds a job queue based on the arguments passed.
|
||||||
"""
|
"""
|
||||||
new_paths = set()
|
new_paths = set()
|
||||||
logger.info(f"job type is {type(job)}")
|
|
||||||
|
|
||||||
# Expand all directories and files, and collect mount point information
|
# Expand all directories and files, and collect mount point information
|
||||||
for path in job.paths:
|
for path in job.paths:
|
||||||
|
@ -28,9 +27,14 @@ async def main(job: argparse.Namespace) -> bool:
|
||||||
else:
|
else:
|
||||||
raise TypeError(f"Not a file or directory: {path}")
|
raise TypeError(f"Not a file or directory: {path}")
|
||||||
|
|
||||||
# Get hardlinks to subsequently unlink for all files
|
# Try to delete hardlinks based on the filesystem type
|
||||||
job.paths = await get_all_hardlinks(new_paths)
|
job.paths = await get_all_hardlinks(new_paths)
|
||||||
|
|
||||||
|
# Just in case, use "find" to delete any remaining hardlinks
|
||||||
|
# from the mount point
|
||||||
|
for path in job.paths:
|
||||||
|
await path.delete_hardlinks_by_inode()
|
||||||
|
|
||||||
# Shred all physical files including hardlinks
|
# Shred all physical files including hardlinks
|
||||||
for path in job.paths:
|
for path in job.paths:
|
||||||
if isinstance(path, ShredFile):
|
if isinstance(path, ShredFile):
|
||||||
|
|
Loading…
Reference in a new issue