1implement Mkhash; 2 3# 4# for compatibility, this is closely modelled on Plan 9's ndb/mkhash 5# 6 7include "sys.m"; 8 sys: Sys; 9 10include "draw.m"; 11 12include "bufio.m"; 13include "attrdb.m"; 14 attrdb: Attrdb; 15 Db, Dbf, Dbentry, Tuples, Attr: import attrdb; 16 attrhash: Attrhash; 17 NDBPLEN, NDBHLEN, NDBCHAIN, NDBNAP: import Attrhash; 18 19Mkhash: module 20{ 21 init: fn(nil: ref Draw->Context, nil: list of string); 22}; 23 24init(nil: ref Draw->Context, args: list of string) 25{ 26 sys = load Sys Sys->PATH; 27 attrdb = load Attrdb Attrdb->PATH; 28 if(attrdb == nil) 29 error(sys->sprint("can't load %s: %r", Attrdb->PATH)); 30 attrdb->init(); 31 attrhash = load Attrhash Attrhash->PATH; 32 if(attrhash == nil) 33 error(sys->sprint("can't load %s: %r", Attrhash->PATH)); 34 35 if(len args != 3) 36 error("usage: mkhash file attr"); 37 args = tl args; 38 dbname := hd args; 39 args = tl args; 40 attr := hd args; 41 dbf := Dbf.open(dbname); 42 if(dbf == nil) 43 error(sys->sprint("can't open %s: %r", dbname)); 44 offset := 0; 45 n := 0; 46 for(;;){ 47 (e, nil, next) := dbf.readentry(offset, nil, nil, 0); 48 if(e == nil) 49 break; 50 m := len e.find(attr); 51 if(0 && m != 0) 52 sys->fprint(sys->fildes(2), "%ud [%d]\n", offset, m); 53 n += m; 54 offset = next; 55 } 56 hlen := 2*n+1; 57 chains := n*2*NDBPLEN; 58 file := array[NDBHLEN + hlen*NDBPLEN + chains] of byte; 59 tab := file[NDBHLEN:]; 60 for(i:=0; i<len tab; i+=NDBPLEN) 61 put3(tab[i:], NDBNAP); 62 offset = 0; 63 chain := hlen*NDBPLEN; 64 for(;;){ 65 (e, nil, next) := dbf.readentry(offset, nil, nil, 0); 66 if(e == nil) 67 break; 68 for(l := e.find(attr); l != nil; l = tl l) 69 for((nil, al) := hd l; al != nil; al = tl al) 70 chain = enter(tab, hd al, hlen, chain, offset); 71 offset = next; 72 } 73 hashfile := dbname+"."+attr; 74 hfd := sys->create(hashfile, Sys->OWRITE, 8r666); 75 if(hfd == nil) 76 error(sys->sprint("can't create %s: %r", hashfile)); 77 mtime := 0; 78 if(dbf.dir != nil) 79 mtime = dbf.dir.mtime; 80 put4(file, mtime); 81 put4(file[4:], hlen); 82 if(sys->write(hfd, file, NDBHLEN+chain) != NDBHLEN+chain) 83 error(sys->sprint("error writing %s: %r", hashfile)); 84} 85 86error(s: string) 87{ 88 sys->fprint(sys->fildes(2), "mkhash: %s\n", s); 89 raise "fail:error"; 90} 91 92enter(tab: array of byte, a: ref Attr, hlen: int, chain: int, offset: int): int 93{ 94 o := attrhash->hash(a.val, hlen)*NDBPLEN; 95 for(; (p := attrhash->get3(tab[o:])) != NDBNAP; o = p & ~NDBCHAIN) 96 if((p & NDBCHAIN) == 0){ 97 put3(tab[o:], chain | NDBCHAIN); 98 put3(tab[chain:], p); 99 put3(tab[chain+NDBPLEN:], offset); 100 return chain+2*NDBPLEN; 101 } 102 put3(tab[o:], offset); 103 return chain; 104} 105 106put3(a: array of byte, v: int) 107{ 108 a[0] = byte v; 109 a[1] = byte (v>>8); 110 a[2] = byte (v>>16); 111} 112 113put4(a: array of byte, v: int) 114{ 115 a[0] = byte v; 116 a[1] = byte (v>>8); 117 a[2] = byte (v>>16); 118 a[3] = byte (v>>24); 119} 120