1implement Wdiff; 2 3include "sys.m"; 4 sys: Sys; 5include "draw.m"; 6include "bufio.m"; 7 bufio: Bufio; 8 Iobuf: import bufio; 9include "arg.m"; 10 arg: Arg; 11include "wrap.m"; 12 wrap : Wrap; 13include "sh.m"; 14include "keyring.m"; 15 keyring : Keyring; 16 17 18Wdiff: module{ 19 init: fn(nil: ref Draw->Context, nil: list of string); 20}; 21 22root := "/"; 23bflag : int; 24listing : int; 25package: int; 26 27diff(w : ref Wrap->Wrapped, name : string, c : chan of int) 28{ 29 sys->pctl(Sys->FORKFD, nil); 30 wrapped := w.root+"/"+name; 31 local := root+"/"+name; 32 (ok, dir) := sys->stat(local); 33 if (ok < 0) { 34 sys->print("cannot stat %s\n", local); 35 c <-= -1; 36 return; 37 } 38 (ok, dir) = sys->stat(wrapped); 39 if (ok < 0) { 40 sys->print("cannot stat %s\n", wrapped); 41 c <-= -1; 42 return; 43 } 44 cmd := "/dis/diff.dis"; 45 m := load Command cmd; 46 if(m == nil) { 47 c <-= -1; 48 return; 49 } 50 if (bflag) 51 m->init(nil, cmd :: "-b" :: wrapped :: local :: nil); 52 else 53 m->init(nil, cmd :: wrapped :: local :: nil); 54 c <-= 0; 55} 56 57fatal(err : string) 58{ 59 sys->fprint(sys->fildes(2), "%s\n", err); 60 exit; 61} 62 63init(nil: ref Draw->Context, args: list of string) 64{ 65 sys = load Sys Sys->PATH; 66 bufio = load Bufio Bufio->PATH; 67 arg = load Arg Arg->PATH; 68 keyring = load Keyring Keyring->PATH; 69 wrap = load Wrap Wrap->PATH; 70 wrap->init(bufio); 71 72 arg->init(args); 73 while ((c := arg->opt()) != 0) { 74 case c { 75 'b' => 76 bflag = 1; 77 'l' => 78 listing = 1; 79 'p' => 80 package = 1; 81 'r' => 82 root = arg->arg(); 83 if (root == nil) 84 fatal("missing root name"); 85 * => 86 fatal(sys->sprint("bad argument -%c", c)); 87 } 88 } 89 args = arg->argv(); 90 if (args == nil || tl args != nil) 91 fatal("usage: install/wdiff [-blp] [-r root] package"); 92 (ok, dir) := sys->stat(hd args); 93 if (ok < 0) 94 fatal(sys->sprint("no such file %s", hd args)); 95 w := wrap->openwraphdr(hd args, root, nil, !listing); 96 if (w == nil) 97 fatal("no such package found"); 98 99 if(package){ 100 while(w.nu > 0 && w.u[w.nu-1].typ == wrap->UPD) 101 w.nu--; 102 } 103 104 digest := array[keyring->MD5dlen] of { * => byte 0 }; 105 digest0 := array[keyring->MD5dlen] of { * => byte 0 }; 106 107 # loop through each md5sum file of each package in increasing time order 108 for(i := 0; i < w.nu; i++){ 109 b := bufio->open(w.u[i].dir+"/md5sum", Sys->OREAD); 110 if (b == nil) 111 fatal("md5sum file not found"); 112 while ((p := b.gets('\n')) != nil) { 113 (n, lst) := sys->tokenize(p, " \t\n"); 114 if (n != 2) 115 fatal("error in md5sum file"); 116 p = hd lst; 117 q := root+"/"+p; 118 (ok, dir) = sys->stat(q); 119 if (ok >= 0 && (dir.mode & Sys->DMDIR)) 120 continue; 121 t: int; 122 (ok, t) = wrap->getfileinfo(w, p, nil, digest0, nil); 123 if(ok < 0){ 124 sys->print("cannot happen\n"); 125 continue; 126 } 127 if(t != w.u[i].time) # covered by later update 128 continue; 129 if (wrap->md5file(q, digest) < 0) { 130 sys->print("%s removed\n", p); 131 continue; 132 } 133 str := wrap->md5conv(digest); 134 str0 := wrap->md5conv(digest0); 135 # if (str == hd tl lst) 136 if(str == str0) 137 continue; 138 if (listing) 139 sys->print("%s modified\n", p); 140 else { 141 endc := chan of int; 142 spawn diff(w, p, endc); 143 <- endc; 144 } 145 } 146 } 147 wrap->end(); 148} 149