summaryrefslogtreecommitdiff
path: root/appl/cmd/install/wrap2list.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/install/wrap2list.b')
-rw-r--r--appl/cmd/install/wrap2list.b305
1 files changed, 305 insertions, 0 deletions
diff --git a/appl/cmd/install/wrap2list.b b/appl/cmd/install/wrap2list.b
new file mode 100644
index 00000000..d2656cf5
--- /dev/null
+++ b/appl/cmd/install/wrap2list.b
@@ -0,0 +1,305 @@
+#
+# 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;
+ }
+ }
+}