aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/vac
diff options
context:
space:
mode:
authorRuss Cox <rsc@swtch.com>2008-06-14 13:28:49 -0400
committerRuss Cox <rsc@swtch.com>2008-06-14 13:28:49 -0400
commit64f9764ea9f958a1abc7a32424f43019723e9e53 (patch)
treecca50bfb352edfb70de5e63d98d2234aac598def /src/cmd/vac
parent01cea2ecb8c0b101a22e7883d87fbf1d28a03043 (diff)
downloadplan9port-64f9764ea9f958a1abc7a32424f43019723e9e53.tar.gz
plan9port-64f9764ea9f958a1abc7a32424f43019723e9e53.tar.bz2
plan9port-64f9764ea9f958a1abc7a32424f43019723e9e53.zip
vac: clean up, add unvac
Diffstat (limited to 'src/cmd/vac')
-rw-r--r--src/cmd/vac/README2
-rw-r--r--src/cmd/vac/file.c238
-rw-r--r--src/cmd/vac/fns.h8
-rw-r--r--src/cmd/vac/mkfile2
-rw-r--r--src/cmd/vac/pack.c85
-rw-r--r--src/cmd/vac/rtest.c71
-rw-r--r--src/cmd/vac/srcload.c302
-rw-r--r--src/cmd/vac/unvac.c293
-rw-r--r--src/cmd/vac/util.c71
-rw-r--r--src/cmd/vac/vac-orig.c1213
-rw-r--r--src/cmd/vac/vac.c84
-rw-r--r--src/cmd/vac/vac.h9
-rw-r--r--src/cmd/vac/vacfs.c176
-rw-r--r--src/cmd/vac/vactest.c182
-rw-r--r--src/cmd/vac/vtread.c126
-rw-r--r--src/cmd/vac/wtest.c47
16 files changed, 488 insertions, 2421 deletions
diff --git a/src/cmd/vac/README b/src/cmd/vac/README
deleted file mode 100644
index c8d68bd7..00000000
--- a/src/cmd/vac/README
+++ /dev/null
@@ -1,2 +0,0 @@
-This is somewhat untested but is believed to work.
-
diff --git a/src/cmd/vac/file.c b/src/cmd/vac/file.c
index 5f177d65..5e51c84a 100644
--- a/src/cmd/vac/file.c
+++ b/src/cmd/vac/file.c
@@ -564,8 +564,6 @@ vacfileread(VacFile *f, void *buf, int cnt, vlong offset)
VtBlock *b;
uchar *p;
-if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset);
-
if(filerlock(f) < 0)
return -1;
@@ -620,64 +618,6 @@ Err1:
return -1;
}
-#if 0
-/*
- * Changes the file block bn to be the given block score.
- * Very sneaky. Only used by flfmt.
- */
-int
-filemapblock(VacFile *f, ulong bn, uchar score[VtScoreSize], ulong tag)
-{
- VtBlock *b;
- VtEntry e;
- VtFile *s;
-
- if(filelock(f) < 0)
- return -1;
-
- s = nil;
- if(f->dir.mode & ModeDir){
- werrstr(ENotFile);
- goto Err;
- }
-
- if(f->source->mode != VtORDWR){
- werrstr(EReadOnly);
- goto Err;
- }
-
- if(vtfilelock(f->source, -1) < 0)
- goto Err;
-
- s = f->source;
- b = _vtfileblock(s, bn, VtORDWR, 1, tag);
- if(b == nil)
- goto Err;
-
- if(vtfilegetentry(s, &e) < 0)
- goto Err;
- if(b->l.type == BtDir){
- memmove(e.score, score, VtScoreSize);
- assert(e.tag == tag || e.tag == 0);
- e.tag = tag;
- e.flags |= VtEntryLocal;
- vtentrypack(&e, b->data, f->source->offset % f->source->epb);
- }else
- memmove(b->data + (bn%(e.psize/VtScoreSize))*VtScoreSize, score, VtScoreSize);
- /* vtblockdirty(b); */
- vtblockput(b);
- vtfileunlock(s);
- fileunlock(f);
- return 0;
-
-Err:
- if(s)
- vtfileunlock(s);
- fileunlock(f);
- return -1;
-}
-#endif
-
int
vacfilesetsize(VacFile *f, uvlong size)
{
@@ -713,8 +653,6 @@ filewrite(VacFile *f, void *buf, int cnt, vlong offset, char *uid)
uchar *p;
vlong eof;
-if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset);
-
if(filelock(f) < 0)
return -1;
@@ -1064,7 +1002,7 @@ vacfilemetaflush(VacFile *f, int rec)
vtfree(kids);
}
-/* assumes metaLock is held */
+/* assumes metalock is held */
static int
filemetaflush2(VacFile *f, char *oelem)
{
@@ -1097,15 +1035,14 @@ filemetaflush2(VacFile *f, char *oelem)
if(mbsearch(&mb, oelem, &i, &me) < 0)
goto Err;
- n = vdsize(&f->dir);
-if(0)fprint(2, "old size %d new size %d\n", me.size, n);
+ n = vdsize(&f->dir, VacDirVersion);
if(mbresize(&mb, &me, n) >= 0){
/* fits in the block */
mbdelete(&mb, i, &me);
if(strcmp(f->dir.elem, oelem) != 0)
mbsearch(&mb, f->dir.elem, &i, &me2);
- vdpack(&f->dir, &me);
+ vdpack(&f->dir, &me, VacDirVersion);
mbinsert(&mb, i, &me);
mbpack(&mb);
/* vtblockdirty(b); */
@@ -1126,19 +1063,17 @@ if(0)fprint(2, "old size %d new size %d\n", me.size, n);
*/
boff = filemetaalloc(fp, &f->dir, f->boff+1);
if(boff == NilBlock){
- /* mbResize might have modified block */
+ /* mbresize might have modified block */
mbpack(&mb);
/* vtblockdirty(b); */
goto Err;
}
-fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff);
f->boff = boff;
/* make sure deletion goes to disk after new entry */
bb = vtfileblock(fp->msource, f->boff, VtORDWR);
mbdelete(&mb, i, &me);
mbpack(&mb);
-/* blockDependency(b, bb, -1, nil, nil); */
vtblockput(bb);
/* vtblockdirty(b); */
vtblockput(b);
@@ -1522,6 +1457,16 @@ Return:
return ret;
}
+int
+vdeunread(VacDirEnum *vde)
+{
+ if(vde->i > 0){
+ vde->i--;
+ return 0;
+ }
+ return -1;
+}
+
void
vdeclose(VacDirEnum *vde)
{
@@ -1555,7 +1500,7 @@ filemetaalloc(VacFile *f, VacDir *dir, u32int start)
s = f->source;
ms = f->msource;
- n = vdsize(dir);
+ n = vdsize(dir, VacDirVersion);
nb = (vtfilegetsize(ms)+ms->dsize-1)/ms->dsize;
b = nil;
if(start > nb)
@@ -1584,9 +1529,8 @@ filemetaalloc(VacFile *f, VacDir *dir, u32int start)
p = mballoc(&mb, n);
if(p == nil){
- /* mbAlloc might have changed block */
+ /* mballoc might have changed block */
mbpack(&mb);
- /* vtblockdirty(b); */
werrstr(EBadMeta);
goto Err;
}
@@ -1595,29 +1539,10 @@ filemetaalloc(VacFile *f, VacDir *dir, u32int start)
assert(me.p == nil);
me.p = p;
me.size = n;
- vdpack(dir, &me);
+ vdpack(dir, &me, VacDirVersion);
mbinsert(&mb, i, &me);
mbpack(&mb);
-#ifdef notdef /* XXX */
- /* meta block depends on super block for qid ... */
- bb = cacheLocal(b->c, PartSuper, 0, VtOREAD);
- blockDependency(b, bb, -1, nil, nil);
- vtblockput(bb);
-
- /* ... and one or two dir entries */
- epb = s->dsize/VtEntrySize;
- bb = vtfileblock(s, dir->entry/epb, VtOREAD);
- blockDependency(b, bb, -1, nil, nil);
- vtblockput(bb);
- if(dir->mode & ModeDir){
- bb = sourceBlock(s, dir->mentry/epb, VtOREAD);
- blockDependency(b, bb, -1, nil, nil);
- vtblockput(bb);
- }
-#endif
-
- /* vtblockdirty(b); */
vtblockput(b);
return bo;
Err:
@@ -1676,7 +1601,7 @@ fileunlock(VacFile *f)
/*
* f->source and f->msource must NOT be locked.
- * fileMetaFlush locks the fileMeta and then the source (in fileMetaFlush2).
+ * vacfilemetaflush locks the filemeta and then the source (in filemetaflush2).
* We have to respect that ordering.
*/
static void
@@ -1736,130 +1661,3 @@ filewaccess(VacFile* f, char *mid)
*/
}
-#if 0
-static void
-markCopied(Block *b)
-{
- VtBlock *lb;
- Label l;
-
- if(globalToLocal(b->score) == NilBlock)
- return;
-
- if(!(b->l.state & BsCopied)){
- /*
- * We need to record that there are now pointers in
- * b that are not unique to b. We do this by marking
- * b as copied. Since we don't return the label block,
- * the caller can't get the dependencies right. So we have
- * to flush the block ourselves. This is a rare occurrence.
- */
- l = b->l;
- l.state |= BsCopied;
- lb = _blockSetLabel(b, &l);
- WriteAgain:
- while(!blockWrite(lb)){
- fprint(2, "getEntry: could not write label block\n");
- sleep(10*1000);
- }
- while(lb->iostate != BioClean && lb->iostate != BioDirty){
- assert(lb->iostate == BioWriting);
- vtSleep(lb->ioready);
- }
- if(lb->iostate == BioDirty)
- goto WriteAgain;
- vtblockput(lb);
- }
-}
-
-static int
-getEntry(VtFile *r, Entry *e, int mark)
-{
- Block *b;
-
- if(r == nil){
- memset(&e, 0, sizeof e);
- return 1;
- }
-
- b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, VtOREAD);
- if(b == nil)
- return 0;
- if(!entryUnpack(e, b->data, r->offset % r->epb)){
- vtblockput(b);
- return 0;
- }
-
- if(mark)
- markCopied(b);
- vtblockput(b);
- return 1;
-}
-
-static int
-setEntry(Source *r, Entry *e)
-{
- Block *b;
- Entry oe;
-
- b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, VtORDWR);
- if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score);
- if(b == nil)
- return 0;
- if(!entryUnpack(&oe, b->data, r->offset % r->epb)){
- vtblockput(b);
- return 0;
- }
- e->gen = oe.gen;
- entryPack(e, b->data, r->offset % r->epb);
-
- /* BUG b should depend on the entry pointer */
-
- markCopied(b);
- /* vtblockdirty(b); */
- vtblockput(b);
- return 1;
-}
-
-/* assumes hold elk */
-int
-fileSnapshot(VacFile *dst, VacFile *src, u32int epoch, int doarchive)
-{
- Entry e, ee;
-
- /* add link to snapshot */
- if(!getEntry(src->source, &e, 1) || !getEntry(src->msource, &ee, 1))
- return 0;
-
- e.snap = epoch;
- e.archive = doarchive;
- ee.snap = epoch;
- ee.archive = doarchive;
-
- if(!setEntry(dst->source, &e) || !setEntry(dst->msource, &ee))
- return 0;
- return 1;
-}
-
-int
-fileGetSources(VacFile *f, Entry *e, Entry *ee, int mark)
-{
- if(!getEntry(f->source, e, mark)
- || !getEntry(f->msource, ee, mark))
- return 0;
- return 1;
-}
-
-int
-fileWalkSources(VacFile *f)
-{
- if(f->mode == VtOREAD)
- return 1;
- if(!sourceLock2(f->source, f->msource, VtORDWR))
- return 0;
- vtfileunlock(f->source);
- vtfileunlock(f->msource);
- return 1;
-}
-
-#endif
diff --git a/src/cmd/vac/fns.h b/src/cmd/vac/fns.h
index 335d85c9..afcb7f7b 100644
--- a/src/cmd/vac/fns.h
+++ b/src/cmd/vac/fns.h
@@ -8,9 +8,13 @@ int meunpack(MetaEntry*, MetaBlock *mb, int i);
int mecmp(MetaEntry*, char *s);
int mecmpnew(MetaEntry*, char *s);
-int vdsize(VacDir *dir);
+enum {
+ VacDirVersion = 8,
+ FossilDirVersion = 9,
+};
+int vdsize(VacDir *dir, int);
int vdunpack(VacDir *dir, MetaEntry*);
-void vdpack(VacDir *dir, MetaEntry*);
+void vdpack(VacDir *dir, MetaEntry*, int);
VacFile *_vacfileroot(VacFs *fs, VtFile *file);
diff --git a/src/cmd/vac/mkfile b/src/cmd/vac/mkfile
index 1f8d9995..02f437e0 100644
--- a/src/cmd/vac/mkfile
+++ b/src/cmd/vac/mkfile
@@ -16,7 +16,7 @@ HFILES=\
dat.h\
fns.h\
-TARG=vac vacfs # vtdump
+TARG=vac vacfs unvac # vtdump
default:V: all
diff --git a/src/cmd/vac/pack.c b/src/cmd/vac/pack.c
index 319cb463..79811dfe 100644
--- a/src/cmd/vac/pack.c
+++ b/src/cmd/vac/pack.c
@@ -200,7 +200,7 @@ if(0)print("eo = %d en = %d\n", eo, en);
return 0;
}
-/* assumes a small amount of checking has been done in mbEntry */
+/* assumes a small amount of checking has been done in mbentry */
int
mecmp(MetaEntry *me, char *s)
{
@@ -372,18 +372,17 @@ mballoc(MetaBlock *mb, int n)
}
int
-vdsize(VacDir *dir)
+vdsize(VacDir *dir, int version)
{
int n;
- /* constant part */
+ if(version < 8 || version > 9)
+ sysfatal("bad version %d in vdpack", version);
+ /* constant part */
n = 4 + /* magic */
2 + /* version */
4 + /* entry */
- 4 + /* guid */
- 4 + /* mentry */
- 4 + /* mgen */
8 + /* qid */
4 + /* mtime */
4 + /* mcount */
@@ -392,6 +391,13 @@ vdsize(VacDir *dir)
4 + /* mode */
0;
+ if(version == 9){
+ n += 4 + /* gen */
+ 4 + /* mentry */
+ 4 + /* mgen */
+ 0;
+ }
+
/* strings */
n += 2 + strlen(dir->elem);
n += 2 + strlen(dir->uid);
@@ -399,35 +405,53 @@ vdsize(VacDir *dir)
n += 2 + strlen(dir->mid);
/* optional sections */
+ if(version < 9 && dir->plan9) {
+ n += 3 + /* option header */
+ 8 + /* path */
+ 4; /* version */
+ }
if(dir->qidspace) {
n += 3 + /* option header */
8 + /* qid offset */
8; /* qid max */
}
+ if(version < 9 && dir->gen) {
+ n += 3 + /* option header */
+ 4; /* gen */
+ }
return n;
}
void
-vdpack(VacDir *dir, MetaEntry *me)
+vdpack(VacDir *dir, MetaEntry *me, int version)
{
uchar *p;
ulong t32;
+ if(version < 8 || version > 9)
+ sysfatal("bad version %d in vdpack", version);
+
p = me->p;
U32PUT(p, DirMagic);
- U16PUT(p+4, 9); /* version */
+ U16PUT(p+4, version); /* version */
p += 6;
p += stringpack(dir->elem, p);
U32PUT(p, dir->entry);
- U32PUT(p+4, dir->gen);
- U32PUT(p+8, dir->mentry);
- U32PUT(p+12, dir->mgen);
- U64PUT(p+16, dir->qid, t32);
- p += 24;
+ p += 4;
+
+ if(version == 9){
+ U32PUT(p, dir->gen);
+ U32PUT(p+4, dir->mentry);
+ U32PUT(p+8, dir->mgen);
+ p += 12;
+ }
+
+ U64PUT(p, dir->qid, t32);
+ p += 8;
p += stringpack(dir->uid, p);
p += stringpack(dir->gid, p);
@@ -439,6 +463,15 @@ vdpack(VacDir *dir, MetaEntry *me)
U32PUT(p+12, dir->atime);
U32PUT(p+16, dir->mode);
p += 5*4;
+
+ if(dir->plan9 && version < 9) {
+ U8PUT(p, DirPlan9Entry);
+ U16PUT(p+1, 8+4);
+ p += 3;
+ U64PUT(p, dir->p9path, t32);
+ U32PUT(p+8, dir->p9version);
+ p += 12;
+ }
if(dir->qidspace) {
U8PUT(p, DirQidSpaceEntry);
@@ -446,12 +479,20 @@ vdpack(VacDir *dir, MetaEntry *me)
p += 3;
U64PUT(p, dir->qidoffset, t32);
U64PUT(p+8, dir->qidmax, t32);
+ p += 16;
+ }
+
+ if(dir->gen && version < 9) {
+ U8PUT(p, DirGenEntry);
+ U16PUT(p+1, 4);
+ p += 3;
+ U32PUT(p, dir->gen);
+ p += 4;
}
assert(p == me->p + me->size);
}
-
int
vdunpack(VacDir *dir, MetaEntry *me)
{
@@ -463,14 +504,12 @@ vdunpack(VacDir *dir, MetaEntry *me)
memset(dir, 0, sizeof(VacDir));
-if(0)print("vdUnpack\n");
/* magic */
if(n < 4 || U32GET(p) != DirMagic)
goto Err;
p += 4;
n -= 4;
-if(0)print("vdUnpack: got magic\n");
/* version */
if(n < 2)
goto Err;
@@ -480,14 +519,10 @@ if(0)print("vdUnpack: got magic\n");
p += 2;
n -= 2;
-if(0)print("vdUnpack: got version\n");
-
/* elem */
if(stringunpack(&dir->elem, &p, &n) < 0)
goto Err;
-if(0)print("vdUnpack: got elem\n");
-
/* entry */
if(n < 4)
goto Err;
@@ -495,8 +530,6 @@ if(0)print("vdUnpack: got elem\n");
p += 4;
n -= 4;
-if(0)print("vdUnpack: got entry\n");
-
if(version < 9) {
dir->gen = 0;
dir->mentry = dir->entry+1;
@@ -511,8 +544,6 @@ if(0)print("vdUnpack: got entry\n");
n -= 3*4;
}
-if(0)print("vdUnpack: got gen etc\n");
-
/* size is gotten from DirEntry */
/* qid */
@@ -522,7 +553,6 @@ if(0)print("vdUnpack: got gen etc\n");
p += 8;
n -= 8;
-if(0)print("vdUnpack: got qid\n");
/* skip replacement */
if(version == 7) {
if(n < VtScoreSize)
@@ -543,7 +573,6 @@ if(0)print("vdUnpack: got qid\n");
if(stringunpack(&dir->mid, &p, &n) < 0)
goto Err;
-if(0)print("vdUnpack: got ids\n");
if(n < 5*4)
goto Err;
dir->mtime = U32GET(p);
@@ -554,7 +583,6 @@ if(0)print("vdUnpack: got ids\n");
p += 5*4;
n -= 5*4;
-if(0)print("vdUnpack: got times\n");
/* optional meta data */
while(n > 0) {
if(n < 3)
@@ -594,15 +622,12 @@ if(0)print("vdUnpack: got times\n");
p += nn;
n -= nn;
}
-if(0)print("vdUnpack: got options\n");
if(p != me->p + me->size)
goto Err;
-if(0)print("vdUnpack: correct size\n");
return 0;
Err:
-if(0)print("vdUnpack: XXXXXXXXXXXX EbadMeta\n");
werrstr(EBadMeta);
vdcleanup(dir);
return -1;
diff --git a/src/cmd/vac/rtest.c b/src/cmd/vac/rtest.c
deleted file mode 100644
index 81143337..00000000
--- a/src/cmd/vac/rtest.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include "stdinc.h"
-
-enum {
- Nblock = 300000,
- BlockSize = 8*1024
-};
-
-uchar data[Nblock*VtScoreSize];
-int rflag;
-int nblock = 10000;
-int perm[Nblock];
-
-void
-main(int argc, char *argv[])
-{
- VtSession *z;
- int i, j, t;
- int start;
- uchar buf[BlockSize];
-
- srand(time(0));
-
- ARGBEGIN{
- case 'r':
- rflag++;
- break;
- case 'n':
- nblock = atoi(ARGF());
- break;
- }ARGEND
-
- for(i=0; i<nblock; i++)
- perm[i] = i;
-
- if(rflag) {
- for(i=0; i<nblock; i++) {
- j = nrand(nblock);
- t = perm[j];
- perm[j] = perm[i];
- perm[i] = t;
- }
- }
-
- if(readn(0, data, VtScoreSize*nblock) < VtScoreSize*nblock)
- sysfatal("read failed: %r");
-
- vtAttach();
-
- z = vtDial("iolaire2");
- if(z == nil)
- sysfatal("cound not connect to venti");
- if(!vtConnect(z, 0))
- vtFatal("vtConnect: %s", vtGetError());
-
- print("starting\n");
-
- start = times(0);
-
- if(rflag && nblock > 10000)
- nblock = 10000;
-
- for(i=0; i<nblock; i++) {
- if(vtRead(z, data+perm[i]*VtScoreSize, VtDataType, buf, BlockSize) < 0)
- vtFatal("vtRead failed: %d: %s", i, vtGetError());
- }
-
- print("time = %f\n", (times(0) - start)*0.001);
-
- vtClose(z);
- vtDetach();
-}
diff --git a/src/cmd/vac/srcload.c b/src/cmd/vac/srcload.c
deleted file mode 100644
index 8f3b2a0c..00000000
--- a/src/cmd/vac/srcload.c
+++ /dev/null
@@ -1,302 +0,0 @@
-#include "stdinc.h"
-#include <bio.h>
-#include "vac.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-
-int num = 1000;
-int length = 20*1024;
-int block= 1024;
-int bush = 4;
-int iter = 10000;
-Biobuf *bout;
-int maxdepth;
-
-Source *mkroot(Cache*);
-void new(Source*, int trace, int);
-int delete(Source*);
-void dump(Source*, int indent, ulong nentry);
-void dumpone(Source *s);
-int count(Source *s, int);
-void stats(Source *s);
-
-void
-main(int argc, char *argv[])
-{
- int i;
- Cache *c;
- char *host = nil;
- VtSession *z;
- int csize = 10000;
- Source *r;
- ulong t;
-
- t = time(0);
- fprint(1, "time = %lud\n", t);
-
- srand(t);
-
- ARGBEGIN{
- case 'i':
- iter = atoi(ARGF());
- break;
- case 'n':
- num = atoi(ARGF());
- break;
- case 'l':
- length = atoi(ARGF());
- break;
- case 'b':
- block = atoi(ARGF());
- break;
- case 'h':
- host = ARGF();
- break;
- case 'u':
- bush = atoi(ARGF());
- break;
- case 'c':
- csize = atoi(ARGF());
- break;
- }ARGEND;
-
- vtAttach();
-
- bout = vtMemAllocZ(sizeof(Biobuf));
- Binit(bout, 1, OWRITE);
-
- fmtinstall('V', vtScoreFmt);
- fmtinstall('R', vtErrFmt);
-
- z = vtDial(host);
- if(z == nil)
- vtFatal("could not connect to server: %s", vtGetError());
-
- if(!vtConnect(z, 0))
- sysfatal("vtConnect: %r");
-
- c = cacheAlloc(z, block, csize);
- r = mkroot(c);
- for(i=0; i<num; i++)
- new(r, 0, 0);
-
- for(i=0; i<iter; i++) {
-if(i % 10000 == 0)
-stats(r);
- new(r, 0, 0);
- delete(r);
- }
-
- fprint(2, "count = %d top = %lud\n", count(r, 0), sourceGetDirSize(r));
-/* cacheCheck(c); */
-fprint(2, "deleting\n");
- for(i=0; i<num; i++)
- delete(r);
-
-/* dump(r, 0, 0); */
-
- lumpDecRef(r->lump, 0);
- sourceRemove(r);
- cacheCheck(c);
-
- vtClose(z);
- vtDetach();
-
- exits(0);
-}
-
-
-Source *
-mkroot(Cache *c)
-{
- Lump *u;
- VtEntry *dir;
- Source *r;
-
- u = cacheAllocLump(c, VtDirType, cacheGetBlockSize(c), 1);
- dir = (VtEntry*)u->data;
- vtPutUint16(dir->psize, cacheGetBlockSize(c));
- vtPutUint16(dir->dsize, cacheGetBlockSize(c));
- dir->flag = VtEntryActive|VtEntryDir;
- memmove(dir->score, vtZeroScore, VtScoreSize);
-
- r = sourceAlloc(c, u, 0, 0);
- vtUnlock(u->lk);
- if(r == nil)
- sysfatal("could not create root source: %r");
- return r;
-}
-
-void
-new(Source *s, int trace, int depth)
-{
- int i, n;
- Source *ss;
-
- if(depth > maxdepth)
- maxdepth = depth;
-
- n = sourceGetDirSize(s);
- for(i=0; i<n; i++) {
- ss = sourceOpen(s, nrand(n), 0);
- if(ss == nil)
- continue;
- if(ss->dir && frand() < 1./bush) {
- if(trace) {
- int j;
- for(j=0; j<trace; j++)
- Bprint(bout, " ");
- Bprint(bout, "decend %d\n", i);
- }
- new(ss, trace?trace+1:0, depth+1);
- sourceFree(ss);
- return;
- }
- sourceFree(ss);
- }
- ss = sourceCreate(s, s->psize, s->dsize, 1+frand()>.5, 0);
- if(ss == nil)
- fprint(2, "could not create directory: %r\n");
- if(trace) {
- int j;
- for(j=1; j<trace; j++)
- Bprint(bout, " ");
- Bprint(bout, "create %d %V\n", ss->entry, ss->lump->score);
- }
- sourceFree(ss);
-}
-
-int
-delete(Source *s)
-{
- int i, n;
- Source *ss;
-
- assert(s->dir);
-
- n = sourceGetDirSize(s);
- /* check if empty */
- for(i=0; i<n; i++) {
- ss = sourceOpen(s, i, 1);
- if(ss != nil) {
- sourceFree(ss);
- break;
- }
- }
- if(i == n)
- return 0;
-
- for(;;) {
- ss = sourceOpen(s, nrand(n), 0);
- if(ss == nil)
- continue;
- if(ss->dir && delete(ss)) {
- sourceFree(ss);
- return 1;
- }
- if(1)
- break;
- sourceFree(ss);
- }
-
-
- sourceRemove(ss);
- return 1;
-}
-
-void
-dumpone(Source *s)
-{
- ulong i, n;
- Source *ss;
-
- Bprint(bout, "gen %4lud depth %d %V", s->gen, s->depth, s->lump->score);
- if(!s->dir) {
- Bprint(bout, " data size: %llud\n", s->size);
- return;
- }
- n = sourceGetDirSize(s);
- Bprint(bout, " dir size: %lud\n", n);
- for(i=0; i<n; i++) {
- ss = sourceOpen(s, i, 1);
- if(ss == nil) {
-fprint(2, "%lud: %r\n", i);
- continue;
- }
- Bprint(bout, "\t%lud %d %llud %V\n", i, ss->dir, ss->size, ss->lump->score);
- sourceFree(ss);
- }
- return;
-}
-
-
-void
-dump(Source *s, int ident, ulong entry)
-{
- ulong i, n;
- Source *ss;
-
- for(i=0; i<ident; i++)
- Bprint(bout, " ");
- Bprint(bout, "%4lud: gen %4lud depth %d", entry, s->gen, s->depth);
- if(!s->dir) {
- Bprint(bout, " data size: %llud\n", s->size);
- return;
- }
- n = sourceGetDirSize(s);
- Bprint(bout, " dir size: %lud\n", n);
- for(i=0; i<n; i++) {
- ss = sourceOpen(s, i, 1);
- if(ss == nil)
- continue;
- dump(ss, ident+1, i);
- sourceFree(ss);
- }
- return;
-}
-
-int
-count(Source *s, int rec)
-{
- ulong i, n;
- int c;
- Source *ss;
-
- if(!s->dir)
- return 0;
- n = sourceGetDirSize(s);
- c = 0;
- for(i=0; i<n; i++) {
- ss = sourceOpen(s, i, 1);
- if(ss == nil)
- continue;
- if(rec)
- c += count(ss, rec);
- c++;
- sourceFree(ss);
- }
- return c;
-}
-
-void
-stats(Source *s)
-{
- int n, i, c, cc, max;
- Source *ss;
-
- cc = 0;
- max = 0;
- n = sourceGetDirSize(s);
- for(i=0; i<n; i++) {
- ss = sourceOpen(s, i, 1);
- if(ss == nil)
- continue;
- cc++;
- c = count(ss, 1);
- if(c > max)
- max = c;
- sourceFree(ss);
- }
-fprint(2, "count = %d top = %d depth=%d maxcount %d\n", cc, n, maxdepth, max);
-}
diff --git a/src/cmd/vac/unvac.c b/src/cmd/vac/unvac.c
new file mode 100644
index 00000000..a2ac2155
--- /dev/null
+++ b/src/cmd/vac/unvac.c
@@ -0,0 +1,293 @@
+#include "stdinc.h"
+#include <auth.h>
+#include <fcall.h>
+#include <thread.h>
+#include "vac.h"
+
+VacFs *fs;
+int tostdout;
+int nwant;
+char **want;
+int *found;
+int chatty;
+VtConn *conn;
+int errors;
+int settimes;
+int table;
+
+int mtimefmt(Fmt*);
+void unvac(VacFile*, char*, VacDir*);
+
+void
+usage(void)
+{
+ fprint(2, "usage: unvac [-TVctv] [-h host] file.vac [file ...]\n");
+ threadexitsall("usage");
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ int i;
+ char *host;
+ VacFile *f;
+
+ fmtinstall('H', encodefmt);
+ fmtinstall('V', vtscorefmt);
+ fmtinstall('F', vtfcallfmt);
+ fmtinstall('T', mtimefmt);
+ fmtinstall('M', dirmodefmt);
+
+ host = nil;
+ ARGBEGIN{
+ case 'T':
+ settimes = 1;
+ break;
+ case 'V':
+ chattyventi = 1;
+ break;
+ case 'c':
+ tostdout++;
+ break;
+ case 'h':
+ host = EARGF(usage());
+ break;
+ case 't':
+ table++;
+ break;
+ case 'v':
+ chatty++;
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(argc < 1)
+ usage();
+
+ conn = vtdial(host);
+ if(conn == nil)
+ sysfatal("could not connect to server: %r");
+
+ if(vtconnect(conn) < 0)
+ sysfatal("vtconnect: %r");
+
+ fs = vacfsopen(conn, argv[0], VtOREAD, 128);
+ if(fs == nil)
+ sysfatal("vacfsopen: %r");
+
+ nwant = argc-1;
+ want = argv+1;
+ found = vtmallocz(nwant*sizeof found[0]);
+
+ if((f = vacfsgetroot(fs)) == nil)
+ sysfatal("vacfsgetroot: %r");
+
+ unvac(f, nil, nil);
+ for(i=0; i<nwant; i++){
+ if(want[i] && !found[i]){
+ fprint(2, "warning: didn't find %s\n", want[i]);
+ errors++;
+ }
+ }
+ if(errors)
+ threadexitsall("errors");
+ threadexitsall(0);
+}
+
+int
+writen(int fd, char *buf, int n)
+{
+ int m;
+ int oldn;
+
+ oldn = n;
+ while(n > 0){
+ m = write(fd, buf, n);
+ if(m <= 0)
+ return -1;
+ buf += m;
+ n -= m;
+ }
+ return oldn;
+}
+
+int
+wantfile(char *name)
+{
+ int i, namelen, n;
+
+ if(nwant == 0)
+ return 1;
+
+ namelen = strlen(name);
+ for(i=0; i<nwant; i++){
+ if(want[i] == nil)
+ continue;
+ n = strlen(want[i]);
+ if(n < namelen && name[n] == '/' && memcmp(name, want[i], n) == 0)
+ return 1;
+ if(namelen < n && want[i][namelen] == '/' && memcmp(want[i], name, n) == 0)
+ return 1;
+ if(n == namelen && memcmp(name, want[i], n) == 0){
+ found[i] = 1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void
+unvac(VacFile *f, char *name, VacDir *vdir)
+{
+ static char buf[65536];
+ int fd, mode, n, mode9;
+ char *newname;
+ char *what;
+ vlong off;
+ Dir d, *dp;
+ VacDirEnum *vde;
+ VacDir newvdir;
+ VacFile *newf;
+
+ if(vdir)
+ mode = vdir->mode;
+ else
+ mode = vacfilegetmode(f);
+
+ if(vdir){
+ if(table){
+ if(chatty){
+ mode9 = vdir->mode&0777;
+ if(mode&ModeDir)
+ mode9 |= DMDIR;
+ if(mode&ModeLink)
+ mode9 |= DMSYMLINK;
+ if(mode&ModeAppend)
+ mode9 |= DMAPPEND;
+ if(mode&ModeExclusive)
+ mode9 |= DMEXCL;
+ if(mode&ModeNamedPipe)
+ mode9 |= DMNAMEDPIPE;
+ if(mode&ModeSetUid)
+ mode9 |= DMSETUID;
+ if(mode&ModeSetGid)
+ mode9 |= DMSETGID;
+ if(mode&ModeDevice)
+ mode9 |= DMDEVICE;
+ print("%M %-10s %-10s %11lld %T %s\n",
+ mode9, vdir->uid, vdir->gid, vdir->size,
+ vdir->mtime, name);
+ }else
+ print("%s%s\n", name, (mode&ModeDir) ? "/" : "");
+ }
+ else if(chatty)
+ fprint(2, "%s%s\n", name, (mode&ModeDir) ? "/" : "");
+ }
+
+ if(mode&(ModeDevice|ModeLink|ModeNamedPipe|ModeExclusive)){
+ if(table)
+ return;
+ if(mode&ModeDevice)
+ what = "device";
+ else if(mode&ModeLink)
+ what = "link";
+ else if(mode&ModeNamedPipe)
+ what = "named pipe";
+ else if(mode&ModeExclusive)
+ what = "lock";
+ else
+ what = "unknown type of file";
+ fprint(2, "warning: ignoring %s %s\n", what, name);
+ return;
+ }
+
+ if(mode&ModeDir){
+ if((vde = vdeopen(f)) == nil){
+ fprint(2, "vdeopen %s: %r", name);
+ errors++;
+ return;
+ }
+ if(!table && !tostdout && vdir){
+ // create directory
+ if((dp = dirstat(name)) == nil){
+ if((fd = create(name, OREAD, DMDIR|(mode&0777))) < 0){
+ fprint(2, "mkdir %s: %r\n", name);
+ vdeclose(vde);
+ }
+ close(fd);
+ }else{
+ if(!(dp->mode&DMDIR)){
+ fprint(2, "%s already exists and is not a directory\n", name);
+ errors++;
+ free(dp);
+ vdeclose(vde);
+ return;
+ }
+ free(dp);
+ }
+ }
+ while(vderead(vde, &newvdir) > 0){
+ if(name == nil)
+ newname = newvdir.elem;
+ else
+ newname = smprint("%s/%s", name, newvdir.elem);
+ if(wantfile(newname)){
+ if((newf = vacfilewalk(f, newvdir.elem)) == nil){
+ fprint(2, "walk %s: %r\n", name);
+ errors++;
+ }else if(newf == f){
+ fprint(2, "walk loop: %s\n", newname);
+ vacfiledecref(newf);
+ }else{
+ unvac(newf, newname, &newvdir);
+ vacfiledecref(newf);
+ }
+ }
+ if(newname != newvdir.elem)
+ free(newname);
+ vdcleanup(&newvdir);
+ }
+ vdeclose(vde);
+ }else{
+ if(!table){
+ if(tostdout)
+ fd = dup(1, -1);
+ else if((fd = create(name, OWRITE, mode&0777)) < 0){
+ fprint(2, "create %s: %r\n", name);
+ errors++;
+ return;
+ }
+ off = 0;
+ while((n = vacfileread(f, buf, sizeof buf, off)) > 0){
+ if(writen(fd, buf, n) != n){
+ fprint(2, "write %s: %r\n", name);
+ errors++;
+ close(fd);
+ remove(name);
+ return;
+ }
+ off += n;
+ }
+ close(fd);
+ }
+ }
+ if(vdir && settimes && !tostdout){
+ nulldir(&d);
+ d.mtime = vdir->mtime;
+ if(dirwstat(name, &d) < 0)
+ fprint(2, "warning: setting mtime on %s: %r", name);
+ }
+}
+
+int
+mtimefmt(Fmt *f)
+{
+ Tm *tm;
+
+ tm = localtime(va_arg(f->args, ulong));
+ fmtprint(f, "%04d-%02d-%02d %02d:%02d",
+ tm->year+1900, tm->mon+1, tm->mday,
+ tm->hour, tm->min);
+ return 0;
+}
diff --git a/src/cmd/vac/util.c b/src/cmd/vac/util.c
deleted file mode 100644
index f52acf60..00000000
--- a/src/cmd/vac/util.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include "stdinc.h"
-#include "vac.h"
-#include "dat.h"
-#include "fns.h"
-
-int
-vtGetUint16(uchar *p)
-{
- return (p[0]<<8)|p[1];
-}
-
-ulong
-vtGetUint32(uchar *p)
-{
- return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
-}
-
-uvlong
-vtGetUint48(uchar *p)
-{
- return ((uvlong)p[0]<<40)|((uvlong)p[1]<<32)|
- (p[2]<<24)|(p[3]<<16)|(p[4]<<8)|p[5];
-}
-
-uvlong
-vtGetUint64(uchar *p)
-{
- return ((uvlong)p[0]<<56)|((uvlong)p[1]<<48)|((uvlong)p[2]<<40)|
- ((uvlong)p[3]<<32)|(p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7];
-}
-
-
-void
-vtPutUint16(uchar *p, int x)
-{
- p[0] = x>>8;
- p[1] = x;
-}
-
-void
-vtPutUint32(uchar *p, ulong x)
-{
- p[0] = x>>24;
- p[1] = x>>16;
- p[2] = x>>8;
- p[3] = x;
-}
-
-void
-vtPutUint48(uchar *p, uvlong x)
-{
- p[0] = x>>40;
- p[1] = x>>32;
- p[2] = x>>24;
- p[3] = x>>16;
- p[4] = x>>8;
- p[5] = x;
-}
-
-void
-vtPutUint64(uchar *p, uvlong x)
-{
- p[0] = x>>56;
- p[1] = x>>48;
- p[2] = x>>40;
- p[3] = x>>32;
- p[4] = x>>24;
- p[5] = x>>16;
- p[6] = x>>8;
- p[7] = x;
-}
diff --git a/src/cmd/vac/vac-orig.c b/src/cmd/vac/vac-orig.c
deleted file mode 100644
index 637c49c0..00000000
--- a/src/cmd/vac/vac-orig.c
+++ /dev/null
@@ -1,1213 +0,0 @@
-#include "stdinc.h"
-#include "vac.h"
-#include "dat.h"
-#include "fns.h"
-
-typedef struct Sink Sink;
-typedef struct MetaSink MetaSink;
-typedef struct DirSink DirSink;
-
-struct Sink {
- VtSession *z;
- VtEntry dir;
- uchar *buf;
- uchar *pbuf[VtPointerDepth+1];
-};
-
-struct DirSink {
- Sink *sink;
- MetaSink *msink;
- ulong nentry;
- uchar *buf;
- uchar *p; /* current pointer */
- uchar *ep; /* end pointer */
-};
-
-struct MetaSink {
- Sink *sink;
- uchar *buf;
- int maxindex;
- int nindex;
- uchar *rp; /* start of current record */
- uchar *p; /* current pointer */
- uchar *ep; /* end pointer */
-};
-
-static void usage(void);
-static int strpCmp(void*, void*);
-static void warn(char *fmt, ...);
-static void cleanup(void);
-static u64int unittoull(char *s);
-static int vac(VtSession *z, char *argv[]);
-static void vacFile(DirSink *dsink, char *lname, char *sname, VacFile*);
-static void vacStdin(DirSink *dsink, char *name, VacFile *vf);
-static void vacData(DirSink *dsink, int fd, char *lname, VacFile*, Dir*);
-static void vacDir(DirSink *dsink, int fd, char *lname, char *sname, VacFile*);
-static int vacMerge(DirSink *dsink, char *lname, char *sname);
-
-Sink *sinkAlloc(VtSession *z, int psize, int dsize);
-void sinkWrite(Sink *k, uchar *data, int n);
-void sinkWriteScore(Sink *k, uchar *score, int n);
-void sinkClose(Sink *k);
-void sinkFree(Sink *k);
-
-DirSink *dirSinkAlloc(VtSession *z, int psize, int dsize);
-void dirSinkWrite(DirSink *k, VtEntry*);
-void dirSinkWriteSink(DirSink *k, Sink*);
-int dirSinkWriteFile(DirSink *k, VacFile *vf);
-void dirSinkClose(DirSink *k);
-void dirSinkFree(DirSink *k);
-
-MetaSink *metaSinkAlloc(VtSession *z, int psize, int dsize);
-void metaSinkPutc(MetaSink *k, int c);
-void metaSinkPutString(MetaSink *k, char *s);
-void metaSinkPutUint32(MetaSink *k, ulong x);
-void metaSinkPutUint64(MetaSink *k, uvlong x);
-void metaSinkWrite(MetaSink *k, uchar *data, int n);
-void metaSinkWriteDir(MetaSink *ms, VacDir *vd);
-void metaSinkEOR(MetaSink *k);
-void metaSinkClose(MetaSink *k);
-void metaSinkFree(MetaSink *k);
-void plan9ToVacDir(VacDir*, Dir*, ulong entry, uvlong qid);
-
-enum {
- Version = 8,
- BlockSize = 8*1024,
- MaxExclude = 1000
-};
-
-struct {
- ulong file;
- ulong sfile;
- ulong data;
- ulong sdata;
- ulong skip;
- ulong meta;
-} stats;
-
-int bsize = BlockSize;
-int maxbsize;
-char *oname, *dfile;
-int verbose;
-uvlong fileid = 1;
-int qdiff;
-char *exclude[MaxExclude];
-int nexclude;
-int nowrite;
-int merge;
-char *isi;
-
-void
-main(int argc, char *argv[])
-{
- VtSession *z;
- char *p;
- char *host = nil;
- int statsFlag = 0;
-
- atexit(cleanup);
-
- ARGBEGIN{
- default:
- usage();
- case 'b':
- p = ARGF();
- if(p == 0)
- usage();
- bsize = unittoull(p);
- if(bsize == ~0)
- usage();
- break;
- case 'd':
- dfile = ARGF();
- if(dfile == nil)
- usage();
- break;
- case 'e':
- if(nexclude >= MaxExclude)
- sysfatal("too many exclusions\n");
- exclude[nexclude] = ARGF();
- if(exclude[nexclude] == nil)
- usage();
- nexclude++;
- break;
- case 'f':
- oname = ARGF();
- if(oname == 0)
- usage();
- break;
- case 'h':
- host = ARGF();
- if(host == nil)
- usage();
- break;
- case 'i':
- isi = ARGF();
- if(isi == nil)
- usage();
- break;
- case 'n':
- nowrite++;
- break;
- case 'm':
- merge++;
- break;
- case 'q':
- qdiff++;
- break;
- case 's':
- statsFlag++;
- break;
- case 'v':
- verbose++;
- break;
- }ARGEND;
-
- if(bsize < 512)
- bsize = 512;
- if(bsize > VtMaxLumpSize)
- bsize = VtMaxLumpSize;
- maxbsize = bsize;
-
- vtAttach();
-
- fmtinstall('V', vtScoreFmt);
- fmtinstall('R', vtErrFmt);
-
- z = vtDial(host, 0);
- if(z == nil)
- vtFatal("could not connect to server: %R");
-
- if(!vtConnect(z, 0))
- vtFatal("vtConnect: %R");
-
- qsort(exclude, nexclude, sizeof(char*), strpCmp);
-
- vac(z, argv);
- if(!vtSync(z))
- fprint(2, "warning: could not ask server to flush pending writes: %R\n");
-
- if(statsFlag)
- fprint(2, "files %ld:%ld data %ld:%ld:%ld meta %ld\n", stats.file, stats.sfile,
- stats.data, stats.skip, stats.sdata, stats.meta);
-/*packetStats(); */
- vtClose(z);
- vtDetach();
-
- exits(0);
-}
-
-void
-static usage(void)
-{
- fprint(2, "usage: %s [-amqsv] [-h host] [-d vacfile] [-b blocksize] [-i name] [-e exclude] [-f vacfile] file ... \n", argv0);
- exits("usage");
-}
-
-static
-int strpCmp(void *p0, void *p1)
-{
- return strcmp(*(char**)p0, *(char**)p1);
-}
-
-
-int
-readBlock(int fd, uchar *buf, int n)
-{
- int m, t = 0;
-
- while(t < n){
- m = read(fd, buf+t, n-t);
- if(m < 0)
- return -1;
- if(m == 0)
- break;
- t += m;
- }
- return t;
-}
-
-int
-vacWrite(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n)
-{
-assert(n > 0);
- if(nowrite) {
- vtSha1(score, buf, n);
- return 1;
- }
- if(!vtWrite(z, score, type, buf, n))
- return 0;
- if(!vtSha1Check(score, buf, n)) {
- uchar score2[VtScoreSize];
-
- vtSha1(score2, buf, n);
-fprint(2, "vtSha1Check: n = %d %V %V\n", n, score, score2);
- vtSetError("vtSha1Check failed");
- return 0;
- }
- return 1;
-}
-
-
-static int
-vac(VtSession *z, char *argv[])
-{
- DirSink *dsink, *ds;
- MetaSink *ms;
- VtRoot root;
- uchar score[VtScoreSize], buf[VtRootSize];
- char cwd[2048];
- int cd, i;
- char *cp2, *cp;
- VacFS *fs;
- VacFile *vff;
- int fd;
- Dir *dir;
- VacDir vd;
-
- if(getwd(cwd, sizeof(cwd)) == 0)
- sysfatal("can't find current directory: %r\n");
-
- dsink = dirSinkAlloc(z, bsize, bsize);
-
- fs = nil;
- if(dfile != nil) {
- fs = vfsOpen(z, dfile, 1, 10000);
- if(fs == nil)
- fprint(2, "could not open diff: %s: %s\n", dfile, vtGetError());
- }
-
-
- if(oname != nil) {
- fd = create(oname, OWRITE, 0666);
- if(fd < 0)
- sysfatal("could not create file: %s: %r", oname);
- } else
- fd = 1;
-
- dir = dirfstat(fd);
- if(dir == nil)
- sysfatal("dirfstat failed: %r");
-
- for(; *argv; argv++) {
- cp2 = *argv;
- cd = 0;
- for (cp = *argv; *cp; cp++)
- if (*cp == '/')
- cp2 = cp;
- if (cp2 != *argv) {
- *cp2 = '\0';
- chdir(*argv);
- *cp2 = '/';
- cp2++;
- cd = 1;
- }
- vff = nil;
- if(fs)
- vff = vfOpen(fs, cp2);
- vacFile(dsink, argv[0], cp2, vff);
- if(vff)
- vfDecRef(vff);
- if(cd && chdir(cwd) < 0)
- sysfatal("can't cd back to %s: %r\n", cwd);
- }
-
- if(isi) {
- vff = nil;
- if(fs)
- vff = vfOpen(fs, isi);
- vacStdin(dsink, isi, vff);
- if(vff)
- vfDecRef(vff);
- }
-
- dirSinkClose(dsink);
-
- /* build meta information for the root */
- ms = metaSinkAlloc(z, bsize, bsize);
- /* fake into a directory */
- dir->mode |= (dir->mode&0444)>>2;
- dir->qid.type |= QTDIR;
- dir->mode |= DMDIR;
- plan9ToVacDir(&vd, dir, 0, fileid++);
- if(strcmp(vd.elem, "/") == 0){
- vtMemFree(vd.elem);
- vd.elem = vtStrDup("root");
- }
- metaSinkWriteDir(ms, &vd);
- vdCleanup(&vd);
- metaSinkClose(ms);
-
- ds = dirSinkAlloc(z, bsize, bsize);
- dirSinkWriteSink(ds, dsink->sink);
- dirSinkWriteSink(ds, dsink->msink->sink);
- dirSinkWriteSink(ds, ms->sink);
- dirSinkClose(ds);
-
- memset(&root, 0, sizeof(root));
- root.version = VtRootVersion;
- strncpy(root.name, dir->name, sizeof(root.name));
- root.name[sizeof(root.name)-1] = 0;
- free(dir);
- sprint(root.type, "vac");
- memmove(root.score, ds->sink->dir.score, VtScoreSize);
- root.blockSize = maxbsize;
- if(fs != nil)
- vfsGetScore(fs, root.prev);
-
- metaSinkFree(ms);
- dirSinkFree(ds);
- dirSinkFree(dsink);
- if(fs != nil)
- vfsClose(fs);
-
- vtRootPack(&root, buf);
- if(!vacWrite(z, score, VtRootType, buf, VtRootSize))
- vtFatal("vacWrite failed: %s", vtGetError());
-
- fprint(fd, "vac:");
- for(i=0; i<VtScoreSize; i++)
- fprint(fd, "%.2x", score[i]);
- fprint(fd, "\n");
-
- /* avoid remove at cleanup */
- oname = nil;
- return 1;
-}
-
-static int
-isExcluded(char *name)
-{
- int bot, top, i, x;
-
- bot = 0;
- top = nexclude;
- while(bot < top) {
- i = (bot+top)>>1;
- x = strcmp(exclude[i], name);
- if(x == 0)
- return 1;
- if(x < 0)
- bot = i + 1;
- else /* x > 0 */
- top = i;
- }
- return 0;
-}
-
-static void
-vacFile(DirSink *dsink, char *lname, char *sname, VacFile *vf)
-{
- int fd;
- Dir *dir;
- VacDir vd;
- ulong entry;
-
- if(isExcluded(lname)) {
- warn("excluding: %s", lname);
- return;
- }
-
- if(merge && vacMerge(dsink, lname, sname))
- return;
-
- fd = open(sname, OREAD);
- if(fd < 0) {
- warn("could not open file: %s: %s", lname, vtOSError());
- return;
- }
-
- if(verbose)
- fprint(2, "%s\n", lname);
-
- dir = dirfstat(fd);
- if(dir == nil) {
- warn("can't stat %s: %r", lname);
- close(fd);
- return;
- }
-
- entry = dsink->nentry;
-
- if(dir->mode & DMDIR)
- vacDir(dsink, fd, lname, sname, vf);
- else
- vacData(dsink, fd, lname, vf, dir);
-
- plan9ToVacDir(&vd, dir, entry, fileid++);
- metaSinkWriteDir(dsink->msink, &vd);
- vdCleanup(&vd);
-
- free(dir);
- close(fd);
-}
-
-static void
-vacStdin(DirSink *dsink, char *name, VacFile *vf)
-{
- Dir *dir;
- VacDir vd;
- ulong entry;
-
- if(verbose)
- fprint(2, "%s\n", "<stdio>");
-
- dir = dirfstat(0);
- if(dir == nil) {
- warn("can't stat <stdio>: %r");
- return;
- }
-
- entry = dsink->nentry;
-
- vacData(dsink, 0, "<stdin>", vf, dir);
-
- plan9ToVacDir(&vd, dir, entry, fileid++);
- vd.elem = vtStrDup(name);
- metaSinkWriteDir(dsink->msink, &vd);
- vdCleanup(&vd);
-
- free(dir);
-}
-
-static ulong
-vacDataSkip(Sink *sink, VacFile *vf, int fd, ulong blocks, uchar *buf, char *lname)
-{
- int n;
- ulong i;
- uchar score[VtScoreSize];
-
- /* skip blocks for append only files */
- if(seek(fd, (blocks-1)*bsize, 0) != (blocks-1)*bsize) {
- warn("error seeking: %s", lname);
- goto Err;
- }
- n = readBlock(fd, buf, bsize);
- if(n < bsize) {
- warn("error checking append only file: %s", lname);
- goto Err;
- }
- if(!vfGetBlockScore(vf, blocks-1, score) || !vtSha1Check(score, buf, n)) {
- warn("last block of append file did not match: %s", lname);
- goto Err;
- }
-
- for(i=0; i<blocks; i++) {
- if(!vfGetBlockScore(vf, i, score)) {
- warn("could not get score: %s: %lud", lname, i);
- seek(fd, i*bsize, 0);
- return i;
- }
- stats.skip++;
- sinkWriteScore(sink, score, bsize);
- }
-
- return i;
-Err:
- seek(fd, 0, 0);
- return 0;
-}
-
-static void
-vacData(DirSink *dsink, int fd, char *lname, VacFile *vf, Dir *dir)
-{
- uchar *buf;
- Sink *sink;
- int n;
- uchar score[VtScoreSize];
- ulong block, same;
- VacDir vd;
- ulong vfblocks;
-
- vfblocks = 0;
- if(vf != nil && qdiff) {
- vfGetDir(vf, &vd);
- if(vd.mtime == dir->mtime)
- if(vd.size == dir->length)
- if(!vd.plan9 || /* vd.p9path == dir->qid.path && */ vd.p9version == dir->qid.vers)
- if(dirSinkWriteFile(dsink, vf)) {
- stats.sfile++;
- vdCleanup(&vd);
- return;
- }
-
- /* look for an append only file */
- if((dir->mode&DMAPPEND) != 0)
- if(vd.size < dir->length)
- if(vd.plan9)
- if(vd.p9path == dir->qid.path)
- vfblocks = vd.size/bsize;
-
- vdCleanup(&vd);
- }
- stats.file++;
-
- buf = vtMemAlloc(bsize);
- sink = sinkAlloc(dsink->sink->z, bsize, bsize);
- block = 0;
- same = stats.sdata+stats.skip;
-
- if(vfblocks > 1)
- block += vacDataSkip(sink, vf, fd, vfblocks, buf, lname);
-
-if(0) fprint(2, "vacData: %s: %ld\n", lname, block);
- for(;;) {
- n = readBlock(fd, buf, bsize);
- if(0 && n < 0)
- warn("file truncated due to read error: %s: %s", lname, vtOSError());
- if(n <= 0)
- break;
- if(vf != nil && vfGetBlockScore(vf, block, score) && vtSha1Check(score, buf, n)) {
- stats.sdata++;
- sinkWriteScore(sink, score, n);
- } else
- sinkWrite(sink, buf, n);
- block++;
- }
- same = stats.sdata+stats.skip - same;
-
- if(same && (dir->mode&DMAPPEND) != 0)
- if(0)fprint(2, "%s: total %lud same %lud:%lud diff %lud\n",
- lname, block, same, vfblocks, block-same);
-
- sinkClose(sink);
- dirSinkWriteSink(dsink, sink);
- sinkFree(sink);
- free(buf);
-}
-
-
-static void
-vacDir(DirSink *dsink, int fd, char *lname, char *sname, VacFile *vf)
-{
- Dir *dirs;
- char *ln, *sn;
- int i, nd;
- DirSink *ds;
- VacFile *vvf;
- char *name;
-
- ds = dirSinkAlloc(dsink->sink->z, bsize, bsize);
- while((nd = dirread(fd, &dirs)) > 0){
- for(i = 0; i < nd; i++){
- name = dirs[i].name;
- /* check for bad file names */
- if(name[0] == 0 || strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
- continue;
- ln = vtMemAlloc(strlen(lname) + strlen(name) + 2);
- sn = vtMemAlloc(strlen(sname) + strlen(name) + 2);
- sprint(ln, "%s/%s", lname, name);
- sprint(sn, "%s/%s", sname, name);
- if(vf != nil)
- vvf = vfWalk(vf, name);
- else
- vvf = nil;
- vacFile(ds, ln, sn, vvf);
- if(vvf != nil)
- vfDecRef(vvf);
- vtMemFree(ln);
- vtMemFree(sn);
- }
- free(dirs);
- }
- dirSinkClose(ds);
- dirSinkWriteSink(dsink, ds->sink);
- dirSinkWriteSink(dsink, ds->msink->sink);
- dirSinkFree(ds);
-}
-
-static int
-vacMergeFile(DirSink *dsink, VacFile *vf, VacDir *dir, uvlong offset, uvlong *max)
-{
- uchar buf[VtEntrySize];
- VtEntry dd, md;
- int e;
-
- if(vfRead(vf, buf, VtEntrySize, (uvlong)dir->entry*VtEntrySize) != VtEntrySize) {
- warn("could not read venti dir entry: %s\n", dir->elem);
- return 0;
- }
- vtEntryUnpack(&dd, buf, 0);
-
- if(dir->mode & ModeDir) {
- e = dir->mentry;
- if(e == 0)
- e = dir->entry + 1;
-
- if(vfRead(vf, buf, VtEntrySize, e*VtEntrySize) != VtEntrySize) {
- warn("could not read venti dir entry: %s\n", dir->elem);
- return 0;
- }
- vtEntryUnpack(&md, buf, 0);
- }
-
- /* max might incorrect in some old dumps */
- if(dir->qid >= *max) {
- warn("qid out of range: %s", dir->elem);
- *max = dir->qid;
- }
-
- dir->qid += offset;
- dir->entry = dsink->nentry;
-
- if(dir->qidSpace) {
- dir->qidOffset += offset;
- } else {
- dir->qidSpace = 1;
- dir->qidOffset = offset;
- dir->qidMax = *max;
- }
-
- dirSinkWrite(dsink, &dd);
- if(dir->mode & ModeDir)
- dirSinkWrite(dsink, &md);
- metaSinkWriteDir(dsink->msink, dir);
-
- return 1;
-}
-
-static int
-vacMerge(DirSink *dsink, char *lname, char *sname)
-{
- char *p;
- VacFS *fs;
- VacFile *vf;
- VacDirEnum *d;
- VacDir dir;
- uvlong max;
-
- p = strrchr(sname, '.');
- if(p == 0 || strcmp(p, ".vac"))
- return 0;
-
- d = nil;
- fs = vfsOpen(dsink->sink->z, sname, 1, 100);
- if(fs == nil)
- return 0;
-
- vf = vfOpen(fs, "/");
- if(vf == nil)
- goto Done;
- max = vfGetId(vf);
- d = vdeOpen(fs, "/");
- if(d == nil)
- goto Done;
-
- if(verbose)
- fprint(2, "merging: %s\n", lname);
-
- if(maxbsize < vfsGetBlockSize(fs))
- maxbsize = vfsGetBlockSize(fs);
-
- for(;;) {
- if(vdeRead(d, &dir, 1) < 1)
- break;
- vacMergeFile(dsink, vf, &dir, fileid, &max);
- vdCleanup(&dir);
- }
- fileid += max;
-
-Done:
- if(d != nil)
- vdeFree(d);
- if(vf != nil)
- vfDecRef(vf);
- vfsClose(fs);
- return 1;
-}
-
-Sink *
-sinkAlloc(VtSession *z, int psize, int dsize)
-{
- Sink *k;
- int i;
-
- if(psize < 512 || psize > VtMaxLumpSize)
- vtFatal("sinkAlloc: bad psize");
- if(dsize < 512 || dsize > VtMaxLumpSize)
- vtFatal("sinkAlloc: bad psize");
-
- psize = VtScoreSize*(psize/VtScoreSize);
-
- k = vtMemAllocZ(sizeof(Sink));
- k->z = z;
- k->dir.flags = VtEntryActive;
- k->dir.psize = psize;
- k->dir.dsize = dsize;
- k->buf = vtMemAllocZ(VtPointerDepth*k->dir.psize + VtScoreSize);
- for(i=0; i<=VtPointerDepth; i++)
- k->pbuf[i] = k->buf + i*k->dir.psize;
- return k;
-}
-
-void
-sinkWriteScore(Sink *k, uchar score[VtScoreSize], int n)
-{
- int i;
- uchar *p;
- VtEntry *d;
-
- memmove(k->pbuf[0], score, VtScoreSize);
-
- d = &k->dir;
-
- for(i=0; i<VtPointerDepth; i++) {
- k->pbuf[i] += VtScoreSize;
- if(k->pbuf[i] < k->buf + d->psize*(i+1))
- break;
- if(i == VtPointerDepth-1)
- vtFatal("file too big");
- p = k->buf+i*d->psize;
- stats.meta++;
- if(!vacWrite(k->z, k->pbuf[i+1], VtPointerType0+i, p, d->psize))
- vtFatal("vacWrite failed: %s", vtGetError());
- k->pbuf[i] = p;
- }
-
- /* round size up to multiple of dsize */
- d->size = d->dsize * ((d->size + d->dsize-1)/d->dsize);
-
- d->size += n;
-}
-
-void
-sinkWrite(Sink *k, uchar *p, int n)
-{
- int type;
- uchar score[VtScoreSize];
-
- if(n > k->dir.dsize)
- vtFatal("sinkWrite: size too big");
-
- if(k->dir.flags & VtEntryDir) {
- type = VtDirType;
- stats.meta++;
- } else {
- type = VtDataType;
- stats.data++;
- }
- if(!vacWrite(k->z, score, type, p, n))
- vtFatal("vacWrite failed: %s", vtGetError());
-
- sinkWriteScore(k, score, n);
-}
-
-static int
-sizeToDepth(uvlong s, int psize, int dsize)
-{
- int np;
- int d;
-
- /* determine pointer depth */
- np = psize/VtScoreSize;
- s = (s + dsize - 1)/dsize;
- for(d = 0; s > 1; d++)
- s = (s + np - 1)/np;
- return d;
-}
-
-void
-sinkClose(Sink *k)
-{
- int i, n;
- uchar *p;
- VtEntry *kd;
-
- kd = &k->dir;
-
- /* empty */
- if(kd->size == 0) {
- memmove(kd->score, vtZeroScore, VtScoreSize);
- return;
- }
-
- for(n=VtPointerDepth-1; n>0; n--)
- if(k->pbuf[n] > k->buf + kd->psize*n)
- break;
-
- kd->depth = sizeToDepth(kd->size, kd->psize, kd->dsize);
-
- /* skip full part of tree */
- for(i=0; i<n && k->pbuf[i] == k->buf + kd->psize*i; i++)
- ;
-
- /* is the tree completely full */
- if(i == n && k->pbuf[n] == k->buf + kd->psize*n + VtScoreSize) {
- memmove(kd->score, k->pbuf[n] - VtScoreSize, VtScoreSize);
- return;
- }
- n++;
-
- /* clean up the edge */
- for(; i<n; i++) {
- p = k->buf+i*kd->psize;
- stats.meta++;
- if(!vacWrite(k->z, k->pbuf[i+1], VtPointerType0+i, p, k->pbuf[i]-p))
- vtFatal("vacWrite failed: %s", vtGetError());
- k->pbuf[i+1] += VtScoreSize;
- }
- memmove(kd->score, k->pbuf[i] - VtScoreSize, VtScoreSize);
-}
-
-void
-sinkFree(Sink *k)
-{
- vtMemFree(k->buf);
- vtMemFree(k);
-}
-
-DirSink *
-dirSinkAlloc(VtSession *z, int psize, int dsize)
-{
- DirSink *k;
- int ds;
-
- ds = VtEntrySize*(dsize/VtEntrySize);
-
- k = vtMemAllocZ(sizeof(DirSink));
- k->sink = sinkAlloc(z, psize, ds);
- k->sink->dir.flags |= VtEntryDir;
- k->msink = metaSinkAlloc(z, psize, dsize);
- k->buf = vtMemAlloc(ds);
- k->p = k->buf;
- k->ep = k->buf + ds;
- return k;
-}
-
-void
-dirSinkWrite(DirSink *k, VtEntry *dir)
-{
- if(k->p + VtEntrySize > k->ep) {
- sinkWrite(k->sink, k->buf, k->p - k->buf);
- k->p = k->buf;
- }
- vtEntryPack(dir, k->p, 0);
- k->nentry++;
- k->p += VtEntrySize;
-}
-
-void
-dirSinkWriteSink(DirSink *k, Sink *sink)
-{
- dirSinkWrite(k, &sink->dir);
-}
-
-int
-dirSinkWriteFile(DirSink *k, VacFile *vf)
-{
- VtEntry dir;
-
- if(!vfGetVtEntry(vf, &dir))
- return 0;
- dirSinkWrite(k, &dir);
- return 1;
-}
-
-void
-dirSinkClose(DirSink *k)
-{
- metaSinkClose(k->msink);
- if(k->p != k->buf)
- sinkWrite(k->sink, k->buf, k->p - k->buf);
- sinkClose(k->sink);
-}
-
-void
-dirSinkFree(DirSink *k)
-{
- sinkFree(k->sink);
- metaSinkFree(k->msink);
- vtMemFree(k->buf);
- vtMemFree(k);
-}
-
-MetaSink *
-metaSinkAlloc(VtSession *z, int psize, int dsize)
-{
- MetaSink *k;
-
- k = vtMemAllocZ(sizeof(MetaSink));
- k->sink = sinkAlloc(z, psize, dsize);
- k->buf = vtMemAlloc(dsize);
- k->maxindex = dsize/100; /* 100 byte entries seems reasonable */
- if(k->maxindex < 1)
- k->maxindex = 1;
- k->rp = k->p = k->buf + MetaHeaderSize + k->maxindex*MetaIndexSize;
- k->ep = k->buf + dsize;
- return k;
-}
-
-/* hack to get base to compare routine - not reentrant */
-uchar *blockBase;
-
-int
-dirCmp(void *p0, void *p1)
-{
- uchar *q0, *q1;
- int n0, n1, r;
-
- /* name is first element of entry */
- q0 = p0;
- q0 = blockBase + (q0[0]<<8) + q0[1];
- n0 = (q0[6]<<8) + q0[7];
- q0 += 8;
-
- q1 = p1;
- q1 = blockBase + (q1[0]<<8) + q1[1];
- n1 = (q1[6]<<8) + q1[7];
- q1 += 8;
-
- if(n0 == n1)
- return memcmp(q0, q1, n0);
- else if (n0 < n1) {
- r = memcmp(q0, q1, n0);
- return (r==0)?1:r;
- } else {
- r = memcmp(q0, q1, n1);
- return (r==0)?-1:r;
- }
-}
-
-void
-metaSinkFlush(MetaSink *k)
-{
- uchar *p;
- int n;
- MetaBlock mb;
-
- if(k->nindex == 0)
- return;
- assert(k->nindex <= k->maxindex);
-
- p = k->buf;
- n = k->rp - p;
-
- mb.size = n;
- mb.free = 0;
- mb.nindex = k->nindex;
- mb.maxindex = k->maxindex;
- mb.buf = p;
- mbPack(&mb);
-
- p += MetaHeaderSize;
-
- /* XXX this is not reentrant! */
- blockBase = k->buf;
- qsort(p, k->nindex, MetaIndexSize, dirCmp);
- p += k->nindex*MetaIndexSize;
-
- memset(p, 0, (k->maxindex-k->nindex)*MetaIndexSize);
- p += (k->maxindex-k->nindex)*MetaIndexSize;
-
- sinkWrite(k->sink, k->buf, n);
-
- /* move down partial entry */
- n = k->p - k->rp;
- memmove(p, k->rp, n);
- k->rp = p;
- k->p = p + n;
- k->nindex = 0;
-}
-
-void
-metaSinkPutc(MetaSink *k, int c)
-{
- if(k->p+1 > k->ep)
- metaSinkFlush(k);
- if(k->p+1 > k->ep)
- vtFatal("directory entry too large");
- k->p[0] = c;
- k->p++;
-}
-
-void
-metaSinkPutString(MetaSink *k, char *s)
-{
- int n = strlen(s);
- metaSinkPutc(k, n>>8);
- metaSinkPutc(k, n);
- metaSinkWrite(k, (uchar*)s, n);
-}
-
-void
-metaSinkPutUint32(MetaSink *k, ulong x)
-{
- metaSinkPutc(k, x>>24);
- metaSinkPutc(k, x>>16);
- metaSinkPutc(k, x>>8);
- metaSinkPutc(k, x);
-}
-
-void
-metaSinkPutUint64(MetaSink *k, uvlong x)
-{
- metaSinkPutUint32(k, x>>32);
- metaSinkPutUint32(k, x);
-}
-
-void
-metaSinkWrite(MetaSink *k, uchar *data, int n)
-{
- if(k->p + n > k->ep)
- metaSinkFlush(k);
- if(k->p + n > k->ep)
- vtFatal("directory entry too large");
-
- memmove(k->p, data, n);
- k->p += n;
-}
-
-void
-metaSinkWriteDir(MetaSink *ms, VacDir *dir)
-{
- metaSinkPutUint32(ms, DirMagic);
- metaSinkPutc(ms, Version>>8);
- metaSinkPutc(ms, Version);
- metaSinkPutString(ms, dir->elem);
- metaSinkPutUint32(ms, dir->entry);
- metaSinkPutUint64(ms, dir->qid);
- metaSinkPutString(ms, dir->uid);
- metaSinkPutString(ms, dir->gid);
- metaSinkPutString(ms, dir->mid);
- metaSinkPutUint32(ms, dir->mtime);
- metaSinkPutUint32(ms, dir->mcount);
- metaSinkPutUint32(ms, dir->ctime);
- metaSinkPutUint32(ms, dir->atime);
- metaSinkPutUint32(ms, dir->mode);
-
- if(dir->plan9) {
- metaSinkPutc(ms, DirPlan9Entry); /* plan9 extra info */
- metaSinkPutc(ms, 0); /* plan9 extra size */
- metaSinkPutc(ms, 12); /* plan9 extra size */
- metaSinkPutUint64(ms, dir->p9path);
- metaSinkPutUint32(ms, dir->p9version);
- }
-
- if(dir->qidSpace != 0) {
- metaSinkPutc(ms, DirQidSpaceEntry);
- metaSinkPutc(ms, 0);
- metaSinkPutc(ms, 16);
- metaSinkPutUint64(ms, dir->qidOffset);
- metaSinkPutUint64(ms, dir->qidMax);
- }
-
- if(dir->gen != 0) {
- metaSinkPutc(ms, DirGenEntry);
- metaSinkPutc(ms, 0);
- metaSinkPutc(ms, 4);
- metaSinkPutUint32(ms, dir->gen);
- }
-
- metaSinkEOR(ms);
-}
-
-
-void
-plan9ToVacDir(VacDir *vd, Dir *dir, ulong entry, uvlong qid)
-{
- memset(vd, 0, sizeof(VacDir));
-
- vd->elem = vtStrDup(dir->name);
- vd->entry = entry;
- vd->qid = qid;
- vd->uid = vtStrDup(dir->uid);
- vd->gid = vtStrDup(dir->gid);
- vd->mid = vtStrDup(dir->muid);
- vd->mtime = dir->mtime;
- vd->mcount = 0;
- vd->ctime = dir->mtime; /* ctime: not available on plan 9 */
- vd->atime = dir->atime;
-
- vd->mode = dir->mode & 0777;
- if(dir->mode & DMDIR)
- vd->mode |= ModeDir;
- if(dir->mode & DMAPPEND)
- vd->mode |= ModeAppend;
- if(dir->mode & DMEXCL)
- vd->mode |= ModeExclusive;
-
- vd->plan9 = 1;
- vd->p9path = dir->qid.path;
- vd->p9version = dir->qid.vers;
-}
-
-
-void
-metaSinkEOR(MetaSink *k)
-{
- uchar *p;
- int o, n;
-
- p = k->buf + MetaHeaderSize;
- p += k->nindex * MetaIndexSize;
- o = k->rp-k->buf; /* offset from start of block */
- n = k->p-k->rp; /* size of entry */
- p[0] = o >> 8;
- p[1] = o;
- p[2] = n >> 8;
- p[3] = n;
- k->rp = k->p;
- k->nindex++;
- if(k->nindex == k->maxindex)
- metaSinkFlush(k);
-}
-
-void
-metaSinkClose(MetaSink *k)
-{
- metaSinkFlush(k);
- sinkClose(k->sink);
-}
-
-void
-metaSinkFree(MetaSink *k)
-{
- sinkFree(k->sink);
- vtMemFree(k->buf);
- vtMemFree(k);
-}
-
-static void
-warn(char *fmt, ...)
-{
- va_list arg;
-
- va_start(arg, fmt);
- fprint(2, "%s: ", argv0);
- vfprint(2, fmt, arg);
- fprint(2, "\n");
- va_end(arg);
-}
-
-static void
-cleanup(void)
-{
- if(oname != nil)
- remove(oname);
-}
-
-#define TWID64 ((u64int)~(u64int)0)
-
-static u64int
-unittoull(char *s)
-{
- char *es;
- u64int n;
-
- if(s == nil)
- return TWID64;
- n = strtoul(s, &es, 0);
- if(*es == 'k' || *es == 'K'){
- n *= 1024;
- es++;
- }else if(*es == 'm' || *es == 'M'){
- n *= 1024*1024;
- es++;
- }else if(*es == 'g' || *es == 'G'){
- n *= 1024*1024*1024;
- es++;
- }
- if(*es != '\0')
- return TWID64;
- return n;
-}
diff --git a/src/cmd/vac/vac.c b/src/cmd/vac/vac.c
index 963a56a0..7637e034 100644
--- a/src/cmd/vac/vac.c
+++ b/src/cmd/vac/vac.c
@@ -5,7 +5,18 @@
#include "dat.h"
#include "fns.h"
-int mainstacksize = 128*1024;
+/*
+ * We're between a rock and a hard place here.
+ * The pw library (getpwnam, etc.) reads the
+ * password and group files into an on-stack buffer,
+ * so if you have some huge groups, you overflow
+ * the stack. Because of this, the thread library turns
+ * it off by default, so that dirstat returns "14571" instead of "rsc".
+ * But for vac we want names. So cautiously turn the pwlibrary
+ * back on (see threadmain) and make the main thread stack huge.
+ */
+extern int _p9usepwlibrary;
+int mainstacksize = 4*1024*1024;
typedef struct Sink Sink;
typedef struct MetaSink MetaSink;
@@ -101,6 +112,8 @@ int nowrite;
int merge;
char *isi;
+char **expandargv(char**);
+
static void
usage(void)
{
@@ -116,6 +129,9 @@ threadmain(int argc, char *argv[])
char *host = nil;
int statsflag = 0;
+ /* see comment above */
+ _p9usepwlibrary = 1;
+
atexit(cleanup);
ARGBEGIN{
@@ -194,20 +210,71 @@ threadmain(int argc, char *argv[])
qsort(exclude, nexclude, sizeof(char*), strpcmp);
+ argv = expandargv(argv);
+
vac(z, argv);
if(vtsync(z) < 0)
fprint(2, "warning: could not ask server to flush pending writes: %r\n");
- if(statsflag)
+ if(statsflag){
fprint(2, "files %ld:%ld data %ld:%ld:%ld meta %ld\n", stats.file, stats.sfile,
stats.data, stats.skip, stats.sdata, stats.meta);
-/*packetStats(); */
+ dup(2, 1);
+ packetstats();
+ }
vthangup(z);
threadexitsall(0);
}
+// Expand special directory names like / and . and .. into a list of their files.
+char**
+expandargv(char **argv)
+{
+ char **nargv;
+ int nargc;
+ int i, n;
+ Dir *d;
+ int fd;
+ char *s;
+
+ nargc = 0;
+ nargv = nil;
+ for(; *argv; argv++){
+ cleanname(*argv);
+ if(strcmp(*argv, "/") == 0 || strcmp(*argv, ".") == 0 || strcmp(*argv, "..") == 0
+ || (strlen(*argv) > 3 && strcmp(*argv+strlen(*argv)-3, "/..") == 0)){
+ if((fd = open(*argv, OREAD)) < 0){
+ warn("could not open %s: %r", *argv);
+ continue;
+ }
+ n = dirreadall(fd, &d);
+ close(fd);
+ if(n < 0){
+ warn("could not read %s: %r", *argv);
+ continue;
+ }
+ nargv = vtrealloc(nargv, (nargc+n)*sizeof nargv[0]);
+ for(i=0; i<n; i++){
+ s = vtmalloc(strlen(*argv)+1+strlen(d[i].name)+1);
+ strcpy(s, *argv);
+ strcat(s, "/");
+ strcat(s, d[i].name);
+ cleanname(s);
+ nargv[nargc++] = s;
+ }
+ free(d);
+ continue;
+ }
+ nargv = vtrealloc(nargv, (nargc+1)*sizeof nargv[0]);
+ nargv[nargc++] = *argv;
+ }
+ nargv = vtrealloc(nargv, (nargc+1)*sizeof nargv[0]);
+ nargv[nargc] = nil;
+ return nargv;
+}
+
static int
strpcmp(const void *p0, const void *p1)
{
@@ -353,7 +420,7 @@ vac(VtConn *z, char *argv[])
vtrootpack(&root, buf);
if(vacwrite(z, score, VtRootType, buf, VtRootSize) < 0)
- sysfatal("vacWrite failed: %r");
+ sysfatal("vacwrite: %r");
fprint(fd, "vac:%V\n", score);
@@ -566,7 +633,6 @@ vacdata(DirSink *dsink, int fd, char *lname, VacFile *vf, Dir *dir)
if(vfblocks > 1)
block += vacdataskip(sink, vf, fd, vfblocks, buf, lname);
-if(0) fprint(2, "vacData: %s: %ld\n", lname, block);
for(;;) {
n = readn(fd, buf, bsize);
if(0 && n < 0)
@@ -857,7 +923,7 @@ sinkwrite(Sink *k, uchar *p, int n)
return;
if(n > k->dir.dsize)
- sysfatal("sinkWrite: size too big");
+ sysfatal("sinkwrite: size too big");
if((k->dir.type&~VtTypeDepthMask) == VtDirType){
type = VtDirType;
@@ -867,7 +933,7 @@ sinkwrite(Sink *k, uchar *p, int n)
stats.data++;
}
if(vacwrite(k->z, score, type, p, n) < 0)
- sysfatal("vacWrite failed: %r");
+ sysfatal("vacwrite: %r");
sinkwritescore(k, score, n);
}
@@ -924,7 +990,7 @@ sinkclose(Sink *k)
p = k->buf+i*kd->psize;
stats.meta++;
if(vacwrite(k->z, k->pbuf[i+1], base+1+i, p, k->pbuf[i]-p) < 0)
- sysfatal("vacWrite failed: %r");
+ sysfatal("vacwrite: %r");
k->pbuf[i+1] += VtScoreSize;
}
memmove(kd->score, k->pbuf[i] - VtScoreSize, VtScoreSize);
@@ -1141,6 +1207,7 @@ metasinkwrite(MetaSink *k, uchar *data, int n)
void
metasinkwritedir(MetaSink *ms, VacDir *dir)
{
+
metasinkputuint32(ms, DirMagic);
metasinkputc(ms, Version>>8);
metasinkputc(ms, Version);
@@ -1218,7 +1285,6 @@ plan9tovacdir(VacDir *vd, Dir *dir, ulong entry, uvlong qid)
vd->p9version = dir->qid.vers;
}
-
void
metasinkeor(MetaSink *k)
{
diff --git a/src/cmd/vac/vac.h b/src/cmd/vac/vac.h
index 6d5a8205..a0c4a91f 100644
--- a/src/cmd/vac/vac.h
+++ b/src/cmd/vac/vac.h
@@ -101,13 +101,6 @@ int vacfssync(VacFs *fs);
int vacfssnapshot(VacFs *fs, char *src, char *dst);
int vacfsgetscore(VacFs *fs, u8int *score);
-/*
- * other ideas
- *
- * VacFs *vfsSnapshot(VacFs*, char *src);
- * int vfsGraft(VacFs*, char *name, VacFs*);
- */
-
VacFile *vacfsgetroot(VacFs *fs);
VacFile *vacfileopen(VacFs *fs, char *path);
VacFile *vacfilecreate(VacFile *file, char *elem, ulong perm, char *muid);
@@ -140,4 +133,4 @@ void vdcopy(VacDir *dst, VacDir *src);
VacDirEnum *vdeopen(VacFile*);
int vderead(VacDirEnum*, VacDir *);
void vdeclose(VacDirEnum*);
-
+int vdeunread(VacDirEnum*);
diff --git a/src/cmd/vac/vacfs.c b/src/cmd/vac/vacfs.c
index 8cf78642..1ce3e2df 100644
--- a/src/cmd/vac/vacfs.c
+++ b/src/cmd/vac/vacfs.c
@@ -5,18 +5,12 @@
#include "vac.h"
typedef struct Fid Fid;
-typedef struct DirBuf DirBuf;
enum
{
OPERM = 0x3 /* mask of all permission types in open mode */
};
-enum
-{
- DirBufSize = 20
-};
-
struct Fid
{
short busy;
@@ -25,18 +19,8 @@ struct Fid
char *user;
Qid qid;
VacFile *file;
-
- DirBuf *db;
-
- Fid *next;
-};
-
-struct DirBuf
-{
VacDirEnum *vde;
- VacDir buf[DirBufSize];
- int i, n;
- int eof;
+ Fid *next;
};
enum
@@ -73,12 +57,8 @@ int perm(Fid*, int);
int permf(VacFile*, char*, int);
ulong getl(void *p);
void init(char*, char*, long, int);
-DirBuf *dirBufAlloc(VacFile*);
-VacDir *dirBufGet(DirBuf*);
-int dirBufUnget(DirBuf*);
-void dirBufFree(DirBuf*);
int vacdirread(Fid *f, char *p, long off, long cnt);
-int vdStat(VacFile *parent, VacDir *vd, uchar *p, int np);
+int vacstat(VacFile *parent, VacDir *vd, uchar *p, int np);
void srv(void* a);
@@ -141,7 +121,6 @@ threadmain(int argc, char *argv[])
int stdio = 0;
char *host = nil;
long ncache = 1000;
- int readOnly = 1;
fmtinstall('H', encodefmt);
fmtinstall('V', vtscorefmt);
@@ -184,7 +163,20 @@ threadmain(int argc, char *argv[])
usage();
initfcalls();
- init(argv[0], host, ncache, readOnly);
+
+ notify(notifyf);
+ user = getuser();
+
+ conn = vtdial(host);
+ if(conn == nil)
+ sysfatal("could not connect to server: %r");
+
+ if(vtconnect(conn) < 0)
+ sysfatal("vtconnect: %r");
+
+ fs = vacfsopen(conn, argv[0], VtOREAD, ncache);
+ if(fs == nil)
+ sysfatal("vacfsopen: %r");
if(pipe(p) < 0)
sysfatal("pipe failed: %r");
@@ -294,19 +286,6 @@ rattach(Fid *f)
return 0;
}
-VacFile*
-_vfWalk(VacFile *file, char *name)
-{
- VacFile *n;
-
- n = vacfilewalk(file, name);
- if(n)
- return n;
- if(strcmp(name, "SLASH") == 0)
- return vacfilewalk(file, "/");
- return nil;
-}
-
char*
rwalk(Fid *f)
{
@@ -356,7 +335,7 @@ rwalk(Fid *f)
err = Eperm;
break;
}
- nfile = _vfWalk(file, rhdr.wname[nqid]);
+ nfile = vacfilewalk(file, rhdr.wname[nqid]);
if(nfile == nil)
break;
vacfiledecref(file);
@@ -410,7 +389,7 @@ ropen(Fid *f)
if(!perm(f, Pread))
return vtstrdup(Eperm);
thdr.qid = f->qid;
- f->db = nil;
+ f->vde = nil;
f->open = 1;
return 0;
}
@@ -564,8 +543,8 @@ rclunk(Fid *f)
if(f->file)
vacfiledecref(f->file);
f->file = nil;
- dirBufFree(f->db);
- f->db = nil;
+ vdeclose(f->vde);
+ f->vde = nil;
return 0;
}
@@ -588,8 +567,6 @@ rremove(Fid *f)
if(!vacfileremove(vf, "none")) {
rerrstr(errbuf, sizeof errbuf);
-print("vfRemove failed: %s\n", errbuf);
-
err = errbuf;
}
@@ -611,7 +588,7 @@ rstat(Fid *f)
parent = vacfilegetparent(f->file);
vacfilegetdir(f->file, &dir);
thdr.stat = statbuf;
- thdr.nstat = vdStat(parent, &dir, thdr.stat, sizeof statbuf);
+ thdr.nstat = vacstat(parent, &dir, thdr.stat, sizeof statbuf);
vdcleanup(&dir);
vacfiledecref(parent);
return 0;
@@ -626,7 +603,7 @@ rwstat(Fid *f)
}
int
-vdStat(VacFile *parent, VacDir *vd, uchar *p, int np)
+vacstat(VacFile *parent, VacDir *vd, uchar *p, int np)
{
char *ext;
int n, ret;
@@ -694,96 +671,39 @@ vdStat(VacFile *parent, VacDir *vd, uchar *p, int np)
return ret;
}
-DirBuf*
-dirBufAlloc(VacFile *vf)
-{
- DirBuf *db;
-
- db = vtmallocz(sizeof(DirBuf));
- db->vde = vdeopen(vf);
- return db;
-}
-
-VacDir *
-dirBufGet(DirBuf *db)
-{
- VacDir *vd;
- int n;
-
- if(db->eof)
- return nil;
-
- if(db->i >= db->n) {
- n = vderead(db->vde, db->buf);
- if(n < 0)
- return nil;
- db->i = 0;
- db->n = n;
- if(n == 0) {
- db->eof = 1;
- return nil;
- }
- }
-
- vd = db->buf + db->i;
- db->i++;
-
- return vd;
-}
-
-int
-dirBufUnget(DirBuf *db)
-{
- assert(db->i > 0);
- db->i--;
- return 1;
-}
-
-void
-dirBufFree(DirBuf *db)
-{
- int i;
-
- if(db == nil)
- return;
-
- for(i=db->i; i<db->n; i++)
- vdcleanup(db->buf + i);
- vdeclose(db->vde);
- vtfree(db);
-}
-
int
vacdirread(Fid *f, char *p, long off, long cnt)
{
- int n, nb;
- VacDir *vd;
+ int i, n, nb;
+ VacDir vd;
/*
* special case of rewinding a directory
* otherwise ignore the offset
*/
- if(off == 0 && f->db) {
- dirBufFree(f->db);
- f->db = nil;
+ if(off == 0 && f->vde){
+ vdeclose(f->vde);
+ f->vde = nil;
}
- if(f->db == nil)
- f->db = dirBufAlloc(f->file);
+ if(f->vde == nil){
+ f->vde = vdeopen(f->file);
+ if(f->vde == nil)
+ return -1;
+ }
for(nb = 0; nb < cnt; nb += n) {
- vd = dirBufGet(f->db);
- if(vd == nil) {
- if(!f->db->eof)
- return -1;
+ i = vderead(f->vde, &vd);
+ if(i < 0)
+ return -1;
+ if(i == 0)
break;
- }
- n = vdStat(f->file, vd, (uchar*)p, cnt-nb);
+ n = vacstat(f->file, &vd, (uchar*)p, cnt-nb);
if(n <= BIT16SZ) {
- dirBufUnget(f->db);
+ vdeunread(f->vde);
break;
}
- vdcleanup(vd);
+ vdcleanup(&vd);
p += n;
}
return nb;
@@ -886,24 +806,6 @@ perm(Fid *f, int p)
}
void
-init(char *file, char *host, long ncache, int readOnly)
-{
- notify(notifyf);
- user = getuser();
-
- conn = vtdial(host);
- if(conn == nil)
- sysfatal("could not connect to server: %r");
-
- if(vtconnect(conn) < 0)
- sysfatal("vtconnect: %r");
-
- fs = vacfsopen(conn, file, /*readOnly ? ModeSnapshot :*/ VtOREAD, ncache);
- if(fs == nil)
- sysfatal("vfsOpen: %r");
-}
-
-void
vacshutdown(void)
{
Fid *f;
diff --git a/src/cmd/vac/vactest.c b/src/cmd/vac/vactest.c
deleted file mode 100644
index c456604f..00000000
--- a/src/cmd/vac/vactest.c
+++ /dev/null
@@ -1,182 +0,0 @@
-#include "stdinc.h"
-#include "vac.h"
-#include "dat.h"
-#include "fns.h"
-
-void usage(void);
-int unvac(VacFS *fs);
-int readScore(int fd, uchar score[VtScoreSize]);
-static void warn(char *fmt, ...);
-void dirlist(VacFS *fs, char *path);
-
-static int nwant;
-static char **want;
-static int dflag = 1;
-static int cflag;
-static int lower;
-static int verbose;
-static int settimes;
-
-void
-main(int argc, char *argv[])
-{
- char *zfile;
- int ok, table;
- VtSession *z;
- char *vsrv = nil;
- char *host = nil;
- char *p;
- int ncache = 1000;
- VacFS *fs;
-
- table = 0;
- zfile = nil;
- ARGBEGIN{
- case 'D':
- dflag++;
- break;
- case 'c':
- cflag++;
- break;
- case 'C':
- p = ARGF();
- if(p == nil)
- usage();
- ncache = atoi(p);
- if(ncache < 10)
- ncache = 10;
- if(ncache > 1000000)
- ncache = 1000000;
- break;
- case 'i':
- lower++;
- break;
- case 'f':
- zfile = ARGF();
- if(zfile == nil)
- usage();
- break;
- case 'h':
- host = ARGF();
- break;
- case 't':
- table++;
- break;
- case 'T':
- settimes++;
- break;
- case 's':
- vsrv = ARGF();
- break;
- case 'v':
- verbose++;
- break;
- default:
- usage();
- break;
- }ARGEND
-
- nwant = argc;
- want = argv;
-
- vtAttach();
-
- if(zfile == nil)
- usage();
-
- if(vsrv != nil)
- z = vtStdioServer(vsrv);
- else
- z = vtDial(host);
- if(z == nil)
- vtFatal("could not connect to server: %s", vtGetError());
- vtSetDebug(z, 0);
- if(!vtConnect(z, 0))
- vtFatal("vtConnect: %s", vtGetError());
- fs = vfsOpen(z, zfile, 1, ncache);
- if(fs == nil)
- vtFatal("vfsOpen: %s", vtGetError());
- ok = unvac(fs);
- vtClose(z);
- vtDetach();
-
- exits(ok? 0 : "error");
-}
-
-void
-usage(void)
-{
- fprint(2, "usage: %s [-tTcDv] -f zipfile [-s ventid] [-h host] [file ...]\n", argv0);
- exits("usage");
-}
-
-void
-suck(VacFile *f)
-{
- USED(f);
-}
-
-
-void
-vacfile(VacFS *fs, char *path, VacDir *vd)
-{
- char *path2;
-
- path2 = vtMemAlloc(strlen(path) + 1 + strlen(vd->elem) + 1);
- if(path[1] == 0)
- sprintf(path2, "/%s", vd->elem);
- else
- sprintf(path2, "%s/%s", path, vd->elem);
-fprint(2, "vac file: %s\n", path2);
- if(vd->mode & ModeDir)
- dirlist(fs, path2);
- vtMemFree(path2);
-}
-
-void
-dirlist(VacFS *fs, char *path)
-{
- VacDir vd[50];
- VacDirEnum *ds;
- int i, n;
-
- ds = vdeOpen(fs, path);
- if(ds == nil) {
- fprint(2, "could not open: %s: %s\n", path, vtGetError());
- return;
- }
- for(;;) {
- n = vdeRead(ds, vd, sizeof(vd)/sizeof(VacDir));
- if(n < 0) {
- warn("vdRead failed: %s: %s", path, vtGetError());
- return;
- }
- if(n == 0)
- break;
- for(i=0; i<n; i++) {
- vacfile(fs, path, &vd[i]);
- vdCleanup(&vd[i]);
- }
- }
- vdeFree(ds);
-}
-
-int
-unvac(VacFS *fs)
-{
- dirlist(fs, "/");
-
- return 1;
-}
-
-static void
-warn(char *fmt, ...)
-{
- va_list arg;
-
- va_start(arg, fmt);
- fprint(2, "%s: ", argv0);
- vfprint(2, fmt, arg);
- fprint(2, "\n");
- va_end(arg);
-}
diff --git a/src/cmd/vac/vtread.c b/src/cmd/vac/vtread.c
deleted file mode 100644
index 8550279f..00000000
--- a/src/cmd/vac/vtread.c
+++ /dev/null
@@ -1,126 +0,0 @@
-#include "stdinc.h"
-#include <bio.h>
-
-typedef struct Source Source;
-
-struct Source
-{
- ulong gen;
- int psize;
- int dsize;
- int dir;
- int active;
- int depth;
- uvlong size;
- uchar score[VtScoreSize];
- int reserved;
-};
-
-int bsize;
-Biobuf *bout;
-VtRootLump root;
-int ver;
-int cmp;
-int all;
-int find;
-uchar fscore[VtScoreSize];
-int dirSize;
-void (*parse)(Source*, uchar*);
-VtSession *z;
-
-int vtGetUint16(uchar *p);
-ulong vtGetUint32(uchar *p);
-uvlong vtGetUint48(uchar *p);
-void usage(void);
-int parseScore(uchar *score, char *buf, int n);
-void readRoot(VtRootLump*, uchar *score, char *file);
-void parse1(Source*, uchar*);
-void parse2(Source*, uchar*);
-int dumpDir(Source*, int indent);
-
-void
-main(int argc, char *argv[])
-{
- char *host = nil;
- uchar score[VtScoreSize];
- uchar buf[VtMaxLumpSize];
- int type;
- int n;
-
- type = VtDataType;
-
- ARGBEGIN{
- case 't':
- type = atoi(ARGF());
- break;
- }ARGEND
-
- vtAttach();
-
- bout = vtMemAllocZ(sizeof(Biobuf));
- Binit(bout, 1, OWRITE);
-
- if(argc != 1)
- usage();
-
- vtAttach();
-
- fmtinstall('V', vtScoreFmt);
- fmtinstall('R', vtErrFmt);
-
- z = vtDial(host);
- if(z == nil)
- vtFatal("could not connect to server: %s", vtGetError());
-
- if(!vtConnect(z, 0))
- sysfatal("vtConnect: %r");
-
- if(!parseScore(score, argv[0], strlen(argv[0])))
- vtFatal("could not parse score: %s", vtGetError());
-
- n = vtRead(z, score, type, buf, VtMaxLumpSize);
- if(n < 0)
- vtFatal("could not read block: %s", vtGetError());
- Bwrite(bout, buf, n);
-
- Bterm(bout);
-
- vtClose(z);
- vtDetach();
- exits(0);
-}
-
-void
-usage(void)
-{
- fprint(2, "%s: -t type score\n", argv0);
- exits("usage");
-}
-
-int
-parseScore(uchar *score, char *buf, int n)
-{
- int i, c;
-
- memset(score, 0, VtScoreSize);
-
- if(n < VtScoreSize*2)
- return 0;
- for(i=0; i<VtScoreSize*2; i++) {
- if(buf[i] >= '0' && buf[i] <= '9')
- c = buf[i] - '0';
- else if(buf[i] >= 'a' && buf[i] <= 'f')
- c = buf[i] - 'a' + 10;
- else if(buf[i] >= 'A' && buf[i] <= 'F')
- c = buf[i] - 'A' + 10;
- else {
- return 0;
- }
-
- if((i & 1) == 0)
- c <<= 4;
-
- score[i>>1] |= c;
- }
- return 1;
-}
diff --git a/src/cmd/vac/wtest.c b/src/cmd/vac/wtest.c
deleted file mode 100644
index 35dc8233..00000000
--- a/src/cmd/vac/wtest.c
+++ /dev/null
@@ -1,47 +0,0 @@
-#include "stdinc.h"
-
-enum {
- Nblock = 10000,
- BlockSize = 8*1024
-};
-
-uchar data[Nblock*BlockSize];
-
-void
-main(int argc, char *argv[])
-{
- VtSession *z;
- int i;
- uchar score[VtScoreSize];
- int start;
-
- ARGBEGIN{
- }ARGEND
-
- for(i=0; i<Nblock; i++) {
- if(readn(0, data+i*BlockSize, BlockSize) < BlockSize)
- sysfatal("read failed: %r");
- }
-
- vtAttach();
-
- z = vtDial("iolaire2");
- if(z == nil)
- sysfatal("cound not connect to venti");
- if(!vtConnect(z, 0))
- vtFatal("vtConnect: %s", vtGetError());
-
- print("starting\n");
-
- start = times(0);
-
- for(i=0; i<Nblock; i++) {
- if(!vtWrite(z, score, VtDataType, data+i*BlockSize, BlockSize))
- vtFatal("vtWrite failed: %s", vtGetError());
- }
-
- print("time = %f\n", (times(0) - start)*0.001);
-
- vtClose(z);
- vtDetach();
-}