#!/usr/bin/env python3 """Набор почти полного HDD для проверки ENOSPC и удаления copy-temp.""" from __future__ import annotations import pathlib import sys SOURCE_SIZE = 262_181 FILLER_SIZE = 32_850_000 def source_content() -> bytes: return bytes(((index * 37 + (index >> 8) * 11 + 0xA7) & 0xFF) for index in range(SOURCE_SIZE)) def write_filler(path: pathlib.Path) -> None: chunk = bytes(((index * 17 + 0x53) & 0xFF) for index in range(65536)) remaining = FILLER_SIZE with path.open("wb") as stream: while remaining: part = min(remaining, len(chunk)) stream.write(chunk[:part]) remaining -= part def create(root: pathlib.Path) -> None: source = root / "SOURCE" target = root / "TARGET" source.mkdir(parents=True) target.mkdir(parents=True) (source / "FULL.BIN").write_bytes(source_content()) write_filler(root / "FILLER.BIN") def verify_initial(root: pathlib.Path) -> None: failures = [] source = root / "SOURCE" / "FULL.BIN" target = root / "TARGET" filler = root / "FILLER.BIN" if not source.is_file() or source.read_bytes() != source_content(): failures.append("повреждён SOURCE/FULL.BIN") if not filler.is_file() or filler.stat().st_size != FILLER_SIZE: failures.append("неверный FILLER.BIN") if not target.is_dir() or list(target.iterdir()): failures.append("TARGET не пуст до теста") if failures: for failure in failures: print(f"FAIL: {failure}") raise SystemExit(1) print("PASS: ENOSPC fixture готов, SOURCE/FULL.BIN сохранён.") def verify(root: pathlib.Path) -> None: failures = [] source = root / "SOURCE" / "FULL.BIN" target = root / "TARGET" filler = root / "FILLER.BIN" if not source.is_file() or source.read_bytes() != source_content(): failures.append("исходный FULL.BIN изменён") if not filler.is_file() or filler.stat().st_size != FILLER_SIZE: failures.append("FILLER.BIN изменён") if (target / "FULL.BIN").exists(): failures.append("после ENOSPC остался конечный TARGET/FULL.BIN") temporaries = sorted(target.glob("~SC*.TMP")) if temporaries: failures.append("после ENOSPC остался временный файл") if failures: for failure in failures: print(f"FAIL: {failure}") raise SystemExit(1) print("PASS: ENOSPC не изменил source/filler и не оставил target/temp.") def main() -> None: commands = {"create", "verify-initial", "verify"} if len(sys.argv) != 3 or sys.argv[1] not in commands: raise SystemExit( f"usage: {sys.argv[0]} create|verify-initial|verify DIR") root = pathlib.Path(sys.argv[2]) if sys.argv[1] == "create": create(root) elif sys.argv[1] == "verify-initial": verify_initial(root) else: verify(root) if __name__ == "__main__": main()