mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
vac: clean up, add unvac
This commit is contained in:
parent
01cea2ecb8
commit
64f9764ea9
16 changed files with 488 additions and 2421 deletions
|
@ -1,2 +0,0 @@
|
||||||
This is somewhat untested but is believed to work.
|
|
||||||
|
|
|
@ -564,8 +564,6 @@ vacfileread(VacFile *f, void *buf, int cnt, vlong offset)
|
||||||
VtBlock *b;
|
VtBlock *b;
|
||||||
uchar *p;
|
uchar *p;
|
||||||
|
|
||||||
if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset);
|
|
||||||
|
|
||||||
if(filerlock(f) < 0)
|
if(filerlock(f) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -620,64 +618,6 @@ Err1:
|
||||||
return -1;
|
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
|
int
|
||||||
vacfilesetsize(VacFile *f, uvlong size)
|
vacfilesetsize(VacFile *f, uvlong size)
|
||||||
{
|
{
|
||||||
|
@ -713,8 +653,6 @@ filewrite(VacFile *f, void *buf, int cnt, vlong offset, char *uid)
|
||||||
uchar *p;
|
uchar *p;
|
||||||
vlong eof;
|
vlong eof;
|
||||||
|
|
||||||
if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset);
|
|
||||||
|
|
||||||
if(filelock(f) < 0)
|
if(filelock(f) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -1064,7 +1002,7 @@ vacfilemetaflush(VacFile *f, int rec)
|
||||||
vtfree(kids);
|
vtfree(kids);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assumes metaLock is held */
|
/* assumes metalock is held */
|
||||||
static int
|
static int
|
||||||
filemetaflush2(VacFile *f, char *oelem)
|
filemetaflush2(VacFile *f, char *oelem)
|
||||||
{
|
{
|
||||||
|
@ -1097,15 +1035,14 @@ filemetaflush2(VacFile *f, char *oelem)
|
||||||
if(mbsearch(&mb, oelem, &i, &me) < 0)
|
if(mbsearch(&mb, oelem, &i, &me) < 0)
|
||||||
goto Err;
|
goto Err;
|
||||||
|
|
||||||
n = vdsize(&f->dir);
|
n = vdsize(&f->dir, VacDirVersion);
|
||||||
if(0)fprint(2, "old size %d new size %d\n", me.size, n);
|
|
||||||
|
|
||||||
if(mbresize(&mb, &me, n) >= 0){
|
if(mbresize(&mb, &me, n) >= 0){
|
||||||
/* fits in the block */
|
/* fits in the block */
|
||||||
mbdelete(&mb, i, &me);
|
mbdelete(&mb, i, &me);
|
||||||
if(strcmp(f->dir.elem, oelem) != 0)
|
if(strcmp(f->dir.elem, oelem) != 0)
|
||||||
mbsearch(&mb, f->dir.elem, &i, &me2);
|
mbsearch(&mb, f->dir.elem, &i, &me2);
|
||||||
vdpack(&f->dir, &me);
|
vdpack(&f->dir, &me, VacDirVersion);
|
||||||
mbinsert(&mb, i, &me);
|
mbinsert(&mb, i, &me);
|
||||||
mbpack(&mb);
|
mbpack(&mb);
|
||||||
/* vtblockdirty(b); */
|
/* 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);
|
boff = filemetaalloc(fp, &f->dir, f->boff+1);
|
||||||
if(boff == NilBlock){
|
if(boff == NilBlock){
|
||||||
/* mbResize might have modified block */
|
/* mbresize might have modified block */
|
||||||
mbpack(&mb);
|
mbpack(&mb);
|
||||||
/* vtblockdirty(b); */
|
/* vtblockdirty(b); */
|
||||||
goto Err;
|
goto Err;
|
||||||
}
|
}
|
||||||
fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff);
|
|
||||||
f->boff = boff;
|
f->boff = boff;
|
||||||
|
|
||||||
/* make sure deletion goes to disk after new entry */
|
/* make sure deletion goes to disk after new entry */
|
||||||
bb = vtfileblock(fp->msource, f->boff, VtORDWR);
|
bb = vtfileblock(fp->msource, f->boff, VtORDWR);
|
||||||
mbdelete(&mb, i, &me);
|
mbdelete(&mb, i, &me);
|
||||||
mbpack(&mb);
|
mbpack(&mb);
|
||||||
/* blockDependency(b, bb, -1, nil, nil); */
|
|
||||||
vtblockput(bb);
|
vtblockput(bb);
|
||||||
/* vtblockdirty(b); */
|
/* vtblockdirty(b); */
|
||||||
vtblockput(b);
|
vtblockput(b);
|
||||||
|
@ -1522,6 +1457,16 @@ Return:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vdeunread(VacDirEnum *vde)
|
||||||
|
{
|
||||||
|
if(vde->i > 0){
|
||||||
|
vde->i--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vdeclose(VacDirEnum *vde)
|
vdeclose(VacDirEnum *vde)
|
||||||
{
|
{
|
||||||
|
@ -1555,7 +1500,7 @@ filemetaalloc(VacFile *f, VacDir *dir, u32int start)
|
||||||
s = f->source;
|
s = f->source;
|
||||||
ms = f->msource;
|
ms = f->msource;
|
||||||
|
|
||||||
n = vdsize(dir);
|
n = vdsize(dir, VacDirVersion);
|
||||||
nb = (vtfilegetsize(ms)+ms->dsize-1)/ms->dsize;
|
nb = (vtfilegetsize(ms)+ms->dsize-1)/ms->dsize;
|
||||||
b = nil;
|
b = nil;
|
||||||
if(start > nb)
|
if(start > nb)
|
||||||
|
@ -1584,9 +1529,8 @@ filemetaalloc(VacFile *f, VacDir *dir, u32int start)
|
||||||
|
|
||||||
p = mballoc(&mb, n);
|
p = mballoc(&mb, n);
|
||||||
if(p == nil){
|
if(p == nil){
|
||||||
/* mbAlloc might have changed block */
|
/* mballoc might have changed block */
|
||||||
mbpack(&mb);
|
mbpack(&mb);
|
||||||
/* vtblockdirty(b); */
|
|
||||||
werrstr(EBadMeta);
|
werrstr(EBadMeta);
|
||||||
goto Err;
|
goto Err;
|
||||||
}
|
}
|
||||||
|
@ -1595,29 +1539,10 @@ filemetaalloc(VacFile *f, VacDir *dir, u32int start)
|
||||||
assert(me.p == nil);
|
assert(me.p == nil);
|
||||||
me.p = p;
|
me.p = p;
|
||||||
me.size = n;
|
me.size = n;
|
||||||
vdpack(dir, &me);
|
vdpack(dir, &me, VacDirVersion);
|
||||||
mbinsert(&mb, i, &me);
|
mbinsert(&mb, i, &me);
|
||||||
mbpack(&mb);
|
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);
|
vtblockput(b);
|
||||||
return bo;
|
return bo;
|
||||||
Err:
|
Err:
|
||||||
|
@ -1676,7 +1601,7 @@ fileunlock(VacFile *f)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* f->source and f->msource must NOT be locked.
|
* 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.
|
* We have to respect that ordering.
|
||||||
*/
|
*/
|
||||||
static void
|
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
|
|
||||||
|
|
|
@ -8,9 +8,13 @@ int meunpack(MetaEntry*, MetaBlock *mb, int i);
|
||||||
int mecmp(MetaEntry*, char *s);
|
int mecmp(MetaEntry*, char *s);
|
||||||
int mecmpnew(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*);
|
int vdunpack(VacDir *dir, MetaEntry*);
|
||||||
void vdpack(VacDir *dir, MetaEntry*);
|
void vdpack(VacDir *dir, MetaEntry*, int);
|
||||||
|
|
||||||
VacFile *_vacfileroot(VacFs *fs, VtFile *file);
|
VacFile *_vacfileroot(VacFs *fs, VtFile *file);
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ HFILES=\
|
||||||
dat.h\
|
dat.h\
|
||||||
fns.h\
|
fns.h\
|
||||||
|
|
||||||
TARG=vac vacfs # vtdump
|
TARG=vac vacfs unvac # vtdump
|
||||||
|
|
||||||
default:V: all
|
default:V: all
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ if(0)print("eo = %d en = %d\n", eo, en);
|
||||||
return 0;
|
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
|
int
|
||||||
mecmp(MetaEntry *me, char *s)
|
mecmp(MetaEntry *me, char *s)
|
||||||
{
|
{
|
||||||
|
@ -372,18 +372,17 @@ mballoc(MetaBlock *mb, int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vdsize(VacDir *dir)
|
vdsize(VacDir *dir, int version)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/* constant part */
|
if(version < 8 || version > 9)
|
||||||
|
sysfatal("bad version %d in vdpack", version);
|
||||||
|
|
||||||
|
/* constant part */
|
||||||
n = 4 + /* magic */
|
n = 4 + /* magic */
|
||||||
2 + /* version */
|
2 + /* version */
|
||||||
4 + /* entry */
|
4 + /* entry */
|
||||||
4 + /* guid */
|
|
||||||
4 + /* mentry */
|
|
||||||
4 + /* mgen */
|
|
||||||
8 + /* qid */
|
8 + /* qid */
|
||||||
4 + /* mtime */
|
4 + /* mtime */
|
||||||
4 + /* mcount */
|
4 + /* mcount */
|
||||||
|
@ -392,6 +391,13 @@ vdsize(VacDir *dir)
|
||||||
4 + /* mode */
|
4 + /* mode */
|
||||||
0;
|
0;
|
||||||
|
|
||||||
|
if(version == 9){
|
||||||
|
n += 4 + /* gen */
|
||||||
|
4 + /* mentry */
|
||||||
|
4 + /* mgen */
|
||||||
|
0;
|
||||||
|
}
|
||||||
|
|
||||||
/* strings */
|
/* strings */
|
||||||
n += 2 + strlen(dir->elem);
|
n += 2 + strlen(dir->elem);
|
||||||
n += 2 + strlen(dir->uid);
|
n += 2 + strlen(dir->uid);
|
||||||
|
@ -399,35 +405,53 @@ vdsize(VacDir *dir)
|
||||||
n += 2 + strlen(dir->mid);
|
n += 2 + strlen(dir->mid);
|
||||||
|
|
||||||
/* optional sections */
|
/* optional sections */
|
||||||
|
if(version < 9 && dir->plan9) {
|
||||||
|
n += 3 + /* option header */
|
||||||
|
8 + /* path */
|
||||||
|
4; /* version */
|
||||||
|
}
|
||||||
if(dir->qidspace) {
|
if(dir->qidspace) {
|
||||||
n += 3 + /* option header */
|
n += 3 + /* option header */
|
||||||
8 + /* qid offset */
|
8 + /* qid offset */
|
||||||
8; /* qid max */
|
8; /* qid max */
|
||||||
}
|
}
|
||||||
|
if(version < 9 && dir->gen) {
|
||||||
|
n += 3 + /* option header */
|
||||||
|
4; /* gen */
|
||||||
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vdpack(VacDir *dir, MetaEntry *me)
|
vdpack(VacDir *dir, MetaEntry *me, int version)
|
||||||
{
|
{
|
||||||
uchar *p;
|
uchar *p;
|
||||||
ulong t32;
|
ulong t32;
|
||||||
|
|
||||||
|
if(version < 8 || version > 9)
|
||||||
|
sysfatal("bad version %d in vdpack", version);
|
||||||
|
|
||||||
p = me->p;
|
p = me->p;
|
||||||
|
|
||||||
U32PUT(p, DirMagic);
|
U32PUT(p, DirMagic);
|
||||||
U16PUT(p+4, 9); /* version */
|
U16PUT(p+4, version); /* version */
|
||||||
p += 6;
|
p += 6;
|
||||||
|
|
||||||
p += stringpack(dir->elem, p);
|
p += stringpack(dir->elem, p);
|
||||||
|
|
||||||
U32PUT(p, dir->entry);
|
U32PUT(p, dir->entry);
|
||||||
U32PUT(p+4, dir->gen);
|
p += 4;
|
||||||
U32PUT(p+8, dir->mentry);
|
|
||||||
U32PUT(p+12, dir->mgen);
|
if(version == 9){
|
||||||
U64PUT(p+16, dir->qid, t32);
|
U32PUT(p, dir->gen);
|
||||||
p += 24;
|
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->uid, p);
|
||||||
p += stringpack(dir->gid, p);
|
p += stringpack(dir->gid, p);
|
||||||
|
@ -439,6 +463,15 @@ vdpack(VacDir *dir, MetaEntry *me)
|
||||||
U32PUT(p+12, dir->atime);
|
U32PUT(p+12, dir->atime);
|
||||||
U32PUT(p+16, dir->mode);
|
U32PUT(p+16, dir->mode);
|
||||||
p += 5*4;
|
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) {
|
if(dir->qidspace) {
|
||||||
U8PUT(p, DirQidSpaceEntry);
|
U8PUT(p, DirQidSpaceEntry);
|
||||||
|
@ -446,12 +479,20 @@ vdpack(VacDir *dir, MetaEntry *me)
|
||||||
p += 3;
|
p += 3;
|
||||||
U64PUT(p, dir->qidoffset, t32);
|
U64PUT(p, dir->qidoffset, t32);
|
||||||
U64PUT(p+8, dir->qidmax, 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);
|
assert(p == me->p + me->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
vdunpack(VacDir *dir, MetaEntry *me)
|
vdunpack(VacDir *dir, MetaEntry *me)
|
||||||
{
|
{
|
||||||
|
@ -463,14 +504,12 @@ vdunpack(VacDir *dir, MetaEntry *me)
|
||||||
|
|
||||||
memset(dir, 0, sizeof(VacDir));
|
memset(dir, 0, sizeof(VacDir));
|
||||||
|
|
||||||
if(0)print("vdUnpack\n");
|
|
||||||
/* magic */
|
/* magic */
|
||||||
if(n < 4 || U32GET(p) != DirMagic)
|
if(n < 4 || U32GET(p) != DirMagic)
|
||||||
goto Err;
|
goto Err;
|
||||||
p += 4;
|
p += 4;
|
||||||
n -= 4;
|
n -= 4;
|
||||||
|
|
||||||
if(0)print("vdUnpack: got magic\n");
|
|
||||||
/* version */
|
/* version */
|
||||||
if(n < 2)
|
if(n < 2)
|
||||||
goto Err;
|
goto Err;
|
||||||
|
@ -480,14 +519,10 @@ if(0)print("vdUnpack: got magic\n");
|
||||||
p += 2;
|
p += 2;
|
||||||
n -= 2;
|
n -= 2;
|
||||||
|
|
||||||
if(0)print("vdUnpack: got version\n");
|
|
||||||
|
|
||||||
/* elem */
|
/* elem */
|
||||||
if(stringunpack(&dir->elem, &p, &n) < 0)
|
if(stringunpack(&dir->elem, &p, &n) < 0)
|
||||||
goto Err;
|
goto Err;
|
||||||
|
|
||||||
if(0)print("vdUnpack: got elem\n");
|
|
||||||
|
|
||||||
/* entry */
|
/* entry */
|
||||||
if(n < 4)
|
if(n < 4)
|
||||||
goto Err;
|
goto Err;
|
||||||
|
@ -495,8 +530,6 @@ if(0)print("vdUnpack: got elem\n");
|
||||||
p += 4;
|
p += 4;
|
||||||
n -= 4;
|
n -= 4;
|
||||||
|
|
||||||
if(0)print("vdUnpack: got entry\n");
|
|
||||||
|
|
||||||
if(version < 9) {
|
if(version < 9) {
|
||||||
dir->gen = 0;
|
dir->gen = 0;
|
||||||
dir->mentry = dir->entry+1;
|
dir->mentry = dir->entry+1;
|
||||||
|
@ -511,8 +544,6 @@ if(0)print("vdUnpack: got entry\n");
|
||||||
n -= 3*4;
|
n -= 3*4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0)print("vdUnpack: got gen etc\n");
|
|
||||||
|
|
||||||
/* size is gotten from DirEntry */
|
/* size is gotten from DirEntry */
|
||||||
|
|
||||||
/* qid */
|
/* qid */
|
||||||
|
@ -522,7 +553,6 @@ if(0)print("vdUnpack: got gen etc\n");
|
||||||
p += 8;
|
p += 8;
|
||||||
n -= 8;
|
n -= 8;
|
||||||
|
|
||||||
if(0)print("vdUnpack: got qid\n");
|
|
||||||
/* skip replacement */
|
/* skip replacement */
|
||||||
if(version == 7) {
|
if(version == 7) {
|
||||||
if(n < VtScoreSize)
|
if(n < VtScoreSize)
|
||||||
|
@ -543,7 +573,6 @@ if(0)print("vdUnpack: got qid\n");
|
||||||
if(stringunpack(&dir->mid, &p, &n) < 0)
|
if(stringunpack(&dir->mid, &p, &n) < 0)
|
||||||
goto Err;
|
goto Err;
|
||||||
|
|
||||||
if(0)print("vdUnpack: got ids\n");
|
|
||||||
if(n < 5*4)
|
if(n < 5*4)
|
||||||
goto Err;
|
goto Err;
|
||||||
dir->mtime = U32GET(p);
|
dir->mtime = U32GET(p);
|
||||||
|
@ -554,7 +583,6 @@ if(0)print("vdUnpack: got ids\n");
|
||||||
p += 5*4;
|
p += 5*4;
|
||||||
n -= 5*4;
|
n -= 5*4;
|
||||||
|
|
||||||
if(0)print("vdUnpack: got times\n");
|
|
||||||
/* optional meta data */
|
/* optional meta data */
|
||||||
while(n > 0) {
|
while(n > 0) {
|
||||||
if(n < 3)
|
if(n < 3)
|
||||||
|
@ -594,15 +622,12 @@ if(0)print("vdUnpack: got times\n");
|
||||||
p += nn;
|
p += nn;
|
||||||
n -= nn;
|
n -= nn;
|
||||||
}
|
}
|
||||||
if(0)print("vdUnpack: got options\n");
|
|
||||||
|
|
||||||
if(p != me->p + me->size)
|
if(p != me->p + me->size)
|
||||||
goto Err;
|
goto Err;
|
||||||
|
|
||||||
if(0)print("vdUnpack: correct size\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
Err:
|
Err:
|
||||||
if(0)print("vdUnpack: XXXXXXXXXXXX EbadMeta\n");
|
|
||||||
werrstr(EBadMeta);
|
werrstr(EBadMeta);
|
||||||
vdcleanup(dir);
|
vdcleanup(dir);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -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
293
src/cmd/vac/unvac.c
Normal 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;
|
||||||
|
}
|
|
@ -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
|
@ -5,7 +5,18 @@
|
||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include "fns.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 Sink Sink;
|
||||||
typedef struct MetaSink MetaSink;
|
typedef struct MetaSink MetaSink;
|
||||||
|
@ -101,6 +112,8 @@ int nowrite;
|
||||||
int merge;
|
int merge;
|
||||||
char *isi;
|
char *isi;
|
||||||
|
|
||||||
|
char **expandargv(char**);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
|
@ -116,6 +129,9 @@ threadmain(int argc, char *argv[])
|
||||||
char *host = nil;
|
char *host = nil;
|
||||||
int statsflag = 0;
|
int statsflag = 0;
|
||||||
|
|
||||||
|
/* see comment above */
|
||||||
|
_p9usepwlibrary = 1;
|
||||||
|
|
||||||
atexit(cleanup);
|
atexit(cleanup);
|
||||||
|
|
||||||
ARGBEGIN{
|
ARGBEGIN{
|
||||||
|
@ -194,20 +210,71 @@ threadmain(int argc, char *argv[])
|
||||||
|
|
||||||
qsort(exclude, nexclude, sizeof(char*), strpcmp);
|
qsort(exclude, nexclude, sizeof(char*), strpcmp);
|
||||||
|
|
||||||
|
argv = expandargv(argv);
|
||||||
|
|
||||||
vac(z, argv);
|
vac(z, argv);
|
||||||
|
|
||||||
if(vtsync(z) < 0)
|
if(vtsync(z) < 0)
|
||||||
fprint(2, "warning: could not ask server to flush pending writes: %r\n");
|
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,
|
fprint(2, "files %ld:%ld data %ld:%ld:%ld meta %ld\n", stats.file, stats.sfile,
|
||||||
stats.data, stats.skip, stats.sdata, stats.meta);
|
stats.data, stats.skip, stats.sdata, stats.meta);
|
||||||
/*packetStats(); */
|
dup(2, 1);
|
||||||
|
packetstats();
|
||||||
|
}
|
||||||
vthangup(z);
|
vthangup(z);
|
||||||
|
|
||||||
threadexitsall(0);
|
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
|
static int
|
||||||
strpcmp(const void *p0, const void *p1)
|
strpcmp(const void *p0, const void *p1)
|
||||||
{
|
{
|
||||||
|
@ -353,7 +420,7 @@ vac(VtConn *z, char *argv[])
|
||||||
|
|
||||||
vtrootpack(&root, buf);
|
vtrootpack(&root, buf);
|
||||||
if(vacwrite(z, score, VtRootType, buf, VtRootSize) < 0)
|
if(vacwrite(z, score, VtRootType, buf, VtRootSize) < 0)
|
||||||
sysfatal("vacWrite failed: %r");
|
sysfatal("vacwrite: %r");
|
||||||
|
|
||||||
fprint(fd, "vac:%V\n", score);
|
fprint(fd, "vac:%V\n", score);
|
||||||
|
|
||||||
|
@ -566,7 +633,6 @@ vacdata(DirSink *dsink, int fd, char *lname, VacFile *vf, Dir *dir)
|
||||||
if(vfblocks > 1)
|
if(vfblocks > 1)
|
||||||
block += vacdataskip(sink, vf, fd, vfblocks, buf, lname);
|
block += vacdataskip(sink, vf, fd, vfblocks, buf, lname);
|
||||||
|
|
||||||
if(0) fprint(2, "vacData: %s: %ld\n", lname, block);
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
n = readn(fd, buf, bsize);
|
n = readn(fd, buf, bsize);
|
||||||
if(0 && n < 0)
|
if(0 && n < 0)
|
||||||
|
@ -857,7 +923,7 @@ sinkwrite(Sink *k, uchar *p, int n)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(n > k->dir.dsize)
|
if(n > k->dir.dsize)
|
||||||
sysfatal("sinkWrite: size too big");
|
sysfatal("sinkwrite: size too big");
|
||||||
|
|
||||||
if((k->dir.type&~VtTypeDepthMask) == VtDirType){
|
if((k->dir.type&~VtTypeDepthMask) == VtDirType){
|
||||||
type = VtDirType;
|
type = VtDirType;
|
||||||
|
@ -867,7 +933,7 @@ sinkwrite(Sink *k, uchar *p, int n)
|
||||||
stats.data++;
|
stats.data++;
|
||||||
}
|
}
|
||||||
if(vacwrite(k->z, score, type, p, n) < 0)
|
if(vacwrite(k->z, score, type, p, n) < 0)
|
||||||
sysfatal("vacWrite failed: %r");
|
sysfatal("vacwrite: %r");
|
||||||
|
|
||||||
sinkwritescore(k, score, n);
|
sinkwritescore(k, score, n);
|
||||||
}
|
}
|
||||||
|
@ -924,7 +990,7 @@ sinkclose(Sink *k)
|
||||||
p = k->buf+i*kd->psize;
|
p = k->buf+i*kd->psize;
|
||||||
stats.meta++;
|
stats.meta++;
|
||||||
if(vacwrite(k->z, k->pbuf[i+1], base+1+i, p, k->pbuf[i]-p) < 0)
|
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;
|
k->pbuf[i+1] += VtScoreSize;
|
||||||
}
|
}
|
||||||
memmove(kd->score, k->pbuf[i] - VtScoreSize, VtScoreSize);
|
memmove(kd->score, k->pbuf[i] - VtScoreSize, VtScoreSize);
|
||||||
|
@ -1141,6 +1207,7 @@ metasinkwrite(MetaSink *k, uchar *data, int n)
|
||||||
void
|
void
|
||||||
metasinkwritedir(MetaSink *ms, VacDir *dir)
|
metasinkwritedir(MetaSink *ms, VacDir *dir)
|
||||||
{
|
{
|
||||||
|
|
||||||
metasinkputuint32(ms, DirMagic);
|
metasinkputuint32(ms, DirMagic);
|
||||||
metasinkputc(ms, Version>>8);
|
metasinkputc(ms, Version>>8);
|
||||||
metasinkputc(ms, Version);
|
metasinkputc(ms, Version);
|
||||||
|
@ -1218,7 +1285,6 @@ plan9tovacdir(VacDir *vd, Dir *dir, ulong entry, uvlong qid)
|
||||||
vd->p9version = dir->qid.vers;
|
vd->p9version = dir->qid.vers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
metasinkeor(MetaSink *k)
|
metasinkeor(MetaSink *k)
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,13 +101,6 @@ int vacfssync(VacFs *fs);
|
||||||
int vacfssnapshot(VacFs *fs, char *src, char *dst);
|
int vacfssnapshot(VacFs *fs, char *src, char *dst);
|
||||||
int vacfsgetscore(VacFs *fs, u8int *score);
|
int vacfsgetscore(VacFs *fs, u8int *score);
|
||||||
|
|
||||||
/*
|
|
||||||
* other ideas
|
|
||||||
*
|
|
||||||
* VacFs *vfsSnapshot(VacFs*, char *src);
|
|
||||||
* int vfsGraft(VacFs*, char *name, VacFs*);
|
|
||||||
*/
|
|
||||||
|
|
||||||
VacFile *vacfsgetroot(VacFs *fs);
|
VacFile *vacfsgetroot(VacFs *fs);
|
||||||
VacFile *vacfileopen(VacFs *fs, char *path);
|
VacFile *vacfileopen(VacFs *fs, char *path);
|
||||||
VacFile *vacfilecreate(VacFile *file, char *elem, ulong perm, char *muid);
|
VacFile *vacfilecreate(VacFile *file, char *elem, ulong perm, char *muid);
|
||||||
|
@ -140,4 +133,4 @@ void vdcopy(VacDir *dst, VacDir *src);
|
||||||
VacDirEnum *vdeopen(VacFile*);
|
VacDirEnum *vdeopen(VacFile*);
|
||||||
int vderead(VacDirEnum*, VacDir *);
|
int vderead(VacDirEnum*, VacDir *);
|
||||||
void vdeclose(VacDirEnum*);
|
void vdeclose(VacDirEnum*);
|
||||||
|
int vdeunread(VacDirEnum*);
|
||||||
|
|
|
@ -5,18 +5,12 @@
|
||||||
#include "vac.h"
|
#include "vac.h"
|
||||||
|
|
||||||
typedef struct Fid Fid;
|
typedef struct Fid Fid;
|
||||||
typedef struct DirBuf DirBuf;
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
OPERM = 0x3 /* mask of all permission types in open mode */
|
OPERM = 0x3 /* mask of all permission types in open mode */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
DirBufSize = 20
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Fid
|
struct Fid
|
||||||
{
|
{
|
||||||
short busy;
|
short busy;
|
||||||
|
@ -25,18 +19,8 @@ struct Fid
|
||||||
char *user;
|
char *user;
|
||||||
Qid qid;
|
Qid qid;
|
||||||
VacFile *file;
|
VacFile *file;
|
||||||
|
|
||||||
DirBuf *db;
|
|
||||||
|
|
||||||
Fid *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DirBuf
|
|
||||||
{
|
|
||||||
VacDirEnum *vde;
|
VacDirEnum *vde;
|
||||||
VacDir buf[DirBufSize];
|
Fid *next;
|
||||||
int i, n;
|
|
||||||
int eof;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -73,12 +57,8 @@ int perm(Fid*, int);
|
||||||
int permf(VacFile*, char*, int);
|
int permf(VacFile*, char*, int);
|
||||||
ulong getl(void *p);
|
ulong getl(void *p);
|
||||||
void init(char*, char*, long, int);
|
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 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);
|
void srv(void* a);
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +121,6 @@ threadmain(int argc, char *argv[])
|
||||||
int stdio = 0;
|
int stdio = 0;
|
||||||
char *host = nil;
|
char *host = nil;
|
||||||
long ncache = 1000;
|
long ncache = 1000;
|
||||||
int readOnly = 1;
|
|
||||||
|
|
||||||
fmtinstall('H', encodefmt);
|
fmtinstall('H', encodefmt);
|
||||||
fmtinstall('V', vtscorefmt);
|
fmtinstall('V', vtscorefmt);
|
||||||
|
@ -184,7 +163,20 @@ threadmain(int argc, char *argv[])
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
initfcalls();
|
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)
|
if(pipe(p) < 0)
|
||||||
sysfatal("pipe failed: %r");
|
sysfatal("pipe failed: %r");
|
||||||
|
@ -294,19 +286,6 @@ rattach(Fid *f)
|
||||||
return 0;
|
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*
|
char*
|
||||||
rwalk(Fid *f)
|
rwalk(Fid *f)
|
||||||
{
|
{
|
||||||
|
@ -356,7 +335,7 @@ rwalk(Fid *f)
|
||||||
err = Eperm;
|
err = Eperm;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nfile = _vfWalk(file, rhdr.wname[nqid]);
|
nfile = vacfilewalk(file, rhdr.wname[nqid]);
|
||||||
if(nfile == nil)
|
if(nfile == nil)
|
||||||
break;
|
break;
|
||||||
vacfiledecref(file);
|
vacfiledecref(file);
|
||||||
|
@ -410,7 +389,7 @@ ropen(Fid *f)
|
||||||
if(!perm(f, Pread))
|
if(!perm(f, Pread))
|
||||||
return vtstrdup(Eperm);
|
return vtstrdup(Eperm);
|
||||||
thdr.qid = f->qid;
|
thdr.qid = f->qid;
|
||||||
f->db = nil;
|
f->vde = nil;
|
||||||
f->open = 1;
|
f->open = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -564,8 +543,8 @@ rclunk(Fid *f)
|
||||||
if(f->file)
|
if(f->file)
|
||||||
vacfiledecref(f->file);
|
vacfiledecref(f->file);
|
||||||
f->file = nil;
|
f->file = nil;
|
||||||
dirBufFree(f->db);
|
vdeclose(f->vde);
|
||||||
f->db = nil;
|
f->vde = nil;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,8 +567,6 @@ rremove(Fid *f)
|
||||||
|
|
||||||
if(!vacfileremove(vf, "none")) {
|
if(!vacfileremove(vf, "none")) {
|
||||||
rerrstr(errbuf, sizeof errbuf);
|
rerrstr(errbuf, sizeof errbuf);
|
||||||
print("vfRemove failed: %s\n", errbuf);
|
|
||||||
|
|
||||||
err = errbuf;
|
err = errbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,7 +588,7 @@ rstat(Fid *f)
|
||||||
parent = vacfilegetparent(f->file);
|
parent = vacfilegetparent(f->file);
|
||||||
vacfilegetdir(f->file, &dir);
|
vacfilegetdir(f->file, &dir);
|
||||||
thdr.stat = statbuf;
|
thdr.stat = statbuf;
|
||||||
thdr.nstat = vdStat(parent, &dir, thdr.stat, sizeof statbuf);
|
thdr.nstat = vacstat(parent, &dir, thdr.stat, sizeof statbuf);
|
||||||
vdcleanup(&dir);
|
vdcleanup(&dir);
|
||||||
vacfiledecref(parent);
|
vacfiledecref(parent);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -626,7 +603,7 @@ rwstat(Fid *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vdStat(VacFile *parent, VacDir *vd, uchar *p, int np)
|
vacstat(VacFile *parent, VacDir *vd, uchar *p, int np)
|
||||||
{
|
{
|
||||||
char *ext;
|
char *ext;
|
||||||
int n, ret;
|
int n, ret;
|
||||||
|
@ -694,96 +671,39 @@ vdStat(VacFile *parent, VacDir *vd, uchar *p, int np)
|
||||||
return ret;
|
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
|
int
|
||||||
vacdirread(Fid *f, char *p, long off, long cnt)
|
vacdirread(Fid *f, char *p, long off, long cnt)
|
||||||
{
|
{
|
||||||
int n, nb;
|
int i, n, nb;
|
||||||
VacDir *vd;
|
VacDir vd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* special case of rewinding a directory
|
* special case of rewinding a directory
|
||||||
* otherwise ignore the offset
|
* otherwise ignore the offset
|
||||||
*/
|
*/
|
||||||
if(off == 0 && f->db) {
|
if(off == 0 && f->vde){
|
||||||
dirBufFree(f->db);
|
vdeclose(f->vde);
|
||||||
f->db = nil;
|
f->vde = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(f->db == nil)
|
if(f->vde == nil){
|
||||||
f->db = dirBufAlloc(f->file);
|
f->vde = vdeopen(f->file);
|
||||||
|
if(f->vde == nil)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
for(nb = 0; nb < cnt; nb += n) {
|
for(nb = 0; nb < cnt; nb += n) {
|
||||||
vd = dirBufGet(f->db);
|
i = vderead(f->vde, &vd);
|
||||||
if(vd == nil) {
|
if(i < 0)
|
||||||
if(!f->db->eof)
|
return -1;
|
||||||
return -1;
|
if(i == 0)
|
||||||
break;
|
break;
|
||||||
}
|
n = vacstat(f->file, &vd, (uchar*)p, cnt-nb);
|
||||||
n = vdStat(f->file, vd, (uchar*)p, cnt-nb);
|
|
||||||
if(n <= BIT16SZ) {
|
if(n <= BIT16SZ) {
|
||||||
dirBufUnget(f->db);
|
vdeunread(f->vde);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vdcleanup(vd);
|
vdcleanup(&vd);
|
||||||
p += n;
|
p += n;
|
||||||
}
|
}
|
||||||
return nb;
|
return nb;
|
||||||
|
@ -885,24 +805,6 @@ perm(Fid *f, int p)
|
||||||
return permf(f->file, f->user, 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
|
void
|
||||||
vacshutdown(void)
|
vacshutdown(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
Loading…
Reference in a new issue