tvac: clean up, add unvac - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 64f9764ea9f958a1abc7a32424f43019723e9e53 | |
parent 01cea2ecb8c0b101a22e7883d87fbf1d28a03043 | |
Author: Russ Cox <[email protected]> | |
Date: Sat, 14 Jun 2008 13:28:49 -0400 | |
vac: clean up, add unvac | |
Diffstat: | |
D src/cmd/vac/README | 2 -- | |
M src/cmd/vac/file.c | 238 +++--------------------------… | |
M src/cmd/vac/fns.h | 8 ++++++-- | |
M src/cmd/vac/mkfile | 2 +- | |
M src/cmd/vac/pack.c | 85 ++++++++++++++++++++---------… | |
D src/cmd/vac/rtest.c | 71 -----------------------------… | |
D src/cmd/vac/srcload.c | 302 -----------------------------… | |
A src/cmd/vac/unvac.c | 293 ++++++++++++++++++++++++++++++ | |
D src/cmd/vac/util.c | 71 -----------------------------… | |
D src/cmd/vac/vac-orig.c | 1213 -----------------------------… | |
M src/cmd/vac/vac.c | 84 +++++++++++++++++++++++++++--… | |
M src/cmd/vac/vac.h | 9 +-------- | |
M src/cmd/vac/vacfs.c | 176 +++++++----------------------… | |
D src/cmd/vac/vactest.c | 182 -----------------------------… | |
D src/cmd/vac/vtread.c | 126 -----------------------------… | |
D 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 | |
t@@ -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 | |
t@@ -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; | |
t@@ -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, scor… | |
- /* 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) | |
{ | |
t@@ -713,8 +653,6 @@ filewrite(VacFile *f, void *buf, int cnt, vlong offset, ch… | |
uchar *p; | |
vlong eof; | |
-if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset); | |
- | |
if(filelock(f) < 0) | |
return -1; | |
t@@ -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) | |
{ | |
t@@ -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); */ | |
t@@ -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); | |
t@@ -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) | |
{ | |
t@@ -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) | |
t@@ -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; | |
} | |
t@@ -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: | |
t@@ -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 | |
t@@ -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 %… | |
- 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 | |
t@@ -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 | |
t@@ -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 | |
t@@ -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) | |
{ | |
t@@ -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 */ | |
t@@ -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); | |
t@@ -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); | |
t@@ -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); | |
t@@ -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) | |
{ | |
t@@ -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; | |
t@@ -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; | |
t@@ -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; | |
t@@ -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 */ | |
t@@ -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) | |
t@@ -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); | |
t@@ -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) | |
t@@ -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 | |
t@@ -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, BlockS… | |
- 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 | |
t@@ -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-… | |
- 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 | |
t@@ -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) =… | |
+ return 1; | |
+ if(namelen < n && want[i][namelen] == '/' && memcmp(want[i], n… | |
+ 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->siz… | |
+ 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)… | |
+ fprint(2, "mkdir %s: %r\n", name); | |
+ vdeclose(vde); | |
+ } | |
+ close(fd); | |
+ }else{ | |
+ if(!(dp->mode&DMDIR)){ | |
+ fprint(2, "%s already exists and is no… | |
+ 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)) == ni… | |
+ 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 | |
t@@ -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 | |
t@@ -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 writ… | |
- | |
- if(statsFlag) | |
- fprint(2, "files %ld:%ld data %ld:%ld:%ld meta %ld\n", stats.f… | |
- 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] [-… | |
- 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, vtGe… | |
- } | |
- | |
- | |
- 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 *l… | |
-{ | |
- 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.p9versi… | |
- 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… | |
- if(n <= 0) | |
- break; | |
- if(vf != nil && vfGetBlockScore(vf, block, score) && vtSha1Che… | |
- 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(na… | |
- 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 *… | |
-{ | |
- uchar buf[VtEntrySize]; | |
- VtEntry dd, md; | |
- int e; | |
- | |
- if(vfRead(vf, buf, VtEntrySize, (uvlong)dir->entry*VtEntrySize) != VtE… | |
- 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[… | |
- 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 siz… | |
- metaSinkPutc(ms, 12); /* plan9 extra si… | |
- 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… | |
- 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 | |
t@@ -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; | |
t@@ -101,6 +112,8 @@ int nowrite; | |
int merge; | |
char *isi; | |
+char **expandargv(char**); | |
+ | |
static void | |
usage(void) | |
{ | |
t@@ -116,6 +129,9 @@ threadmain(int argc, char *argv[]) | |
char *host = nil; | |
int statsflag = 0; | |
+ /* see comment above */ | |
+ _p9usepwlibrary = 1; | |
+ | |
atexit(cleanup); | |
ARGBEGIN{ | |
t@@ -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 writ… | |
- if(statsflag) | |
+ if(statsflag){ | |
fprint(2, "files %ld:%ld data %ld:%ld:%ld meta %ld\n", stats.f… | |
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 fil… | |
+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 || strcm… | |
+ || (strlen(*argv) > 3 && strcmp(*argv+strlen(*… | |
+ 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)… | |
+ 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) | |
{ | |
t@@ -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); | |
t@@ -566,7 +633,6 @@ vacdata(DirSink *dsink, int fd, char *lname, VacFile *vf, … | |
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) | |
t@@ -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; | |
t@@ -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); | |
} | |
t@@ -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); | |
t@@ -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); | |
t@@ -1218,7 +1285,6 @@ plan9tovacdir(VacDir *vd, Dir *dir, ulong entry, uvlong … | |
vd->p9version = dir->qid.vers; | |
} | |
- | |
void | |
metasinkeor(MetaSink *k) | |
{ | |
diff --git a/src/cmd/vac/vac.h b/src/cmd/vac/vac.h | |
t@@ -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 *mui… | |
t@@ -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 | |
t@@ -5,18 +5,12 @@ | |
#include "vac.h" | |
typedef struct Fid Fid; | |
-typedef struct DirBuf DirBuf; | |
enum | |
{ | |
OPERM = 0x3 /* mask of all permission types in o… | |
}; | |
-enum | |
-{ | |
- DirBufSize = 20 | |
-}; | |
- | |
struct Fid | |
{ | |
short busy; | |
t@@ -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 | |
t@@ -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); | |
t@@ -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); | |
t@@ -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"); | |
t@@ -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) | |
{ | |
t@@ -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); | |
t@@ -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; | |
} | |
t@@ -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; | |
} | |
t@@ -588,8 +567,6 @@ rremove(Fid *f) | |
if(!vacfileremove(vf, "none")) { | |
rerrstr(errbuf, sizeof errbuf); | |
-print("vfRemove failed: %s\n", errbuf); | |
- | |
err = errbuf; | |
} | |
t@@ -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; | |
t@@ -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; | |
t@@ -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; | |
t@@ -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, ncac… | |
- 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 | |
t@@ -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 .… | |
- 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 | |
t@@ -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 | |
t@@ -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(); | |
-} |