A Python port of the Invisible Internet Project (I2P)
at main 84 lines 2.1 kB view raw
1"""File utility operations. 2 3Copy, delete, zip extraction, checksums, read/write. 4 5Ported from net.i2p.util.FileUtil. 6""" 7 8from __future__ import annotations 9 10import hashlib 11import os 12import shutil 13import zipfile 14 15 16def copy_file(src: str, dst: str) -> bool: 17 """Copy a file. Returns True on success.""" 18 try: 19 shutil.copy2(src, dst) 20 return True 21 except (OSError, FileNotFoundError): 22 return False 23 24 25def rm_dir(path: str, recursive: bool = True) -> bool: 26 """Remove a directory. Returns True on success.""" 27 try: 28 if recursive: 29 shutil.rmtree(path) 30 else: 31 os.rmdir(path) 32 return True 33 except (OSError, FileNotFoundError): 34 return False 35 36 37def extract_zip(zip_path: str, dest_dir: str) -> bool: 38 """Extract a ZIP archive to dest_dir. Returns True on success.""" 39 try: 40 with zipfile.ZipFile(zip_path, "r") as zf: 41 zf.extractall(dest_dir) 42 return True 43 except (zipfile.BadZipFile, OSError): 44 return False 45 46 47def verify_zip(zip_path: str) -> bool: 48 """Verify a ZIP archive is valid.""" 49 try: 50 with zipfile.ZipFile(zip_path, "r") as zf: 51 return zf.testzip() is None 52 except (zipfile.BadZipFile, OSError): 53 return False 54 55 56def file_checksum(path: str, algorithm: str = "sha256") -> str | None: 57 """Compute hex checksum of a file. Returns None on error.""" 58 try: 59 h = hashlib.new(algorithm) 60 with open(path, "rb") as f: 61 for chunk in iter(lambda: f.read(65536), b""): 62 h.update(chunk) 63 return h.hexdigest() 64 except (OSError, ValueError): 65 return None 66 67 68def read_file(path: str) -> bytes | None: 69 """Read file contents. Returns None on error.""" 70 try: 71 with open(path, "rb") as f: 72 return f.read() 73 except OSError: 74 return None 75 76 77def write_file(path: str, data: bytes) -> bool: 78 """Write data to file. Returns True on success.""" 79 try: 80 with open(path, "wb") as f: 81 f.write(data) 82 return True 83 except OSError: 84 return False