nixos-configuration/hosts/iron/services/jellyfin/rar2fs_mounts.py
2025-10-06 20:32:51 +02:00

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())