"""Private durable journal and fail-closed cold-copy verification primitives.""" import hashlib import json import os from pathlib import Path import stat import tempfile def digest(data): return hashlib.sha256(data).hexdigest() def private_write(path, data): """Unique temporary files let explicit recovery proceed after process crashes.""" path = Path(path) if path.is_symlink(): raise ValueError("Refusing a symlink journal/configuration target") descriptor, temporary = tempfile.mkstemp(prefix=f".{path.name}-", dir=path.parent) with os.fdopen(descriptor, "wb") as stream: stream.write(data) stream.flush() os.fsync(stream.fileno()) os.replace(temporary, path) descriptor = os.open(path.parent, os.O_RDONLY) try: os.fsync(descriptor) finally: os.close(descriptor) def private_json(path, value): private_write(path, json.dumps(value, sort_keys=True).encode()) def dotenv(entries): """Do not guess escaping for unsupported environment values; never log them.""" import re result = {} for entry in entries: key, separator, value = entry.partition("=") if not separator or not re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*", key): raise ValueError("Unsupported runtime environment entry") if key in result or any(character in value for character in "\x00\n\r'\\"): raise ValueError("Runtime environment needs reviewed dotenv escaping") result[key] = value return "".join(f"{key}='{value}'\n" for key, value in sorted(result.items())).encode() def tree_manifest(root): """Hash content plus ownership/modes/xattrs; reject symlinks and special files. Preserving an unknown symlink could let the candidate write original data. Hardlink equivalence groups are compared without depending on inode numbers. """ root = Path(root) if root.is_symlink() or not root.is_dir(): raise ValueError("Cold-copy root must be a real directory") records = {} inodes = {} for path in [root, *sorted(root.rglob("*"))]: info = path.lstat() relative = str(path.relative_to(root)) if not stat.S_ISREG(info.st_mode) and not stat.S_ISDIR(info.st_mode): raise ValueError("Cold-copy tree contains an unreviewed symlink/special file") record = {"mode": stat.S_IMODE(info.st_mode), "uid": info.st_uid, "gid": info.st_gid} if stat.S_ISREG(info.st_mode): hasher = hashlib.sha256() with path.open("rb") as stream: for block in iter(lambda: stream.read(1024 * 1024), b""): hasher.update(block) record.update(kind="file", size=info.st_size, sha256=hasher.hexdigest()) group = (info.st_dev, info.st_ino) record["hardlink"] = inodes.setdefault(group, relative) else: record["kind"] = "directory" if hasattr(os, "listxattr"): record["xattrs"] = {name: digest(os.getxattr(path, name)) for name in sorted(os.listxattr(path))} records[relative] = record return records def clone_cold(source, target, runner): source, target = Path(source), Path(target) if target.exists() or target.is_symlink(): raise ValueError("Cold-copy target already exists") before = tree_manifest(source) target.parent.mkdir(parents=True, exist_ok=True, mode=0o700) # Destination does not exist: cp -a copies root metadata as well as children. runner(["cp", "-a", "--reflink=auto", "--", str(source), str(target)], timeout=3600) runner(["sync", "-f", "--", str(target)], timeout=3600) copied = tree_manifest(target) if before != copied or before != tree_manifest(source): raise ValueError("Cold copy content/metadata does not match unchanged original") return digest(json.dumps(before, sort_keys=True).encode())