code wiki / (root) / nx_fileop.nx

nx_fileop.nx source

↩ module page · 77 lines · 5897 B

1// nx_fileop.nx -- sovereign file-op CLI (retires Remove-Item / mv). Composes the canonical nx_fio + nx_syscalls's 2// sys_renameat. Usage: 3// nx_fileop rm <path> delete a file (refuses empty / "/" ) 4// nx_fileop mv <src> <dst> atomic rename (sys_renameat) 5// nx_fileop exists <path> existence check (exit 0 if present, 3 if absent) 6// nx_fileop prepare-install-intent INTENT SOURCE LIVE CANDIDATE BACKUP NEW_SHA256 OLD_SHA256 MODE_DECIMAL BUDGET_BYTES 7// Creates or verifies an identical immutable intent; never publishes an artifact. 8// No shell. license_tier: ORIGINAL 9import "nx_file_install.nx" 10import "nx_gate.nx" 11 12func fo_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8) { if a[i]!=b[i] { return 0 } i=i+1 } if b[i]!=(0 as u8) { return 0 } return 1 } 13func fo_bad_path(p: *u8) -> i64 { if p[0]==(0 as u8) { return 1 } if p[0]==(0x2f as u8) { if p[1]==(0 as u8) { return 1 } } return 0 } 14 15func main(argc: i64, argv: *i64) -> i64 { 16 if argc>=2 && fo_streq(argv[1] as *u8,"prepare-install-intent")==1 { return fo_prepare_intent(argc,argv) } 17 if argc < 3 { gw("usage: nx_fileop rm <path> | mv <src> <dst> | exists <path> | prepare-install-intent INTENT SOURCE LIVE CANDIDATE BACKUP NEW_SHA256 OLD_SHA256 MODE_DECIMAL BUDGET_BYTES\n" as *u8); sys_exit(1); return 1 } 18 let op: *u8 = argv[1] as *u8 19 let a2: *u8 = argv[2] as *u8 20 21 if fo_streq(op, "rm" as *u8)==1 { 22 if fo_bad_path(a2)==1 { gw("nx_fileop rm: refusing empty / root path\n" as *u8); sys_exit(1); return 1 } 23 if fio_exists(a2)==0 { gw("nx_fileop rm: not found " as *u8); gw(a2); gw("\n" as *u8); sys_exit(2); return 2 } 24 let r: i64 = fio_unlink(a2) 25 if r==0 { gw("nx_fileop rm OK " as *u8); gw(a2); gw("\n" as *u8); sys_exit(0); return 0 } 26 gw("nx_fileop rm FAIL " as *u8); gw(a2); gw(" rc=" as *u8); gn(r); gw("\n" as *u8); sys_exit(3); return 3 27 } 28 if fo_streq(op, "mv" as *u8)==1 { 29 if argc < 4 { gw("usage: nx_fileop mv <src> <dst>\n" as *u8); sys_exit(1); return 1 } 30 let dst: *u8 = argv[3] as *u8 31 if fo_bad_path(a2)==1 { gw("nx_fileop mv: refusing empty / root src\n" as *u8); sys_exit(1); return 1 } 32 let r: i64 = sys_renameat(a2, dst) 33 if r==0 { gw("nx_fileop mv OK " as *u8); gw(a2); gw(" -> " as *u8); gw(dst); gw("\n" as *u8); sys_exit(0); return 0 } 34 gw("nx_fileop mv FAIL rc=" as *u8); gn(r); gw("\n" as *u8); sys_exit(3); return 3 35 } 36 if fo_streq(op, "exists" as *u8)==1 { 37 if fio_exists(a2)==1 { gw("nx_fileop exists YES " as *u8); gw(a2); gw("\n" as *u8); sys_exit(0); return 0 } 38 gw("nx_fileop exists NO " as *u8); gw(a2); gw("\n" as *u8); sys_exit(3); return 3 39 } 40 gw("nx_fileop: unknown op " as *u8); gw(op); gw("\n" as *u8); sys_exit(1); return 1 41} 42 43// Preparation records intent only; publication remains a separately authorized operation. 44func fo_intent_error(stage:*u8,code:i64)->i64 { 45 gw("{\"schema\":\"nishi.install-intent.v1\",\"status\":\"refused\",\"published\":false,\"stage\":\"");gw(stage);gw("\",\"code\":");gn(code);gw("}\n");return 3 46} 47func fo_decimal(s:*u8,max:i64,out:*i64)->i64 { 48 if s[0]==0 as u8 { return 0 };var i:i64=0;var v:i64=0 49 while s[i]!=0 as u8 { let d:i64=(s[i] as i64)-48;if d<0 || d>9 || v>(max-d)/10 { return 0 };v=v*10+d;i=i+1 } 50 out[0]=v;return 1 51} 52func fo_digest(s:*u8,out:*u8)->i64 { 53 if fi_len(s)!=64 { return 0 };var i:i64=0 54 while i<64 { let c:i64=s[i] as i64;var v:i64=0-1 55 if c>=48 && c<=57 { v=c-48 };if c>=97 && c<=102 { v=c-87 };if c>=65 && c<=70 { v=c-55 };if v<0 { return 0 } 56 if i%2==0 { out[i/2]=(v*16) as u8 } else { out[i/2]=((out[i/2] as i64)+v) as u8 };i=i+1 };return 1 57} 58func fo_plan_matches(p:*NxFileInstallPlan,argv:*i64,newhash:*u8,oldhash:*u8,mode:i64)->i64 { 59 return fo_streq(p.source,argv[3] as *u8)==1 && fo_streq(p.live,argv[4] as *u8)==1 && fo_streq(p.candidate,argv[5] as *u8)==1 && fo_streq(p.backup,argv[6] as *u8)==1 && p.mode==mode && fi_same(p.expected_new,newhash,FI_DIGEST_BYTES)==1 && fi_same(p.expected_old,oldhash,FI_DIGEST_BYTES)==1 60} 61func fo_prepare_intent(argc:i64,argv:*i64)->i64 { 62 if argc!=11 { return fo_intent_error("arguments",FIO_EINVAL) } 63 let capacity:i64=FI_DIGEST_BYTES*2+__size_of(i64)*2+__size_of(NxFileInstallPlan)+__size_of(NxFileWriteResult) 64 let mem:*u8=sys_mmap(capacity);if (mem as i64)<0 { return fo_intent_error("allocation",mem as i64) } 65 let newhash:*u8=mem;let oldhash:*u8=mem+FI_DIGEST_BYTES;let values:*i64=(mem+FI_DIGEST_BYTES*2) as *i64 66 let p:*NxFileInstallPlan=(mem+FI_DIGEST_BYTES*2+__size_of(i64)*2) as *NxFileInstallPlan 67 let w:*NxFileWriteResult=((p as *u8)+__size_of(NxFileInstallPlan)) as *NxFileWriteResult 68 fi_plan_init(p) 69 var rc:i64=FIO_EINVAL;var stage:*u8="input";var reused:i64=0 70 if fi_path_valid(argv[2] as *u8)==1 && fo_streq(argv[2] as *u8,argv[3] as *u8)==0 && fo_streq(argv[2] as *u8,argv[4] as *u8)==0 && fo_streq(argv[2] as *u8,argv[5] as *u8)==0 && fo_streq(argv[2] as *u8,argv[6] as *u8)==0 && fo_digest(argv[7] as *u8,newhash)==1 && fo_digest(argv[8] as *u8,oldhash)==1 && fo_decimal(argv[9] as *u8,0x1ff,values)==1 && fo_decimal(argv[10] as *u8,9223372036854775807,((values as *u8)+__size_of(i64)) as *i64)==1 && values[1]>0 { 71 stage="intent-create";rc=fi_plan_create(argv[2] as *u8,argv[3] as *u8,argv[4] as *u8,argv[5] as *u8,argv[6] as *u8,values[0],newhash,oldhash,values[1],w) 72 if rc==FIO_EEXIST { stage="existing-intent";rc=fi_plan_read(argv[2] as *u8,values[1],p);if rc==0 { if fo_plan_matches(p,argv,newhash,oldhash,values[0])==1 { reused=1 } else { rc=FIO_EBADMSG } };fi_plan_close(p) } 73 } 74 sys_munmap(mem,capacity) 75 if rc!=0 { return fo_intent_error(stage,rc) } 76 if reused==1 { gw("{\"schema\":\"nishi.install-intent.v1\",\"status\":\"existing-identical\",\"published\":false}\n") } else { gw("{\"schema\":\"nishi.install-intent.v1\",\"status\":\"created-durable\",\"published\":false}\n") };return 0 77}