diff options
Diffstat (limited to 'appl/cmd/install/wfind.b')
| -rw-r--r-- | appl/cmd/install/wfind.b | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/appl/cmd/install/wfind.b b/appl/cmd/install/wfind.b new file mode 100644 index 00000000..579fd946 --- /dev/null +++ b/appl/cmd/install/wfind.b @@ -0,0 +1,204 @@ +implement Wfind; + +include "sys.m"; + sys: Sys; +include "draw.m"; +include "bufio.m"; + bufio: Bufio; + Iobuf: import bufio; +include "arg.m"; + arg: Arg; +include "wrap.m"; + wrap : Wrap; +include "sh.m"; +include "keyring.m"; + keyring : Keyring; +include "readdir.m"; + readdir : Readdir; + +Wfind: module{ + init: fn(nil: ref Draw->Context, nil: list of string); +}; + +fatal(err : string) +{ + sys->fprint(sys->fildes(2), "%s\n", err); + exit; +} + +init(nil: ref Draw->Context, args: list of string) +{ + sys = load Sys Sys->PATH; + bufio = load Bufio Bufio->PATH; + arg = load Arg Arg->PATH; + keyring = load Keyring Keyring->PATH; + readdir = load Readdir Readdir->PATH; + wrap = load Wrap Wrap->PATH; + wrap->init(bufio); + + pkgs: list of string; + indir := "/install"; + arg->init(args); + while ((c := arg->opt()) != 0) { + case c { + 'p' => + pkg := arg->arg(); + if (pkg == nil) + fatal("missing package name"); + pkgs = pkg :: pkgs; + * => + fatal(sys->sprint("bad argument -%c", c)); + } + } + args = arg->argv(); + if (args == nil) + fatal("usage: install/wfind [-p package ... ] file ..."); + # (ok, dir) := sys->stat(indir); + # if (ok < 0) + # fatal(sys->sprint("cannot open install directory %s", indir)); + if(pkgs != nil){ + npkgs: list of string; + for(pkg := pkgs; pkg != nil; pkg = tl pkg) + npkgs = hd pkg :: npkgs; + pkgs = npkgs; + for(pkg = pkgs; pkg != nil; pkg = tl pkg) + scanpkg(hd pkg, indir+"/"+hd pkg, args); + } + else + scanpkgs(indir, args); + prfiles(); +} + +scanpkgs(d : string, files: list of string) +{ + (dir, n) := readdir->init(d, Readdir->NAME|Readdir->COMPACT); + for (i := 0; i < n; i++) { + if (dir[i].mode & Sys->DMDIR) + scanpkg(dir[i].name, d + "/" + dir[i].name, files); + } +} + +scanpkg(pkg : string, d : string, files: list of string) +{ + # base package, updates and update packages have the name + # <timestamp> or <timestamp.gz> + (dir, n) := readdir->init(d, Readdir->NAME|Readdir->COMPACT); + for (i := 0; i < n; i++) { + f := dir[i].name; + l := len f; + if (l >= 4 && f[l-3:l] == ".gz") + f = f[0:l-3]; + scanfile(f, pkg, d+"/"+dir[i].name, files); + } + w := wrap->openwrap(pkg, "/", 0); + if(w == nil) + return; + for(i = 0; i < w.nu; i++) + scanw(w, i, files, WRAP, pkg); +} + +scanfile(f: string, pkg: string, d: string, files: list of string) +{ + f = nil; + # sys->print("%s %s %s\n", f, pkg, d); + w := wrap->openwraphdr(d, "/", nil, 0); + if(w == nil) + return; + if(w.nu != 1) + fatal("strange package: more than one piece"); + # sys->print(" %s %d %s %d %d %d\n", w.name, w.tfull, w.u[0].desc, w.u[0].time, w.u[0].utime, w.u[0].typ); + scanw(w, 0, files, INSTALL, pkg); +} + +scanw(w: ref Wrap->Wrapped, i: int, files: list of string, where: int, pkg: string) +{ + w.u[i].bmd5.seek(big 0, Bufio->SEEKSTART); + while ((p := w.u[i].bmd5.gets('\n')) != nil){ + # sys->print("%s", p); + (n, l) := sys->tokenize(p, " \n"); + if(n != 2) + fatal(sys->sprint("bad md5 file in %s\n", wtype(where)+"/"+w.name+"/"+wrap->now2string(w.u[i].time, 0))); + file := hd l; + md5 := hd tl l; + for(fs := files; fs != nil; fs = tl fs){ + if(strsuffix(file, hd fs)){ + # sys->print("%s %s %s %d\n", pkg, file, md5, where); + addfile(file, w, i, md5, where, pkg); + } + } + } +} + +Stat: adt{ + name: string; + occs: list of (ref Wrap->Wrapped, int, string, int, string); + md5: string; +}; + +stats: list of ref Stat; + +addfile(file: string, w: ref Wrap->Wrapped, i: int, md5: string, where: int, pkg: string) +{ + for(sts := stats; sts != nil; sts = tl sts){ + st := hd sts; + if(st.name == file){ + st.occs = (w, i, md5, where, pkg) :: st.occs; + return; + } + } + digest := array[keyring->MD5dlen] of { * => byte 0 }; + if (wrap->md5file(file, digest) < 0) + str := "non-existent"+blanks(32-12); + else + str = wrap->md5conv(digest); + st := ref Stat; + st.name = file; + st.occs = (w, i, md5, where, pkg) :: nil; + st.md5 = str; + stats = st :: stats; +} + +prfiles() +{ + for(sts := stats; sts != nil; sts = tl sts){ + st := hd sts; + sys->print("%s\n", st.name); + proccs(st.occs); + sys->print("\t%s %s\n", st.md5, st.name); + } +} + +proccs(ocs: list of (ref Wrap->Wrapped, int, string, int, string)) +{ + if(ocs != nil){ + proccs(tl ocs); + (w, i, md5, where, pkg) := hd ocs; + sys->print("\t%s %s/%s(%s)\t%s\n", md5, w.name, wrap->now2string(w.u[i].time, 0), ptype(w.u[i].typ), wtype(where)+"/"+pkg); + } +} + +ptype(p: int): string +{ + return (array[] of { "???", "package ", "update ", "full upd" })[p]; +} + +INSTALL: con 0; +WRAP: con 1; + +wtype(w: int): string +{ + return (array[] of { "/install", "/wrap" })[w]; +} + +strsuffix(s: string, suf: string): int +{ + return (l1 := len s) >= (l2 := len suf) && s[l1-l2: l1] == suf; +} + +blanks(n: int): string +{ + s := ""; + for(i := 0; i < n; i++) + s += " "; + return s; +} |
