vac: clean up, add unvac

This commit is contained in:
Russ Cox 2008-06-14 13:28:49 -04:00
parent 01cea2ecb8
commit 64f9764ea9
16 changed files with 488 additions and 2421 deletions

View file

@ -1,2 +0,0 @@
This is somewhat untested but is believed to work.

View file

@ -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

View file

@ -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);

View file

@ -16,7 +16,7 @@ HFILES=\
dat.h\
fns.h\
TARG=vac vacfs # vtdump
TARG=vac vacfs unvac # vtdump
default:V: all

View file

@ -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;

View file

@ -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();
}

View file

@ -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);
}

293
src/cmd/vac/unvac.c Normal file
View file

@ -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;
}

View file

@ -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;
}

File diff suppressed because it is too large Load diff

View file

@ -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)
{

View file

@ -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*);

View file

@ -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;
@ -885,24 +805,6 @@ perm(Fid *f, int p)
return permf(f->file, f->user, 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)
{

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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();
}