"""File utility operations. Copy, delete, zip extraction, checksums, read/write. Ported from net.i2p.util.FileUtil. """ from __future__ import annotations import hashlib import os import shutil import zipfile def copy_file(src: str, dst: str) -> bool: """Copy a file. Returns True on success.""" try: shutil.copy2(src, dst) return True except (OSError, FileNotFoundError): return False def rm_dir(path: str, recursive: bool = True) -> bool: """Remove a directory. Returns True on success.""" try: if recursive: shutil.rmtree(path) else: os.rmdir(path) return True except (OSError, FileNotFoundError): return False def extract_zip(zip_path: str, dest_dir: str) -> bool: """Extract a ZIP archive to dest_dir. Returns True on success.""" try: with zipfile.ZipFile(zip_path, "r") as zf: zf.extractall(dest_dir) return True except (zipfile.BadZipFile, OSError): return False def verify_zip(zip_path: str) -> bool: """Verify a ZIP archive is valid.""" try: with zipfile.ZipFile(zip_path, "r") as zf: return zf.testzip() is None except (zipfile.BadZipFile, OSError): return False def file_checksum(path: str, algorithm: str = "sha256") -> str | None: """Compute hex checksum of a file. Returns None on error.""" try: h = hashlib.new(algorithm) with open(path, "rb") as f: for chunk in iter(lambda: f.read(65536), b""): h.update(chunk) return h.hexdigest() except (OSError, ValueError): return None def read_file(path: str) -> bytes | None: """Read file contents. Returns None on error.""" try: with open(path, "rb") as f: return f.read() except OSError: return None def write_file(path: str, data: bytes) -> bool: """Write data to file. Returns True on success.""" try: with open(path, "wb") as f: f.write(data) return True except OSError: return False