Vac works.
diff --git a/src/cmd/vac/pack.c b/src/cmd/vac/pack.c
index b16834d..074152e 100644
--- a/src/cmd/vac/pack.c
+++ b/src/cmd/vac/pack.c
@@ -12,7 +12,7 @@
 	ushort index;
 };
 
-static int	stringUnpack(char **s, uchar **p, int *n);
+static int	stringunpack(char **s, uchar **p, int *n);
 
 /*
  * integer conversion routines
@@ -23,35 +23,35 @@
 #define	U48GET(p)	(((uvlong)U16GET(p)<<32)|(uvlong)U32GET((p)+2))
 #define	U64GET(p)	(((uvlong)U32GET(p)<<32)|(uvlong)U32GET((p)+4))
 
-#define	U8PUT(p,v)	(p)[0]=(v)
-#define	U16PUT(p,v)	(p)[0]=(v)>>8;(p)[1]=(v)
-#define	U32PUT(p,v)	(p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
+#define	U8PUT(p,v)	(p)[0]=(v)&0xFF
+#define	U16PUT(p,v)	(p)[0]=((v)>>8)&0xFF;(p)[1]=(v)&0xFF
+#define	U32PUT(p,v)	(p)[0]=((v)>>24)&0xFF;(p)[1]=((v)>>16)&0xFF;(p)[2]=((v)>>8)&0xFF;(p)[3]=(v)&0xFF
 #define	U48PUT(p,v,t32)	t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
 #define	U64PUT(p,v,t32)	t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
 
 static int
-stringUnpack(char **s, uchar **p, int *n)
+stringunpack(char **s, uchar **p, int *n)
 {
 	int nn;
 
 	if(*n < 2)
-		return 0;
+		return -1;
 	
 	nn = U16GET(*p);
 	*p += 2;
 	*n -= 2;
 	if(nn > *n)
-		return 0;
-	*s = vtMemAlloc(nn+1);
+		return -1;
+	*s = vtmalloc(nn+1);
 	memmove(*s, *p, nn);
 	(*s)[nn] = 0;
 	*p += nn;
 	*n -= nn;
-	return 1;
+	return 0;
 }
 
 static int
-stringPack(char *s, uchar *p)
+stringpack(char *s, uchar *p)
 {
 	int n;
 
@@ -63,7 +63,7 @@
 
 
 int
-mbUnpack(MetaBlock *mb, uchar *p, int n)
+mbunpack(MetaBlock *mb, uchar *p, int n)
 {
 	u32int magic;
 
@@ -72,13 +72,13 @@
 
 	if(n == 0) {
 		memset(mb, 0, sizeof(MetaBlock));
-		return 1;
+		return 0;
 	}
 
 	magic = U32GET(p);
 	if(magic != MetaMagic && magic != MetaMagic+1) {
-		vtSetError("bad meta block magic");
-		return 0;
+		werrstr("bad meta block magic");
+		return -1;
 	}
 	mb->size = U16GET(p+4);
 	mb->free = U16GET(p+6);
@@ -87,22 +87,22 @@
 	mb->unbotch = (magic == MetaMagic+1);
 
 	if(mb->size > n) {
-		vtSetError("bad meta block size");
-		return 0;
+		werrstr("bad meta block size");
+		return -1;
 	}
 	p += MetaHeaderSize;
 	n -= MetaHeaderSize;
 
 	USED(p);
 	if(n < mb->maxindex*MetaIndexSize) {
- 		vtSetError("truncated meta block 2");
-		return 0;
+ 		werrstr("truncated meta block 2");
+		return -1;
 	}
-	return 1;
+	return 0;
 }
 
 void
-mbPack(MetaBlock *mb)
+mbpack(MetaBlock *mb)
 {
 	uchar *p;
 
@@ -117,7 +117,7 @@
 
 
 void
-mbDelete(MetaBlock *mb, int i, MetaEntry *me)
+mbdelete(MetaBlock *mb, int i, MetaEntry *me)
 {
 	uchar *p;
 	int n;
@@ -137,7 +137,7 @@
 }
 
 void
-mbInsert(MetaBlock *mb, int i, MetaEntry *me)
+mbinsert(MetaBlock *mb, int i, MetaEntry *me)
 {
 	uchar *p;
 	int o, n;
@@ -161,14 +161,14 @@
 }
 
 int
-meUnpack(MetaEntry *me, MetaBlock *mb, int i)
+meunpack(MetaEntry *me, MetaBlock *mb, int i)
 {
 	uchar *p;
 	int eo, en;
 
 	if(i < 0 || i >= mb->nindex) {
-		vtSetError("bad meta entry index");
-		return 0;
+		werrstr("bad meta entry index");
+		return -1;
 	}
 
 	p = mb->buf + MetaHeaderSize + i*MetaIndexSize;
@@ -177,32 +177,32 @@
 
 if(0)print("eo = %d en = %d\n", eo, en);
 	if(eo < MetaHeaderSize + mb->maxindex*MetaIndexSize) {
-		vtSetError("corrupted entry in meta block");
-		return 0;
+		werrstr("corrupted entry in meta block");
+		return -1;
 	}
 
 	if(eo+en > mb->size) {
- 		vtSetError("truncated meta block");
-		return 0;
+ 		werrstr("truncated meta block");
+		return -1;
 	}
 
 	p = mb->buf + eo;
 	
 	/* make sure entry looks ok and includes an elem name */
 	if(en < 8 || U32GET(p) != DirMagic || en < 8 + U16GET(p+6)) {
-		vtSetError("corrupted meta block entry");
-		return 0;
+		werrstr("corrupted meta block entry");
+		return -1;
 	}
 
 	me->p = p;
 	me->size = en;
 
-	return 1;
+	return 0;
 }
 
 /* assumes a small amount of checking has been done in mbEntry */
 int
-meCmp(MetaEntry *me, char *s)
+mecmp(MetaEntry *me, char *s)
 {
 	int n;
 	uchar *p;
@@ -230,7 +230,7 @@
 }
 
 int
-meCmpNew(MetaEntry *me, char *s)
+mecmpnew(MetaEntry *me, char *s)
 {
 	int n;
 	uchar *p;
@@ -258,9 +258,9 @@
 }
 
 static int
-offsetCmp(void *s0, void *s1)
+offsetcmp(const void *s0, const void *s1)
 {
-	MetaChunk *mc0, *mc1;
+	const MetaChunk *mc0, *mc1;
 
 	mc0 = s0;
 	mc1 = s1;
@@ -272,13 +272,13 @@
 }
 
 static MetaChunk *
-metaChunks(MetaBlock *mb)
+metachunks(MetaBlock *mb)
 {
 	MetaChunk *mc;
 	int oo, o, n, i;
 	uchar *p;
 
-	mc = vtMemAlloc(mb->nindex*sizeof(MetaChunk));
+	mc = vtmalloc(mb->nindex*sizeof(MetaChunk));
 	p = mb->buf + MetaHeaderSize;
 	for(i = 0; i<mb->nindex; i++) {
 		mc[i].offset = U16GET(p);
@@ -287,7 +287,7 @@
 		p += MetaIndexSize;
 	}
 
-	qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp);
+	qsort(mc, mb->nindex, sizeof(MetaChunk), offsetcmp);
 
 	/* check block looks ok */
 	oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;
@@ -307,12 +307,12 @@
 
 	return mc;
 Err:
-	vtMemFree(mc);
+	vtfree(mc);
 	return nil;
 }
 
 static void
-mbCompact(MetaBlock *mb, MetaChunk *mc)
+mbcompact(MetaBlock *mb, MetaChunk *mc)
 {
 	int oo, o, n, i;
 
@@ -333,7 +333,7 @@
 }
 
 uchar *
-mbAlloc(MetaBlock *mb, int n)
+mballoc(MetaBlock *mb, int n)
 {
 	int i, o;
 	MetaChunk *mc;
@@ -346,33 +346,33 @@
 	if(mb->maxsize - mb->size + mb->free < n)
 		return nil;
 
-	mc = metaChunks(mb);
+	mc = metachunks(mb);
 
 	/* look for hole */
 	o = MetaHeaderSize + mb->maxindex*MetaIndexSize;
 	for(i=0; i<mb->nindex; i++) {
 		if(mc[i].offset - o >= n) {
-			vtMemFree(mc);
+			vtfree(mc);
 			return mb->buf + o;
 		}
 		o = mc[i].offset + mc[i].size;
 	}
 
 	if(mb->maxsize - o >= n) {
-		vtMemFree(mc);
+		vtfree(mc);
 		return mb->buf + o;
 	}
 
 	/* compact and return off the end */
-	mbCompact(mb, mc);
-	vtMemFree(mc);
+	mbcompact(mb, mc);
+	vtfree(mc);
 
 	assert(mb->maxsize - mb->size >= n);
 	return mb->buf + mb->size;
 }
 
 int
-vdSize(VacDir *dir)
+vdsize(VacDir *dir)
 {
 	int n;
 	
@@ -399,17 +399,17 @@
 	n += 2 + strlen(dir->mid);
 
 	/* optional sections */
-	if(dir->qidSpace) {
+	if(dir->qidspace) {
 		n += 	3 + 	/* option header */
-			8 + 	/* qidOffset */
-			8;	/* qid Max */
+			8 + 	/* qid offset */
+			8;	/* qid max */
 	}
 
 	return n;
 }
 
 void
-vdPack(VacDir *dir, MetaEntry *me)
+vdpack(VacDir *dir, MetaEntry *me)
 {
 	uchar *p;
 	ulong t32;
@@ -420,7 +420,7 @@
 	U16PUT(p+4, 9);		/* version */
 	p += 6;
 
-	p += stringPack(dir->elem, p);
+	p += stringpack(dir->elem, p);
 
 	U32PUT(p, dir->entry);
 	U32PUT(p+4, dir->gen);
@@ -429,9 +429,9 @@
 	U64PUT(p+16, dir->qid, t32);
 	p += 24;
 
-	p += stringPack(dir->uid, p);
-	p += stringPack(dir->gid, p);
-	p += stringPack(dir->mid, p);
+	p += stringpack(dir->uid, p);
+	p += stringpack(dir->gid, p);
+	p += stringpack(dir->mid, p);
 	
 	U32PUT(p, dir->mtime);
 	U32PUT(p+4, dir->mcount);
@@ -440,12 +440,12 @@
 	U32PUT(p+16, dir->mode);
 	p += 5*4;
 
-	if(dir->qidSpace) {
+	if(dir->qidspace) {
 		U8PUT(p, DirQidSpaceEntry);
 		U16PUT(p+1, 2*8);
 		p += 3;
-		U64PUT(p, dir->qidOffset, t32);
-		U64PUT(p+8, dir->qidMax, t32);
+		U64PUT(p, dir->qidoffset, t32);
+		U64PUT(p+8, dir->qidmax, t32);
 	}
 
 	assert(p == me->p + me->size);
@@ -453,7 +453,7 @@
 
 
 int
-vdUnpack(VacDir *dir, MetaEntry *me)
+vdunpack(VacDir *dir, MetaEntry *me)
 {
 	int t, nn, n, version;
 	uchar *p;
@@ -483,7 +483,7 @@
 if(0)print("vdUnpack: got version\n");
 
 	/* elem */
-	if(!stringUnpack(&dir->elem, &p, &n))
+	if(stringunpack(&dir->elem, &p, &n) < 0)
 		goto Err;
 
 if(0)print("vdUnpack: got elem\n");
@@ -532,15 +532,15 @@
 	}
 	
 	/* uid */
-	if(!stringUnpack(&dir->uid, &p, &n))
+	if(stringunpack(&dir->uid, &p, &n) < 0)
 		goto Err;
 
 	/* gid */
-	if(!stringUnpack(&dir->gid, &p, &n))
+	if(stringunpack(&dir->gid, &p, &n) < 0)
 		goto Err;
 
 	/* mid */
-	if(!stringUnpack(&dir->mid, &p, &n))
+	if(stringunpack(&dir->mid, &p, &n) < 0)
 		goto Err;
 
 if(0)print("vdUnpack: got ids\n");
@@ -584,11 +584,11 @@
 				break;
 			break;
 		case DirQidSpaceEntry:
-			if(dir->qidSpace || nn != 16)
+			if(dir->qidspace || nn != 16)
 				goto Err;
-			dir->qidSpace = 1;
-			dir->qidOffset = U64GET(p);
-			dir->qidMax = U64GET(p+8);
+			dir->qidspace = 1;
+			dir->qidoffset = U64GET(p);
+			dir->qidmax = U64GET(p+8);
 			break;
 		}
 		p += nn;
@@ -600,10 +600,112 @@
 		goto Err;
 
 if(0)print("vdUnpack: correct size\n");
-	return 1;
+	return 0;
 Err:
 if(0)print("vdUnpack: XXXXXXXXXXXX EbadMeta\n");
-	vtSetError(EBadMeta);
-	vdCleanup(dir);
-	return 0;
+	werrstr(EBadMeta);
+	vdcleanup(dir);
+	return -1;
+}
+
+void
+vdcleanup(VacDir *dir)
+{
+	vtfree(dir->elem);
+	dir->elem = nil;
+	vtfree(dir->uid);
+	dir->uid = nil;
+	vtfree(dir->gid);
+	dir->gid = nil;
+	vtfree(dir->mid);
+	dir->mid = nil;
+}
+
+void
+vdcopy(VacDir *dst, VacDir *src)
+{
+	*dst = *src;
+	dst->elem = vtstrdup(dst->elem);
+	dst->uid = vtstrdup(dst->uid);
+	dst->gid = vtstrdup(dst->gid);
+	dst->mid = vtstrdup(dst->mid);
+}
+
+int
+mbsearch(MetaBlock *mb, char *elem, int *ri, MetaEntry *me)
+{
+	int i;
+	int b, t, x;
+
+	/* binary search within block */
+	b = 0;
+	t = mb->nindex;
+	while(b < t) {
+		i = (b+t)>>1;
+		if(meunpack(me, mb, i) < 0)
+			return 0;
+		if(mb->unbotch)
+			x = mecmpnew(me, elem);
+		else
+			x = mecmp(me, elem);
+
+		if(x == 0) {
+			*ri = i;
+			return 1;
+		}
+	
+		if(x < 0)
+			b = i+1;
+		else /* x > 0 */
+			t = i;
+	}
+
+	assert(b == t);
+	
+	*ri = b;	/* b is the index to insert this entry */
+	memset(me, 0, sizeof(*me));
+
+	return 1;
+}
+
+void
+mbinit(MetaBlock *mb, uchar *p, int n)
+{
+	memset(mb, 0, sizeof(MetaBlock));
+	mb->maxsize = n;
+	mb->buf = p;
+	mb->maxindex = n/100;
+	mb->size = MetaHeaderSize + mb->maxindex*MetaIndexSize;
+}
+
+int
+mbresize(MetaBlock *mb, MetaEntry *me, int n)
+{
+	uchar *p, *ep;
+
+	/* easy case */
+	if(n <= me->size){
+		me->size = n;
+		return 0;
+	}
+
+	/* try and expand entry */
+
+	p = me->p + me->size;
+	ep = mb->buf + mb->maxsize;
+	while(p < ep && *p == 0)
+		p++;
+	if(n <= p - me->p){
+		me->size = n;
+		return 0;
+	}
+
+	p = mballoc(mb, n);
+	if(p != nil){
+		me->p = p;
+		me->size = n;
+		return 0;
+	}
+
+	return -1;
 }