ref: dd16eef8365cb0b9e4805c23291aadcaa596dd87
dir: /appl/cmd/install/wrap2list.b/
# # Copyright © 2001 Vita Nuova (Holdings) Limited. All rights reserved. # implement Wrap2list; # make a version list suitable for SDS from /wrap include "sys.m"; sys : Sys; include "draw.m"; include "bufio.m"; bufio : Bufio; Iobuf : import bufio; include "crc.m"; crcm : Crc; include "wrap.m"; wrap: Wrap; Wrap2list: module { init : fn(ctxt: ref Draw->Context, argv: list of string); }; stderr: ref Sys->FD; HASHSZ: con 64; Element: type string; Hash: adt{ elems: array of Element; nelems: int; }; List: adt{ tabs: array of ref Hash; init: fn(l: self ref List); add: fn(l: self ref List, e: Element); subtract: fn(l: self ref List, e: Element); end: fn(l: self ref List): array of Element; }; flist: ref List; hash(s: string): int { h := 0; n := len s; for(i := 0; i < n; i++) h += s[i]; if(h < 0) h = -h; return h%HASHSZ; } List.init(l: self ref List) { ts := l.tabs = array[HASHSZ] of ref Hash; for(i := 0; i < HASHSZ; i++){ t := ts[i] = ref Hash; t.elems = array[HASHSZ] of Element; t.nelems = 0; } } List.add(l: self ref List, e: Element) { h := hash(e); t := l.tabs[h]; n := t.nelems; es := t.elems; for(i := 0; i < n; i++){ if(e == es[i]) return; } if(n == len es) es = t.elems = (array[2*n] of Element)[0:] = es; es[t.nelems++] = e; # sys->print("+ %s\n", e); } List.subtract(l: self ref List, e: Element) { h := hash(e); t := l.tabs[h]; n := t.nelems; es := t.elems; for(i := 0; i < n; i++){ if(e == es[i]){ es[i] = nil; break; } } # sys->print("- %s\n", e); } List.end(l: self ref List): array of Element { tot := 0; ts := l.tabs; for(i := 0; i < HASHSZ; i++) tot += ts[i].nelems; a := array[tot] of Element; m := 0; for(i = 0; i < HASHSZ; i++){ t := ts[i]; n := t.nelems; es := t.elems; a[m:] = es[0: n]; m += n; } return a; } usage() { sys->fprint(stderr, "Usage: wrap2list [ file ... ]\n"); exit; } init(nil: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; bufio = load Bufio Bufio->PATH; crcm = load Crc Crc->PATH; wrap = load Wrap Wrap->PATH; wrap->init(bufio); if(argv != nil) argv = tl argv; init := 0; if(argv != nil && hd argv == "-i"){ init = 1; argv = tl argv; } stderr = sys->fildes(2); # root := "/"; flist = ref List; flist.init(); fd := sys->open("/wrap", Sys->OREAD); for(;;){ (nd, d) := sys->dirread(fd); if(nd <= 0) break; for(i:=0; i<nd; i++){ if((d[0].mode & Sys->DMDIR) && (w := wrap->openwrap(d[i].name, "/", 1)) != nil){ # sys->fprint(stderr, "%s %s %d %d\n", w.name, w.root, w.tfull, w.nu); for(j := 0; j < w.nu; j++){ addfiles(w.u[j].bmd5); if((b := bufio->open(w.u[j].dir+"/remove", Bufio->OREAD)) != nil) subtractfiles(b); # sys->fprint(stderr, "%d: %s %s %d %d %d\n", i, w.u[j].desc, w.u[j].dir, w.u[j].time, w.u[j].utime, w.u[j].typ); } } } } for( ; argv != nil; argv = tl argv){ if((b := bufio->open(hd argv, Bufio->OREAD)) != nil) addfiles(b); } out(uniq(rmnil(sort(flist.end()))), init); } addfiles(b: ref Bufio->Iobuf) { b.seek(big 0, Bufio->SEEKSTART); while((s := b.gets('\n')) != nil){ (n, l) := sys->tokenize(s, " \n"); if(n > 0) flist.add(hd l); } } subtractfiles(b: ref Bufio->Iobuf) { b.seek(big 0, Bufio->SEEKSTART); while((s := b.gets('\n')) != nil){ (n, l) := sys->tokenize(s, " \n"); if(n > 0) flist.subtract(hd l); } } out(fs: array of Element, init: int) { nf := len fs; for(i := 0; i < nf; i++){ f := fs[i]; outl(f, nil, init); l := len f; if(l >= 7 && f[l-7:] == "emu.new"){ g := f; f[l-3] = 'e'; f[l-2] = 'x'; f[l-1] = 'e'; outl(f, g, init); # try emu.exe outl(f[0: l-4], g, init); # try emu # sys->fprint(sys->fildes(2), "%s %s\n", f, g); } } } outl(f: string, g: string, init: int) { (ok, d) := sys->stat(f); if(ok < 0){ # sys->fprint(stderr, "cannot open %s\n", f); return; } if(g == nil) g = "-"; if(d.mode & Sys->DMDIR) d.length = big 0; if(init) mtime := 0; else mtime = d.mtime; sys->print("%s %s %d %d %d %d %d\n", f, g, int d.length, d.mode, mtime, crc(f, d), 0); } crc(f: string, d: Sys->Dir): int { crcs := crcm->init(0, int 16rffffffff); if(d.mode & Sys->DMDIR) return 0; fd := sys->open(f, Sys->OREAD); if(fd == nil){ sys->fprint(stderr, "cannot open %s\n", f); return 0; } crc := 0; buf := array[Sys->ATOMICIO] of byte; for(;;){ nr := sys->read(fd, buf, len buf); if(nr < 0){ sys->fprint(stderr, "bad read on %s : %r\n", f); return 0; } if(nr <= 0) break; crc = crcm->crc(crcs, buf, nr); } crcm->reset(crcs); return crc; } sort(a: array of Element): array of Element { qsort(a, len a); return a; } rmnil(a: array of Element): array of Element { n := len a; for(i := 0; i < n; i++) if(a[i] != nil) break; return a[i: n]; } uniq(a: array of Element): array of Element { n := len a; for(i := 0; i < n-1; ){ if(a[i] == a[i+1]) a[i+1:] = a[i+2: n--]; else i++; } return a[0: n]; } qsort(a: array of Element, n: int) { i, j: int; t: Element; while(n > 1){ i = n>>1; t = a[0]; a[0] = a[i]; a[i] = t; i = 0; j = n; for(;;){ do i++; while(i < n && a[i] < a[0]); do j--; while(j > 0 && a[j] > a[0]); if(j < i) break; t = a[i]; a[i] = a[j]; a[j] = t; } t = a[0]; a[0] = a[j]; a[j] = t; n = n-j-1; if(j >= n){ qsort(a, j); a = a[j+1:]; }else{ qsort(a[j+1:], n); n = j; } } }