1094 lines · 22.7 KB · Brainfuck
RawDownload
implement Vac; include "sys.m";include "venti.m";include "vac.m"; sys: Sys;venti: Venti; werrstr, sprint, fprint, fildes: import sys;Roottype, Dirtype, Pointertype0, Datatype: import venti;Score, Session, Scoresize: import venti; dflag = 0; # from venti.bBIT8SZ:	con 1;BIT16SZ:        con 2;BIT32SZ:        con 4;BIT48SZ:        con 6;BIT64SZ:	con 8; Rootnamelen:	con 128;Rootversion:	con 2;Direntrymagic:	con 16r1c4d9072;Metablockmagic:	con 16r5656fc79;Maxstringsize: con 1000; blankroot: Root;blankentry: Entry;blankdirentry: Direntry;blankmetablock: Metablock;blankmetaentry: Metaentry;  init(){	sys = load Sys Sys->PATH;	venti = load Venti Venti->PATH;	venti->init();} pstring(a: array of byte, o: int, s: string): int{	sa := array of byte s;	# could do conversion ourselves	n := len sa;	a[o] = byte (n >> 8);	a[o+1] = byte n;	a[o+2:] = sa;	return o+BIT16SZ+n;} gstring(a: array of byte, o: int): (string, int){	if(o < 0 || o+BIT16SZ > len a)		return (nil, -1);	l := (int a[o] << 8) | int a[o+1];	if(l > Maxstringsize)		return (nil, -1);	o += BIT16SZ;	e := o+l;	if(e > len a)		return (nil, -1);	return (string a[o:e], e);} gtstring(a: array of byte, o: int, n: int): string{	e := o + n;	if(e > len a)		return nil;	for(i := o; i < e; i++)		if(a[i] == byte 0)			break;	return string a[o:i];}  Root.new(name, rtype: string, score: Score, blocksize: int, prev: ref Score): ref Root{	return ref Root(Rootversion, name, rtype, score, blocksize, prev);} Root.pack(r: self ref Root): array of byte{	d := array[Rootsize] of byte;	i := 0;	i = p16(d, i, r.version);	i = ptstring(d, i, r.name, Rootnamelen);	if(i < 0)		return nil;	i = ptstring(d, i, r.rtype, Rootnamelen);	if(i < 0)		return nil;	i = pscore(d, i, r.score);	i = p16(d, i, r.blocksize);	if(r.prev == nil) {		for(j := 0; j < Scoresize; j++)			d[i+j] = byte 0;		i += Scoresize;	} else 		i = pscore(d, i, *r.prev);	if(i != len d) {		sys->werrstr("root pack, bad length: "+string i);		return nil;	}	return d;} Root.unpack(d: array of byte): ref Root{	if(len d != Rootsize){		sys->werrstr("root entry is wrong length");		return nil;	}	r := ref blankroot;	r.version = g16(d, 0);	if(r.version != Rootversion){		sys->werrstr("unknown root version");		return nil;	}	o := BIT16SZ;	r.name = gtstring(d, o, Rootnamelen);	o += Rootnamelen;	r.rtype = gtstring(d, o, Rootnamelen);	o += Rootnamelen;	r.score = gscore(d, o);	o += Scoresize;	r.blocksize = g16(d, o);	o += BIT16SZ;	r.prev = ref gscore(d, o);	return r;} Entry.new(psize, dsize, flags: int, size: big, score: Venti->Score): ref Entry{	return ref Entry(0, psize, dsize, (flags&Entrydepthmask)>>Entrydepthshift, flags, size, score);} Entry.pack(e: self ref Entry): array of byte{	d := array[Entrysize] of byte;	i := 0;	i = p32(d, i, e.gen);	i = p16(d, i, e.psize);	i = p16(d, i, e.dsize);	e.flags |= e.depth<<Entrydepthshift;	d[i++] = byte e.flags;	for(j := 0; j < 5; j++)		d[i++] = byte 0;	i = p48(d, i, e.size);	i = pscore(d, i, e.score);	if(i != len d) {		werrstr(sprint("bad length, have %d, want %d", i, len d));		return nil;	}	return d;} Entry.unpack(d: array of byte): ref Entry{	if(len d != Entrysize){		sys->werrstr("entry is wrong length");		return nil;	}	e := ref blankentry;	i := 0;	e.gen = g32(d, i);	i += BIT32SZ;	e.psize = g16(d, i);	i += BIT16SZ;	e.dsize = g16(d, i);	i += BIT16SZ;	e.flags = int d[i];	e.depth = (e.flags & Entrydepthmask) >> Entrydepthshift;	e.flags &= ~Entrydepthmask;	i += BIT8SZ;	i += 5;			# skip something...	e.size = g48(d, i);	i += BIT48SZ;	e.score = gscore(d, i);	i += Scoresize;	if((e.flags & Entryactive) == 0)		return e;	if(!checksize(e.psize) || !checksize(e.dsize)){		sys->werrstr(sys->sprint("bad blocksize (%d or %d)", e.psize, e.dsize));		return nil;	}	return e;} Direntry.new(): ref Direntry{	return ref Direntry(9, "", 0, 0, 0, 0, big 0, "", "", "", 0, 0, 0, 0, 0, 0);} Direntry.mk(d: Sys->Dir): ref Direntry{	atime := 0; # d.atime;	mode := d.mode&Modeperm;	if(d.mode&sys->DMAPPEND)		mode |= Modeappend;	if(d.mode&sys->DMEXCL)		mode |= Modeexcl;	if(d.mode&sys->DMDIR)		mode |= Modedir;	if(d.mode&sys->DMTMP)		mode |= Modetemp;	return ref Direntry(9, d.name, 0, 0, 0, 0, d.qid.path, d.uid, d.gid, d.muid, d.mtime, 0, 0, atime, mode, d.mode);} Direntry.mkdir(de: self ref Direntry): ref Sys->Dir{        d := ref sys->nulldir;        d.name = de.elem;        d.uid = de.uid;        d.gid = de.gid;        d.muid = de.mid;        d.qid.path = de.qid;        d.qid.vers = 0;        d.qid.qtype = de.emode>>24;        d.mode = de.emode;        d.atime = de.atime;        d.mtime = de.mtime;        d.length = big 0;        return d;} strlen(s: string): int{	return 2+len array of byte s;} Direntry.pack(de: self ref Direntry): array of byte{	# assume version 9	length := 4+2+strlen(de.elem)+4+4+4+4+8+strlen(de.uid)+strlen(de.gid)+strlen(de.mid)+4+4+4+4+4; # + qidspace? 	d := array[length] of byte;	i := 0;	i = p32(d, i, Direntrymagic);	i = p16(d, i, de.version);	i = pstring(d, i, de.elem);	i = p32(d, i, de.entry);	if(de.version == 9) {		i = p32(d, i, de.gen);		i = p32(d, i, de.mentry);		i = p32(d, i, de.mgen);	}	i = p64(d, i, de.qid);	i = pstring(d, i, de.uid);	i = pstring(d, i, de.gid);	i = pstring(d, i, de.mid);	i = p32(d, i, de.mtime);	i = p32(d, i, de.mcount);	i = p32(d, i, de.ctime);	i = p32(d, i, de.atime);	i = p32(d, i, de.mode);	if(i != len d) {		werrstr(sprint("bad length for direntry (expected %d, have %d)", len d, i));		return nil;	}	return d;} Direntry.unpack(d: array of byte): ref Direntry{	{		de := ref blankdirentry;		i := 0;		magic: int;		(magic, i) = eg32(d, i);		if(magic != Direntrymagic) {			werrstr(sprint("bad magic (%x, want %x)", magic, Direntrymagic));			return nil;		}		(de.version, i) = eg16(d, i);		if(de.version != 8 && de.version != 9) {			werrstr(sprint("bad version (%d)", de.version));			return nil;		}		(de.elem, i) = egstring(d, i);		(de.entry, i) = eg32(d, i);		case de.version {		8 =>			de.gen = 0;			de.mentry = de.entry+1;			de.mgen = 0;		9 =>			(de.gen, i) = eg32(d, i);			(de.mentry, i) = eg32(d, i);			(de.mgen, i) = eg32(d, i);		}		(de.qid, i) = eg64(d, i);		(de.uid, i) = egstring(d, i);		(de.gid, i) = egstring(d, i);		(de.mid, i) = egstring(d, i);		(de.mtime, i) = eg32(d, i);		(de.mcount, i) = eg32(d, i);		(de.ctime, i) = eg32(d, i);		(de.atime, i) = eg32(d, i);		(de.mode, i) = eg32(d, i);		de.emode = de.mode&Modeperm;		if(de.mode&Modeappend)			de.emode |= sys->DMAPPEND;		if(de.mode&Modeexcl)			de.emode |= sys->DMEXCL;		if(de.mode&Modedir)			de.emode |= sys->DMDIR;		if(de.mode&Modetemp)			de.emode |= sys->DMTMP;		if(de.version == 9)			; # xxx handle qid space?, can be in here		return de;	} exception e {	"too small:*" =>		werrstr("direntry "+e);		return nil;	* =>		raise e;	}}  Metablock.new(): ref Metablock{	return ref Metablock(0, 0, 0, 0);} Metablock.pack(mb: self ref Metablock, d: array of byte){	i := 0;	i = p32(d, i, Metablockmagic);	i = p16(d, i, mb.size);	i = p16(d, i, mb.free);	i = p16(d, i, mb.maxindex);	i = p16(d, i, mb.nindex);} Metablock.unpack(d: array of byte): ref Metablock{	if(len d < Metablocksize) {		werrstr(sprint("bad length for metablock (%d, want %d)", len d, Metablocksize));		return nil;	}	i := 0;	magic := g32(d, i);	if(magic != Metablockmagic && magic != Metablockmagic+1) {		werrstr(sprint("bad magic for metablock (%x, need %x)", magic, Metablockmagic));		return nil;	}	i += BIT32SZ; 	mb := ref blankmetablock;	mb.size = g16(d, i);	i += BIT16SZ;	mb.free = g16(d, i);	i += BIT16SZ;	mb.maxindex = g16(d, i);	i += BIT16SZ;	mb.nindex = g16(d, i);	i += BIT16SZ;	if(mb.nindex == 0) {		werrstr("bad metablock, nindex=0");		return nil;	}	return mb;} Metaentry.pack(me: self ref Metaentry, d: array of byte){	i := 0;	i = p16(d, i, me.offset);	i = p16(d, i, me.size);} Metaentry.unpack(d: array of byte, i: int): ref Metaentry{	o := Metablocksize+i*Metaentrysize;	if(o+Metaentrysize > len d) {		werrstr(sprint("meta entry lies outside meta block, i=%d", i));		return nil;	} 	me := ref blankmetaentry;	me.offset = g16(d, o);	o += BIT16SZ;	me.size = g16(d, o);	o += BIT16SZ;	if(me.offset+me.size > len d) {		werrstr(sprint("meta entry points outside meta block, i=%d", i));		return nil;	}	return me;}  Page.new(dsize: int): ref Page{	psize := (dsize/Scoresize)*Scoresize;	return ref Page(array[psize] of byte, 0);} Page.add(p: self ref Page, s: Score){	for(i := 0; i < Scoresize; i++)		p.d[p.o+i] = s.a[i];	p.o += Scoresize;} Page.full(p: self ref Page): int{	return p.o+Scoresize > len p.d;} Page.data(p: self ref Page): array of byte{	for(i := p.o; i >= Scoresize; i -= Scoresize)		if(!Score(p.d[i-Scoresize:i]).eq(Score.zero()))			break;	return p.d[:i];}  File.new(s: ref Session, dtype, dsize: int): ref File{	p := array[1] of ref Page;	p[0] = Page.new(dsize);	return ref File(p, dtype, dsize, big 0, s);} fflush(f: ref File, last: int): (int, ref Entry){	for(i := 0; i < len f.p; i++) {		if(!last && !f.p[i].full())			return (0, nil);		if(last && f.p[i].o == Scoresize) {			flags := Entryactive;			if(f.dtype & Dirtype)				flags |= Entrydir;			flags |= i<<Entrydepthshift;			score := Score(f.p[i].data());			if(len score.a == 0)				score = Score.zero();			return (0, Entry.new(len f.p[i].d, f.dsize, flags, f.size, score));		}		(ok, score) := f.s.write(Pointertype0+i, f.p[i].data());		if(ok < 0)			return (-1, nil);		f.p[i] = Page.new(f.dsize);		if(i+1 == len f.p) {			newp := array[len f.p+1] of ref Page;			newp[:] = f.p;			newp[len newp-1] = Page.new(f.dsize);			f.p = newp;		}		f.p[i+1].add(score);	}	werrstr("internal error in fflush");	return (-1, nil);} File.write(f: self ref File, d: array of byte): int{	(fok, nil) := fflush(f, 0);	if(fok < 0)		return -1;	length := len d;	for(i := len d; i > 0; i--)		if(d[i-1] != byte 0)			break;	d = d[:i];	(ok, score) := f.s.write(f.dtype, d);	if(ok < 0)		return -1;	f.size += big length;	f.p[0].add(score);	return 0;} File.finish(f: self ref File): ref Entry{	(ok, e) := fflush(f, 1);	if(ok < 0)		return nil;	return e;}  Sink.new(s: ref Venti->Session, dsize: int): ref Sink{	dirdsize := (dsize/Entrysize)*Entrysize;	return ref Sink(File.new(s, Dirtype, dsize), array[dirdsize] of byte, 0, 0);} Sink.add(m: self ref Sink, e: ref Entry): int{	ed := e.pack();	if(ed == nil)		return -1;

Lines 1–500 of 1094.