| """ |
| neural-vault CLI. Dependency-free except `mount` (needs WinFsp + winfspy). |
| |
| store <vault> <src_folder> [--k K --m M] ingest a folder (dedup + RS) |
| ls <vault> list stored files |
| stat <vault> dedup / redundancy stats |
| export <vault> <dst_folder> reconstruct all files (RS-healed) |
| heal <vault> regenerate any missing shards |
| mount <vault> <mountpoint> expose as a drive (WinFsp) |
| |
| image <device> <out.pt> [--k --m --part-mb] scan a whole drive/partition |
| (e.g. \\\\.\\C: or an .img, may need admin) into a self-healing .pt |
| image-verify <out.pt> report archive health |
| image-heal <out.pt> repair detected bit-rot |
| image-restore <out.pt> <out.img> reconstruct the image bit-exact |
| """ |
| import argparse |
| from storage.vault import Vault |
| from storage.vaultfs import winfsp_available |
| from storage import diskimage |
|
|
|
|
| def main(): |
| ap = argparse.ArgumentParser(prog="neural-vault") |
| sub = ap.add_subparsers(dest="cmd", required=True) |
| p = sub.add_parser("store"); p.add_argument("vault"); p.add_argument("src") |
| p.add_argument("--k", type=int, default=4); p.add_argument("--m", type=int, default=2) |
| for name in ("ls", "stat", "heal"): |
| q = sub.add_parser(name); q.add_argument("vault") |
| e = sub.add_parser("export"); e.add_argument("vault"); e.add_argument("dst") |
| mo = sub.add_parser("mount"); mo.add_argument("vault"); mo.add_argument("mountpoint") |
| im = sub.add_parser("image"); im.add_argument("device"); im.add_argument("out") |
| im.add_argument("--k", type=int, default=4); im.add_argument("--m", type=int, default=2) |
| im.add_argument("--part-mb", type=int, default=64); im.add_argument("--label") |
| iv = sub.add_parser("image-verify"); iv.add_argument("out") |
| ih = sub.add_parser("image-heal"); ih.add_argument("out") |
| ir = sub.add_parser("image-restore"); ir.add_argument("out"); ir.add_argument("dst") |
| args = ap.parse_args() |
|
|
| if args.cmd == "store": |
| v = Vault(args.vault, args.k, args.m) |
| v.store_folder(args.src) |
| s = v.stats() |
| print(f"stored {len(v.list_files())} files, {s['unique_chunks']} unique chunks, " |
| f"{s['stored']//1024} KB on disk ({s['overhead']:.2f}x, RS {args.k}+{args.m})") |
| elif args.cmd == "ls": |
| for rel, sz in Vault(args.vault).list_files(): |
| print(f"{sz:>10} {rel}") |
| elif args.cmd == "stat": |
| s = Vault(args.vault).stats() |
| print(f"logical {s['logical']//1024} KB | stored {s['stored']//1024} KB | " |
| f"{s['unique_chunks']} chunks | overhead {s['overhead']:.2f}x") |
| elif args.cmd == "heal": |
| print(f"regenerated {Vault(args.vault).heal()} missing shard(s)") |
| elif args.cmd == "export": |
| print(f"exported {Vault(args.vault).export(args.dst)} files") |
| elif args.cmd == "mount": |
| if not winfsp_available(): |
| print("WinFsp/winfspy not installed. Install WinFsp (https://winfsp.dev) " |
| "and `pip install winfspy`, or use `export` for now.") |
| return |
| from storage.vaultfs import mount |
| fs = mount(Vault(args.vault), args.mountpoint) |
| print(f"mounted vault at {args.mountpoint} (Ctrl+C to unmount)") |
| try: |
| import time |
| while True: |
| time.sleep(1) |
| except KeyboardInterrupt: |
| fs.stop() |
| print("unmounted") |
| elif args.cmd == "image": |
| r = diskimage.create(args.device, args.out, k=args.k, m=args.m, |
| part_mb=args.part_mb, label=args.label) |
| red = (args.k + args.m) / args.k |
| print(f"imaged {r['bytes']//1024} KB -> {r['out']} ({r['mode']}, {r['parts']} part(s), " |
| f"RS {args.k}+{args.m} ~{red:.2f}x). bad sectors: {r['bad_sectors']}") |
| if r["bad_sectors"]: |
| print(f" WARNING: {r['bad_sectors']} sectors unreadable at scan (zero-filled).") |
| elif args.cmd == "image-verify": |
| h = diskimage.verify(args.out) |
| print(f"health: {'HEALTHY' if h['healthy'] else 'DAMAGED'} " |
| f"chunks={h['chunks']} corrupted_shards={h['corrupted_shards']} " |
| f"repairable={h['repairable_chunks']} lost={h['lost_chunks']}") |
| elif args.cmd == "image-heal": |
| print(f"repaired {diskimage.heal(args.out)} shard(s)") |
| elif args.cmd == "image-restore": |
| n = diskimage.restore(args.out, args.dst) |
| print(f"restored {n//1024} KB -> {args.dst}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|