1# 2# Copyright © 2001 Vita Nuova (Holdings) Limited. All rights reserved. 3# 4 5implement Wrap2list; 6 7# make a version list suitable for SDS from /wrap 8 9include "sys.m"; 10 sys : Sys; 11include "draw.m"; 12include "bufio.m"; 13 bufio : Bufio; 14 Iobuf : import bufio; 15include "crc.m"; 16 crcm : Crc; 17include "wrap.m"; 18 wrap: Wrap; 19 20Wrap2list: module 21{ 22 init : fn(ctxt: ref Draw->Context, argv: list of string); 23}; 24 25stderr: ref Sys->FD; 26 27HASHSZ: con 64; 28 29Element: type string; 30 31Hash: adt{ 32 elems: array of Element; 33 nelems: int; 34}; 35 36List: adt{ 37 tabs: array of ref Hash; 38 init: fn(l: self ref List); 39 add: fn(l: self ref List, e: Element); 40 subtract: fn(l: self ref List, e: Element); 41 end: fn(l: self ref List): array of Element; 42}; 43 44flist: ref List; 45 46hash(s: string): int 47{ 48 h := 0; 49 n := len s; 50 for(i := 0; i < n; i++) 51 h += s[i]; 52 if(h < 0) 53 h = -h; 54 return h%HASHSZ; 55} 56 57List.init(l: self ref List) 58{ 59 ts := l.tabs = array[HASHSZ] of ref Hash; 60 for(i := 0; i < HASHSZ; i++){ 61 t := ts[i] = ref Hash; 62 t.elems = array[HASHSZ] of Element; 63 t.nelems = 0; 64 } 65} 66 67List.add(l: self ref List, e: Element) 68{ 69 h := hash(e); 70 t := l.tabs[h]; 71 n := t.nelems; 72 es := t.elems; 73 for(i := 0; i < n; i++){ 74 if(e == es[i]) 75 return; 76 } 77 if(n == len es) 78 es = t.elems = (array[2*n] of Element)[0:] = es; 79 es[t.nelems++] = e; 80# sys->print("+ %s\n", e); 81} 82 83List.subtract(l: self ref List, e: Element) 84{ 85 h := hash(e); 86 t := l.tabs[h]; 87 n := t.nelems; 88 es := t.elems; 89 for(i := 0; i < n; i++){ 90 if(e == es[i]){ 91 es[i] = nil; 92 break; 93 } 94 } 95# sys->print("- %s\n", e); 96} 97 98List.end(l: self ref List): array of Element 99{ 100 tot := 0; 101 ts := l.tabs; 102 for(i := 0; i < HASHSZ; i++) 103 tot += ts[i].nelems; 104 a := array[tot] of Element; 105 m := 0; 106 for(i = 0; i < HASHSZ; i++){ 107 t := ts[i]; 108 n := t.nelems; 109 es := t.elems; 110 a[m:] = es[0: n]; 111 m += n; 112 } 113 return a; 114} 115 116usage() 117{ 118 sys->fprint(stderr, "Usage: wrap2list [ file ... ]\n"); 119 exit; 120} 121 122init(nil: ref Draw->Context, argv: list of string) 123{ 124 sys = load Sys Sys->PATH; 125 bufio = load Bufio Bufio->PATH; 126 crcm = load Crc Crc->PATH; 127 wrap = load Wrap Wrap->PATH; 128 wrap->init(bufio); 129 if(argv != nil) 130 argv = tl argv; 131 init := 0; 132 if(argv != nil && hd argv == "-i"){ 133 init = 1; 134 argv = tl argv; 135 } 136 stderr = sys->fildes(2); 137 # root := "/"; 138 flist = ref List; 139 flist.init(); 140 fd := sys->open("/wrap", Sys->OREAD); 141 for(;;){ 142 (nd, d) := sys->dirread(fd); 143 if(nd <= 0) 144 break; 145 for(i:=0; i<nd; i++){ 146 if((d[0].mode & Sys->DMDIR) && (w := wrap->openwrap(d[i].name, "/", 1)) != nil){ 147 # sys->fprint(stderr, "%s %s %d %d\n", w.name, w.root, w.tfull, w.nu); 148 for(j := 0; j < w.nu; j++){ 149 addfiles(w.u[j].bmd5); 150 if((b := bufio->open(w.u[j].dir+"/remove", Bufio->OREAD)) != nil) 151 subtractfiles(b); 152 # 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); 153 } 154 } 155 } 156 } 157 for( ; argv != nil; argv = tl argv){ 158 if((b := bufio->open(hd argv, Bufio->OREAD)) != nil) 159 addfiles(b); 160 } 161 out(uniq(rmnil(sort(flist.end()))), init); 162} 163 164addfiles(b: ref Bufio->Iobuf) 165{ 166 b.seek(big 0, Bufio->SEEKSTART); 167 while((s := b.gets('\n')) != nil){ 168 (n, l) := sys->tokenize(s, " \n"); 169 if(n > 0) 170 flist.add(hd l); 171 } 172} 173 174subtractfiles(b: ref Bufio->Iobuf) 175{ 176 b.seek(big 0, Bufio->SEEKSTART); 177 while((s := b.gets('\n')) != nil){ 178 (n, l) := sys->tokenize(s, " \n"); 179 if(n > 0) 180 flist.subtract(hd l); 181 } 182} 183 184out(fs: array of Element, init: int) 185{ 186 nf := len fs; 187 for(i := 0; i < nf; i++){ 188 f := fs[i]; 189 outl(f, nil, init); 190 l := len f; 191 if(l >= 7 && f[l-7:] == "emu.new"){ 192 g := f; 193 f[l-3] = 'e'; 194 f[l-2] = 'x'; 195 f[l-1] = 'e'; 196 outl(f, g, init); # try emu.exe 197 outl(f[0: l-4], g, init); # try emu 198# sys->fprint(sys->fildes(2), "%s %s\n", f, g); 199 } 200 } 201} 202 203outl(f: string, g: string, init: int) 204{ 205 (ok, d) := sys->stat(f); 206 if(ok < 0){ 207 # sys->fprint(stderr, "cannot open %s\n", f); 208 return; 209 } 210 if(g == nil) 211 g = "-"; 212 if(d.mode & Sys->DMDIR) 213 d.length = big 0; 214 if(init) 215 mtime := 0; 216 else 217 mtime = d.mtime; 218 sys->print("%s %s %d %d %d %d %d\n", f, g, int d.length, d.mode, mtime, crc(f, d), 0); 219} 220 221crc(f: string, d: Sys->Dir): int 222{ 223 crcs := crcm->init(0, int 16rffffffff); 224 if(d.mode & Sys->DMDIR) 225 return 0; 226 fd := sys->open(f, Sys->OREAD); 227 if(fd == nil){ 228 sys->fprint(stderr, "cannot open %s\n", f); 229 return 0; 230 } 231 crc := 0; 232 buf := array[Sys->ATOMICIO] of byte; 233 for(;;){ 234 nr := sys->read(fd, buf, len buf); 235 if(nr < 0){ 236 sys->fprint(stderr, "bad read on %s : %r\n", f); 237 return 0; 238 } 239 if(nr <= 0) 240 break; 241 crc = crcm->crc(crcs, buf, nr); 242 } 243 crcm->reset(crcs); 244 return crc; 245} 246 247sort(a: array of Element): array of Element 248{ 249 qsort(a, len a); 250 return a; 251} 252 253rmnil(a: array of Element): array of Element 254{ 255 n := len a; 256 for(i := 0; i < n; i++) 257 if(a[i] != nil) 258 break; 259 return a[i: n]; 260} 261 262uniq(a: array of Element): array of Element 263{ 264 n := len a; 265 for(i := 0; i < n-1; ){ 266 if(a[i] == a[i+1]) 267 a[i+1:] = a[i+2: n--]; 268 else 269 i++; 270 } 271 return a[0: n]; 272} 273 274qsort(a: array of Element, n: int) 275{ 276 i, j: int; 277 t: Element; 278 279 while(n > 1){ 280 i = n>>1; 281 t = a[0]; a[0] = a[i]; a[i] = t; 282 i = 0; 283 j = n; 284 for(;;){ 285 do 286 i++; 287 while(i < n && a[i] < a[0]); 288 do 289 j--; 290 while(j > 0 && a[j] > a[0]); 291 if(j < i) 292 break; 293 t = a[i]; a[i] = a[j]; a[j] = t; 294 } 295 t = a[0]; a[0] = a[j]; a[j] = t; 296 n = n-j-1; 297 if(j >= n){ 298 qsort(a, j); 299 a = a[j+1:]; 300 }else{ 301 qsort(a[j+1:], n); 302 n = j; 303 } 304 } 305} 306