diff options
author | Russ Cox <rsc@swtch.com> | 2008-06-14 13:28:49 -0400 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2008-06-14 13:28:49 -0400 |
commit | 64f9764ea9f958a1abc7a32424f43019723e9e53 (patch) | |
tree | cca50bfb352edfb70de5e63d98d2234aac598def /src/cmd/vac | |
parent | 01cea2ecb8c0b101a22e7883d87fbf1d28a03043 (diff) | |
download | plan9port-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/README | 2 | ||||
-rw-r--r-- | src/cmd/vac/file.c | 238 | ||||
-rw-r--r-- | src/cmd/vac/fns.h | 8 | ||||
-rw-r--r-- | src/cmd/vac/mkfile | 2 | ||||
-rw-r--r-- | src/cmd/vac/pack.c | 85 | ||||
-rw-r--r-- | src/cmd/vac/rtest.c | 71 | ||||
-rw-r--r-- | src/cmd/vac/srcload.c | 302 | ||||
-rw-r--r-- | src/cmd/vac/unvac.c | 293 | ||||
-rw-r--r-- | src/cmd/vac/util.c | 71 | ||||
-rw-r--r-- | src/cmd/vac/vac-orig.c | 1213 | ||||
-rw-r--r-- | src/cmd/vac/vac.c | 84 | ||||
-rw-r--r-- | src/cmd/vac/vac.h | 9 | ||||
-rw-r--r-- | src/cmd/vac/vacfs.c | 176 | ||||
-rw-r--r-- | src/cmd/vac/vactest.c | 182 | ||||
-rw-r--r-- | src/cmd/vac/vtread.c | 126 | ||||
-rw-r--r-- | src/cmd/vac/wtest.c | 47 |
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(); -} |