|
2 | 2 | #
|
3 | 3 | # SPDX-License-Identifier: GPL-3.0-only
|
4 | 4 | #
|
5 |
| -# ghetto-purge.py v0.0.2 |
| 5 | +# ghetto-purge.py v0.0.3 |
6 | 6 | #
|
7 | 7 | # Read files and directories from an input file, one per line, and attempt to
|
8 | 8 | # remove them from the GlusterFS brick along with their .glusterfs links. This
|
@@ -32,18 +32,12 @@ def main():
|
32 | 32 | # Note that we have to remove \n from the line
|
33 | 33 | path_to_analyze = f"{brick_path}/{line.strip()}"
|
34 | 34 |
|
35 |
| - # To be safe I check if this is a symlink first, because we only |
36 |
| - # want to process entries named in our input file and not follow them |
37 |
| - # all over the file system. I am not sure how to deal with these yet... |
38 |
| - # pathlib's exists() will follow symlinks and return False if they are |
39 |
| - # broken, for example (note that pathlib's is_dir() is different than |
40 |
| - # os.is_dir(), and the latter has follow_symlinks(false)). |
41 |
| - if Path(f"{path_to_analyze}").is_symlink(): |
42 |
| - print(f"Skipping symlink: {path_to_analyze}") |
43 |
| - |
44 |
| - continue |
45 |
| - |
46 |
| - if Path(f"{path_to_analyze}").exists(): |
| 35 | + # Pathlib's Path.exists() will return false if the path is a broken |
| 36 | + # symlink so we need to check for the symlink case here as well. |
| 37 | + if ( |
| 38 | + Path(f"{path_to_analyze}").exists() |
| 39 | + or Path(f"{path_to_analyze}").is_symlink() |
| 40 | + ): |
47 | 41 | if Path(f"{path_to_analyze}").is_dir():
|
48 | 42 | if args.debug:
|
49 | 43 | print(f"Descend into: {path_to_analyze}")
|
@@ -122,8 +116,22 @@ def process_file(brick_path, path):
|
122 | 116 | if args.debug:
|
123 | 117 | print(f"Processing file: {path}")
|
124 | 118 |
|
125 |
| - # Get a string representation of the xattr from hex bytes |
126 |
| - file_gfid = os.getxattr(path, "trusted.gfid").hex() |
| 119 | + # Try to get a string representation of the xattr from hex bytes. We need |
| 120 | + # to try/except because os.getxattr() returns FileNotFoundError when the |
| 121 | + # file is a broken symlink, and OSError when the link goes somewhere that |
| 122 | + # does not have GlusterFS metadata. This happens in the case of eg Python |
| 123 | + # virtual environments in user's home directories and it is not a problem |
| 124 | + # to remove it and return without trying to remove a .glusterfs hard link. |
| 125 | + try: |
| 126 | + file_gfid = os.getxattr(path, "trusted.gfid").hex() |
| 127 | + except (FileNotFoundError, OSError): |
| 128 | + if not args.dry_run: |
| 129 | + os.remove(path) |
| 130 | + |
| 131 | + print(f'{"(DRY RUN) " if args.dry_run else ""}Removed symlink: {path}') |
| 132 | + |
| 133 | + return |
| 134 | + |
127 | 135 | file_glusterfs_path = dot_glusterfs_path(brick_path, file_gfid)
|
128 | 136 |
|
129 | 137 | if Path(path).exists():
|
|
0 commit comments