112 lines
2.7 KiB
Python
112 lines
2.7 KiB
Python
from pathlib import Path
|
|
import argparse
|
|
import errno
|
|
import os
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
|
|
mounts = {}
|
|
|
|
|
|
class RarMount:
|
|
process = None
|
|
|
|
@property
|
|
def mountpoint(self):
|
|
result = self.mount_root / self.rar_file.relative_to(self.rar_root).parent
|
|
return result
|
|
|
|
def __init__(self, mount_root: str, rar_file: Path, rar_root: Path):
|
|
self.mount_root = mount_root
|
|
self.rar_file = rar_file
|
|
self.rar_root = rar_root
|
|
|
|
os.makedirs(self.mountpoint, exist_ok=True)
|
|
|
|
print(f"Mounting '{self.rar_file}' at '{self.mountpoint}'")
|
|
self.process = subprocess.Popen(
|
|
[
|
|
"rar2fs",
|
|
"-f",
|
|
"-o",
|
|
"auto_unmount",
|
|
"-o",
|
|
"allow_other",
|
|
"--no-inherit-perm",
|
|
self.rar_file,
|
|
self.mountpoint,
|
|
]
|
|
)
|
|
|
|
def __del__(self):
|
|
if self.process:
|
|
self.process.terminate()
|
|
self.process.communicate()
|
|
|
|
for i in range(10):
|
|
try:
|
|
os.rmdir(self.mountpoint)
|
|
except FileNotFoundError:
|
|
pass
|
|
except OSError as ex:
|
|
# if ex.errno == errno.ENOEMPTY:
|
|
# break
|
|
if ex.errno == errno.EBUSY:
|
|
time.sleep(1)
|
|
raise
|
|
else:
|
|
break
|
|
|
|
for dir in self.mountpoint.relative_to(self.mount_root).parents:
|
|
try:
|
|
os.rmdir(self.mount_root.joinpath(dir))
|
|
except OSError as ex:
|
|
pass
|
|
|
|
|
|
def signal_handler(sig, frame):
|
|
for rar_file, mount in mounts.items():
|
|
del mount
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(
|
|
description="Recursively globs a path containing rar files and mounts them under a given mount path."
|
|
)
|
|
|
|
parser.add_argument("rar_path", type=Path, help="Path to the RAR directory")
|
|
|
|
parser.add_argument("mount_path", type=Path, help="Path to the mount directory")
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def main():
|
|
args = parse_args()
|
|
|
|
if not args.rar_path.is_dir():
|
|
parser.error(f"RAR path '{args.rar_path}' is not a valid directory.")
|
|
|
|
signal.signal(signal.SIGINT, signal_handler)
|
|
|
|
for rar_file in args.rar_path.rglob("*.rar"):
|
|
if rar_file in mounts:
|
|
continue
|
|
if len(rar_file.parts) >= 2 and rar_file.parts[-2].lower() in ["subs", "proof"]:
|
|
continue
|
|
|
|
mounts[rar_file] = RarMount(args.mount_path, rar_file, args.rar_path)
|
|
|
|
while True:
|
|
time.sleep(600)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|