aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/vac/cache.c876
-rw-r--r--src/cmd/vac/dat.h149
-rw-r--r--src/cmd/vac/error.c2
-rw-r--r--src/cmd/vac/error.h2
-rw-r--r--src/cmd/vac/file.c2276
-rw-r--r--src/cmd/vac/fns.h55
-rw-r--r--src/cmd/vac/fs.c187
-rw-r--r--src/cmd/vac/mkfile3
-rw-r--r--src/cmd/vac/pack.c246
-rw-r--r--src/cmd/vac/source.c390
-rw-r--r--src/cmd/vac/stdinc.h9
-rw-r--r--src/cmd/vac/vac.c746
-rw-r--r--src/cmd/vac/vac.h109
-rw-r--r--src/cmd/vac/vtdump.c215
14 files changed, 2365 insertions, 2900 deletions
diff --git a/src/cmd/vac/cache.c b/src/cmd/vac/cache.c
deleted file mode 100644
index fc34d688..00000000
--- a/src/cmd/vac/cache.c
+++ /dev/null
@@ -1,876 +0,0 @@
-#include "stdinc.h"
-#include "vac.h"
-#include "dat.h"
-#include "fns.h"
-
-typedef struct Label Label;
-
-enum {
- BadHeap = ~0,
-};
-
-/*
- * the plan is to store data to the cache in c->size blocks
- * with the block zero extended to fill it out. When writing to
- * venti, the block will be zero truncated. The walker will also check
- * that the block fits within psize or dsize as the case may be.
- */
-
-struct Cache
-{
- VtLock *lk;
- VtSession *z;
- u32int now; /* ticks for usage timestamps */
- int size; /* max. size of any block; allocated to each block */
- Lump **heads; /* hash table for finding address */
- int nheap; /* number of available victims */
- Lump **heap; /* heap for locating victims */
- long nblocks; /* number of blocks allocated */
- Lump *blocks; /* array of block descriptors */
- u8int *mem; /* memory for all block descriptors */
- Lump *free; /* free list of lumps */
-
- long hashSize;
-};
-
-/*
- * the tag for a block is hash(index, parent tag)
- */
-
-struct Label {
- uchar gen[4];
- uchar state;
- uchar type; /* top bit indicates it is part of a directory */
- uchar tag[4]; /* tag of file it is in */
-};
-
-
-static char ENoDir[] = "directory entry is not allocated";
-
-static void fixHeap(int si, Lump *b);
-static int upHeap(int i, Lump *b);
-static int downHeap(int i, Lump *b);
-static char *lumpState(int);
-static void lumpSetState(Lump *u, int state);
-
-Cache *
-cacheAlloc(VtSession *z, int blockSize, long nblocks)
-{
- int i;
- Cache *c;
- Lump *b;
-
- c = vtMemAllocZ(sizeof(Cache));
-
- c->lk = vtLockAlloc();
- c->z = z;
- c->size = blockSize;
- c->nblocks = nblocks;
- c->hashSize = nblocks;
- c->heads = vtMemAllocZ(c->hashSize*sizeof(Lump*));
- c->heap = vtMemAllocZ(nblocks*sizeof(Lump*));
- c->blocks = vtMemAllocZ(nblocks*sizeof(Lump));
- c->mem = vtMemAllocZ(nblocks * blockSize);
- for(i = 0; i < nblocks; i++){
- b = &c->blocks[i];
- b->lk = vtLockAlloc();
- b->c = c;
- b->data = &c->mem[i * blockSize];
- b->addr = i+1;
- b->state = LumpFree;
- b->heap = BadHeap;
- b->next = c->free;
- c->free = b;
- }
- c->nheap = 0;
-
- return c;
-}
-
-long
-cacheGetSize(Cache *c)
-{
- return c->nblocks;
-}
-
-int
-cacheGetBlockSize(Cache *c)
-{
- return c->size;
-}
-
-int
-cacheSetSize(Cache *c, long nblocks)
-{
- USED(c);
- USED(nblocks);
- return 0;
-}
-
-void
-cacheFree(Cache *c)
-{
- int i;
-
- for(i = 0; i < c->nblocks; i++){
- assert(c->blocks[i].ref == 0);
- vtLockFree(c->blocks[i].lk);
- }
- vtMemFree(c->heads);
- vtMemFree(c->blocks);
- vtMemFree(c->mem);
- vtMemFree(c);
-}
-
-static u32int
-hash(Cache *c, uchar score[VtScoreSize], int type)
-{
- u32int h;
- uchar *p = score + VtScoreSize-4;
-
- h = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
- h += type;
- return h % c->hashSize;
-}
-
-static void
-findLump(Cache *c, Lump *bb)
-{
- Lump *b, *last;
- int h;
-
- last = nil;
- h = hash(c, bb->score, bb->type);
- for(b = c->heads[h]; b != nil; b = b->next){
- if(last != b->prev)
- vtFatal("bad prev link");
- if(b == bb)
- return;
- last = b;
- }
- vtFatal("block missing from hash table");
-}
-
-void
-cacheCheck(Cache *c)
-{
- u32int size, now;
- int i, k, refed, free;
- static uchar zero[VtScoreSize];
- Lump *p;
-
- size = c->size;
- now = c->now;
-
- free = 0;
- for(p=c->free; p; p=p->next)
- free++;
- for(i = 0; i < c->nheap; i++){
- if(c->heap[i]->heap != i)
- vtFatal("mis-heaped at %d: %d", i, c->heap[i]->heap);
- if(i > 0 && c->heap[(i - 1) >> 1]->used2 - now > c->heap[i]->used2 - now)
- vtFatal("bad heap ordering");
- k = (i << 1) + 1;
- if(k < c->nheap && c->heap[i]->used2 - now > c->heap[k]->used2 - now)
- vtFatal("bad heap ordering");
- k++;
- if(k < c->nheap && c->heap[i]->used2 - now > c->heap[k]->used2 - now)
- vtFatal("bad heap ordering");
- }
-
- refed = 0;
- for(i = 0; i < c->nblocks; i++){
- if(c->blocks[i].data != &c->mem[i * size])
- vtFatal("mis-blocked at %d", i);
- if(c->blocks[i].ref && c->blocks[i].heap == BadHeap){
- refed++;
- }
- if(memcmp(zero, c->blocks[i].score, VtScoreSize))
- findLump(c, &c->blocks[i]);
- }
-if(refed > 0)fprint(2, "cacheCheck: nheap %d refed %d free %d\n", c->nheap, refed, free);
- assert(c->nheap + refed + free == c->nblocks);
- refed = 0;
- for(i = 0; i < c->nblocks; i++){
- if(c->blocks[i].ref) {
-if(1)fprint(2, "%d %V %d %s\n", c->blocks[i].type, c->blocks[i].score, c->blocks[i].ref, lumpState(c->blocks[i].state));
- refed++;
- }
- }
-if(refed > 0)fprint(2, "cacheCheck: in used %d\n", refed);
-}
-
-/*
- * delete an arbitrary block from the heap
- */
-static void
-delHeap(Lump *db)
-{
- fixHeap(db->heap, db->c->heap[--db->c->nheap]);
- db->heap = BadHeap;
-}
-
-static void
-fixHeap(int si, Lump *b)
-{
- int i;
-
- i = upHeap(si, b);
- if(i == si)
- downHeap(i, b);
-}
-
-static int
-upHeap(int i, Lump *b)
-{
- Lump *bb;
- u32int now;
- int p;
- Cache *c;
-
- c = b->c;
- now = c->now;
- for(; i != 0; i = p){
- p = (i - 1) >> 1;
- bb = c->heap[p];
- if(b->used2 - now >= bb->used2 - now)
- break;
- c->heap[i] = bb;
- bb->heap = i;
- }
- c->heap[i] = b;
- b->heap = i;
-
- return i;
-}
-
-static int
-downHeap(int i, Lump *b)
-{
- Lump *bb;
- u32int now;
- int k;
- Cache *c;
-
- c = b->c;
- now = c->now;
- for(; ; i = k){
- k = (i << 1) + 1;
- if(k >= c->nheap)
- break;
- if(k + 1 < c->nheap && c->heap[k]->used2 - now > c->heap[k + 1]->used2 - now)
- k++;
- bb = c->heap[k];
- if(b->used2 - now <= bb->used2 - now)
- break;
- c->heap[i] = bb;
- bb->heap = i;
- }
- c->heap[i] = b;
- b->heap = i;
- return i;
-}
-
-
-/* called with c->lk held */
-Lump *
-cacheBumpLump(Cache *c)
-{
- Lump *b;
-
- /*
- * missed: locate the block with the oldest second to last use.
- * remove it from the heap, and fix up the heap.
- */
- if(c->free) {
- b = c->free;
- c->free = b->next;
- } else {
- for(;;){
- if(c->nheap == 0) {
- cacheCheck(c);
- assert(0);
- return nil;
- }
- b = c->heap[0];
- delHeap(b);
- if(b->ref == 0)
- break;
- }
-
- /*
- * unchain the block from hash chain
- */
- if(b->prev == nil)
- c->heads[hash(c, b->score, b->type)] = b->next;
- else
- b->prev->next = b->next;
- if(b->next != nil)
- b->next->prev = b->prev;
-
- }
-
- /*
- * the new block has no last use, so assume it happens sometime in the middle
- */
- b->used = (b->used2 + c->now) / 2;
- b->asize = 0;
-
- return b;
-}
-
-Lump *
-cacheAllocLump(Cache *c, int type, int size, int dir)
-{
- Lump *b;
- ulong h;
-
- assert(size <= c->size);
-
-again:
- vtLock(c->lk);
- b = cacheBumpLump(c);
- if(b == nil) {
- vtUnlock(c->lk);
-fprint(2, "cache is full\n");
- /* XXX should be better */
- sleep(100);
- goto again;
- }
-
- vtLock(b->lk);
-
- assert(b->ref == 0);
- b->ref++;
- b->used2 = b->used;
- b->used = c->now++;
-
- /* convert addr into score */
- memset(b->score, 0, VtScoreSize-4);
- b->score[VtScoreSize-4] = b->addr>>24;
- b->score[VtScoreSize-3] = b->addr>>16;
- b->score[VtScoreSize-2] = b->addr>>8;
- b->score[VtScoreSize-1] = b->addr;
-
- b->dir = dir;
- b->type = type;
- b->gen = 0;
- b->asize = size;
- b->state = LumpFree;
-
- h = hash(c, b->score, b->type);
-
- /* chain onto correct hash */
- b->next = c->heads[h];
- c->heads[h] = b;
- if(b->next != nil)
- b->next->prev = b;
- b->prev = nil;
-
- vtUnlock(c->lk);
-
- vtZeroExtend(type, b->data, 0, size);
- lumpSetState(b, LumpActive);
-
- return b;
-}
-
-int
-scoreIsLocal(uchar score[VtScoreSize])
-{
- static uchar zero[VtScoreSize];
-
- return memcmp(score, zero, VtScoreSize-4) == 0;
-}
-
-Lump *
-cacheGetLump(Cache *c, uchar score[VtScoreSize], int type, int size)
-{
- Lump *b;
- ulong h;
- int n;
- static uchar zero[VtScoreSize];
-
- assert(size <= c->size);
-
- h = hash(c, score, type);
-
-again:
- /*
- * look for the block in the cache
- */
- vtLock(c->lk);
- for(b = c->heads[h]; b != nil; b = b->next){
- if(memcmp(b->score, score, VtScoreSize) == 0 && b->type == type)
- goto found;
- }
-
- /* should not be looking for a temp block */
- if(scoreIsLocal(score)) {
- if(memcmp(score, zero, VtScoreSize) == 0)
- vtSetError("looking for zero score");
- else
- vtSetError("missing local block");
- vtUnlock(c->lk);
- return nil;
- }
-
- b = cacheBumpLump(c);
- if(b == nil) {
- vtUnlock(c->lk);
- sleep(100);
- goto again;
- }
-
- /* chain onto correct hash */
- b->next = c->heads[h];
- c->heads[h] = b;
- if(b->next != nil)
- b->next->prev = b;
- b->prev = nil;
-
- memmove(b->score, score, VtScoreSize);
- b->type = type;
- b->state = LumpFree;
-
-found:
- b->ref++;
- b->used2 = b->used;
- b->used = c->now++;
- if(b->heap != BadHeap)
- fixHeap(b->heap, b);
-
- vtUnlock(c->lk);
-
- vtLock(b->lk);
- if(b->state != LumpFree)
- return b;
-
- n = vtRead(c->z, score, type, b->data, size);
- if(n < 0) {
- lumpDecRef(b, 1);
- return nil;
- }
- if(!vtSha1Check(score, b->data, n)) {
- vtSetError("vtSha1Check failed");
- lumpDecRef(b, 1);
- return nil;
- }
- vtZeroExtend(type, b->data, n, size);
- b->asize = size;
- lumpSetState(b, LumpVenti);
-
- return b;
-}
-
-static char *
-lumpState(int state)
-{
- switch(state) {
- default:
- return "Unknown!!";
- case LumpFree:
- return "Free";
- case LumpActive:
- return "Active";
- case LumpSnap:
- return "Snap";
- case LumpZombie:
- return "Zombie";
- case LumpVenti:
- return "Venti";
- }
-}
-
-static void
-lumpSetState(Lump *u, int state)
-{
-// if(u->state != LumpFree)
-// fprint(2, "%V: %s -> %s\n", u->score, lumpState(u->state), lumpState(state));
- u->state = state;
-}
-
-int
-lumpGetScore(Lump *u, int offset, uchar score[VtScoreSize])
-{
- uchar *sp;
- VtRoot root;
- VtEntry dir;
-
- vtLock(u->lk);
-
- switch(u->type) {
- default:
- vtSetError("bad type");
- goto Err;
- case VtPointerType0:
- case VtPointerType1:
- case VtPointerType2:
- case VtPointerType3:
- case VtPointerType4:
- case VtPointerType5:
- case VtPointerType6:
- if((offset+1)*VtScoreSize > u->asize)
- sp = nil;
- else
- sp = u->data + offset*VtScoreSize;
- break;
- case VtRootType:
- if(u->asize < VtRootSize) {
- vtSetError("runt root block");
- goto Err;
- }
- if(!vtRootUnpack(&root, u->data))
- goto Err;
- sp = root.score;
- break;
- case VtDirType:
- if((offset+1)*VtEntrySize > u->asize) {
- vtSetError(ENoDir);
- goto Err;
- }
- if(!vtEntryUnpack(&dir, u->data, offset))
- goto Err;
- if(!dir.flags & VtEntryActive) {
- vtSetError(ENoDir);
- goto Err;
- }
- sp = dir.score;
- break;
- }
-
- if(sp == nil)
- memmove(score, vtZeroScore, VtScoreSize);
- else
- memmove(score, sp, VtScoreSize);
-
- vtUnlock(u->lk);
- return !scoreIsLocal(score);
-Err:
- vtUnlock(u->lk);
- return 0;
-}
-
-Lump *
-lumpWalk(Lump *u, int offset, int type, int size, int readOnly, int lock)
-{
- Lump *v, *vv;
- Cache *c;
- uchar score[VtScoreSize], *sp;
- VtRoot root;
- VtEntry dir;
- int split, isdir;
-
- c = u->c;
- vtLock(u->lk);
-
-Again:
- v = nil;
- vv = nil;
-
- isdir = u->dir;
- switch(u->type) {
- default:
- vtSetError("bad type");
- goto Err;
- case VtPointerType0:
- case VtPointerType1:
- case VtPointerType2:
- case VtPointerType3:
- case VtPointerType4:
- case VtPointerType5:
- case VtPointerType6:
- if((offset+1)*VtScoreSize > u->asize)
- sp = nil;
- else
- sp = u->data + offset*VtScoreSize;
- break;
- case VtRootType:
- if(u->asize < VtRootSize) {
- vtSetError("runt root block");
- goto Err;
- }
- if(!vtRootUnpack(&root, u->data))
- goto Err;
- sp = root.score;
- break;
- case VtDirType:
- if((offset+1)*VtEntrySize > u->asize) {
- vtSetError(ENoDir);
- goto Err;
- }
- if(!vtEntryUnpack(&dir, u->data, offset))
- goto Err;
- if(!(dir.flags & VtEntryActive)) {
- vtSetError(ENoDir);
- goto Err;
- }
- isdir = (dir.flags & VtEntryDir) != 0;
-// sp = dir.score;
- sp = u->data + offset*VtEntrySize + 20;
- break;
- }
-
- if(sp == nil)
- memmove(score, vtZeroScore, VtScoreSize);
- else
- memmove(score, sp, VtScoreSize);
-
- vtUnlock(u->lk);
-
-
-if(0)fprint(2, "lumpWalk: %V:%s %d:%d-> %V:%d\n", u->score, lumpState(u->state), u->type, offset, score, type);
- v = cacheGetLump(c, score, type, size);
- if(v == nil)
- return nil;
-
- split = 1;
- if(readOnly)
- split = 0;
-
- switch(v->state) {
- default:
- assert(0);
- case LumpFree:
-fprint(2, "block is free %V!\n", v->score);
- vtSetError("phase error");
- goto Err2;
- case LumpActive:
- if(v->gen < u->gen) {
-print("LumpActive gen\n");
- lumpSetState(v, LumpSnap);
- v->gen = u->gen;
- } else
- split = 0;
- break;
- case LumpSnap:
- case LumpVenti:
- break;
- }
-
- /* easy case */
- if(!split) {
- if(!lock)
- vtUnlock(v->lk);
- return v;
- }
-
- if(sp == nil) {
- vtSetError("bad offset");
- goto Err2;
- }
-
- vv = cacheAllocLump(c, v->type, size, isdir);
- /* vv is locked */
- vv->gen = u->gen;
- memmove(vv->data, v->data, v->asize);
-if(0)fprint(2, "split %V into %V\n", v->score, vv->score);
-
- lumpDecRef(v, 1);
- v = nil;
-
- vtLock(u->lk);
- if(u->state != LumpActive) {
- vtSetError("bad parent state: can not happen");
- goto Err;
- }
-
- /* check that nothing changed underfoot */
- if(memcmp(sp, score, VtScoreSize) != 0) {
- lumpDecRef(vv, 1);
-fprint(2, "lumpWalk: parent changed under foot\n");
- goto Again;
- }
-
- /* XXX - hold Active blocks up - will go eventually */
- lumpIncRef(vv);
-
- /* change the parent */
- memmove(sp, vv->score, VtScoreSize);
-
- vtUnlock(u->lk);
-
- if(!lock)
- vtUnlock(vv->lk);
- return vv;
-Err:
- vtUnlock(u->lk);
- lumpDecRef(v, 0);
- lumpDecRef(vv, 1);
- return nil;
-Err2:
- lumpDecRef(v, 1);
- return nil;
-
-}
-
-void
-lumpFreeEntry(Lump *u, int entry)
-{
- uchar score[VtScoreSize];
- int type;
- ulong gen;
- VtEntry dir;
- Cache *c;
-
- c = u->c;
- vtLock(u->lk);
- if(u->state == LumpVenti)
- goto Exit;
-
- switch(u->type) {
- default:
- fprint(2, "freeing bad lump type: %d\n", u->type);
- return;
- case VtPointerType0:
- if((entry+1)*VtScoreSize > u->asize)
- goto Exit;
- memmove(score, u->data + entry*VtScoreSize, VtScoreSize);
- memmove(u->data + entry*VtScoreSize, vtZeroScore, VtScoreSize);
- type = u->dir?VtDirType:VtDataType;
- break;
- case VtPointerType1:
- case VtPointerType2:
- case VtPointerType3:
- case VtPointerType4:
- case VtPointerType5:
- case VtPointerType6:
- if((entry+1)*VtScoreSize > u->asize)
- goto Exit;
- memmove(score, u->data + entry*VtScoreSize, VtScoreSize);
- memmove(u->data + entry*VtScoreSize, vtZeroScore, VtScoreSize);
- type = u->type-1;
- break;
- case VtDirType:
- if((entry+1)*VtEntrySize > u->asize)
- goto Exit;
- if(!vtEntryUnpack(&dir, u->data, entry))
- goto Exit;
- if(!dir.flags & VtEntryActive)
- goto Exit;
- gen = dir.gen;
- if(gen != ~0)
- gen++;
- if(dir.depth == 0)
- type = (dir.flags&VtEntryDir)?VtDirType:VtDataType;
- else
- type = VtPointerType0 + dir.depth - 1;
- memmove(score, dir.score, VtScoreSize);
- memset(&dir, 0, sizeof(dir));
- dir.gen = gen;
- vtEntryPack(&dir, u->data, entry);
- break;
- case VtDataType:
- type = VtErrType;
- break;
- }
- vtUnlock(u->lk);
- if(type == VtErrType || !scoreIsLocal(score))
- return;
-
- u = cacheGetLump(c, score, type, c->size);
- if(u == nil)
- return;
- lumpDecRef(u, 1);
- /* XXX remove extra reference */
- lumpDecRef(u, 0);
- return;
-Exit:
- vtUnlock(u->lk);
- return;
-
-}
-
-void
-lumpCleanup(Lump *u)
-{
- int i, n;
-
- switch(u->type) {
- default:
- return;
- case VtPointerType0:
- case VtPointerType1:
- case VtPointerType2:
- case VtPointerType3:
- case VtPointerType4:
- case VtPointerType5:
- case VtPointerType6:
- n = u->asize/VtScoreSize;
- break;
- case VtDirType:
- n = u->asize/VtEntrySize;
- break;
- }
-
- for(i=0; i<n; i++)
- lumpFreeEntry(u, i);
-}
-
-
-void
-lumpDecRef(Lump *b, int unlock)
-{
- int i;
- Cache *c;
-
- if(b == nil)
- return;
-
- if(unlock)
- vtUnlock(b->lk);
-
- c = b->c;
- vtLock(c->lk);
- if(--b->ref > 0) {
- vtUnlock(c->lk);
- return;
- }
- assert(b->ref == 0);
-
- switch(b->state) {
- default:
- fprint(2, "bad state: %s\n", lumpState(b->state));
- assert(0);
- case LumpActive:
- /* hack - but will do for now */
- b->ref++;
- vtUnlock(c->lk);
- lumpCleanup(b);
- vtLock(c->lk);
- b->ref--;
- lumpSetState(b, LumpFree);
- break;
- case LumpZombie:
- lumpSetState(b, LumpFree);
- break;
- case LumpFree:
- case LumpVenti:
- break;
- }
-
- /*
- * reinsert in the free heap
- */
- if(b->heap == BadHeap) {
- i = upHeap(c->nheap++, b);
- c->heap[i] = b;
- b->heap = i;
- }
-
- vtUnlock(c->lk);
-}
-
-Lump *
-lumpIncRef(Lump *b)
-{
- Cache *c;
-
- c = b->c;
-
- vtLock(c->lk);
- assert(b->ref > 0);
- b->ref++;
- vtUnlock(c->lk);
- return b;
-}
diff --git a/src/cmd/vac/dat.h b/src/cmd/vac/dat.h
index a468668d..ec15db4a 100644
--- a/src/cmd/vac/dat.h
+++ b/src/cmd/vac/dat.h
@@ -1,60 +1,27 @@
-typedef struct Source Source;
-typedef struct VacFile VacFile;
typedef struct MetaBlock MetaBlock;
typedef struct MetaEntry MetaEntry;
-typedef struct Lump Lump;
-typedef struct Cache Cache;
-typedef struct Super Super;
-enum {
- NilBlock = (~0UL),
+enum
+{
MaxBlock = (1UL<<31),
};
-
-struct VacFS {
- int ref;
-
- /* need a read write lock? */
-
- uchar score[VtScoreSize];
- VacFile *root;
-
- VtSession *z;
- int readOnly;
- int bsize; /* maximum block size */
- uvlong qid; /* next qid */
- Cache *cache;
+enum {
+ BytesPerEntry = 100, /* estimate of bytes per dir entries - determines number of index entries in the block */
+ FullPercentage = 80, /* don't allocate in block if more than this percentage full */
+ FlushSize = 200, /* number of blocks to flush */
+ DirtyPercentage = 50, /* maximum percentage of dirty blocks */
};
-struct Source {
- VtLock *lk;
-
- Cache *cache; /* immutable */
- int readOnly; /* immutable */
-
- Lump *lump; /* lump containing venti dir entry */
- ulong block; /* block number within parent: immutable */
- int entry; /* which entry in the block: immutable */
-
- /* most of a VtEntry, except the score */
- ulong gen; /* generation: immutable */
- int dir; /* dir flags: immutable */
- int depth; /* number of levels of pointer blocks */
- int psize; /* pointer block size: immutable */
- int dsize; /* data block size: immutable */
- uvlong size; /* size in bytes of file */
-
- int epb; /* dir entries per block = dize/VtEntrySize: immutable */
-};
-
-struct MetaEntry {
+struct MetaEntry
+{
uchar *p;
ushort size;
};
-struct MetaBlock {
+struct MetaBlock
+{
int maxsize; /* size of block */
int size; /* size used */
int free; /* free space within used size */
@@ -64,93 +31,13 @@ struct MetaBlock {
uchar *buf;
};
-/*
- * contains a one block buffer
- * to avoid problems of the block changing underfoot
- * and to enable an interface that supports unget.
- */
-struct VacDirEnum {
+struct VacDirEnum
+{
VacFile *file;
-
- ulong block; /* current block */
- MetaBlock mb; /* parsed version of block */
- int index; /* index in block */
-};
-
-/* Lump states */
-enum {
- LumpFree,
- LumpVenti, /* on venti server: score > 2^32: just a cached copy */
- LumpActive, /* active */
- LumpActiveRO, /* active: read only block */
- LumpActiveA, /* active: achrived */
- LumpSnap, /* snapshot: */
- LumpSnapRO, /* snapshot: read only */
- LumpSnapA, /* snapshot: achived */
- LumpZombie, /* block with no pointer to it: waiting to be freed */
-
- LumpMax
-};
-
-/*
- * Each lump has a state and generation
- * The following invariants are maintained
- * Each lump has no more than than one parent per generation
- * For Active*, no child has a parent of a greater generation
- * For Snap*, there is a snap parent of given generation and there are
- * no parents of greater gen - implies no children of a greater gen
- * For *RO, the lump is fixed - no change ca be made - all pointers
- * are valid venti addresses
- * For *A, the lump is on the venti server
- * There are no pointers to Zombie lumps
- *
- * Transitions
- * Archiver at generation g
- * Mutator at generation h
- *
- * Want to modify a lump
- * Venti: create new Active(h)
- * Active(x): x == h: do nothing
- * Acitve(x): x < h: change to Snap(h-1) + add Active(h)
- * ActiveRO(x): change to SnapRO(h-1) + add Active(h)
- * ActiveA(x): add Active(h)
- * Snap*(x): should not occur
- * Zombie(x): should not occur
- * Want to archive
- * Active(x): x != g: should never happen
- * Active(x): x == g fix children and free them: move to ActoveRO(g);
- * ActiveRO(x): x != g: should never happen
- * ActiveRO(x): x == g: wait until it hits ActiveA or SnapA
- * ActiveA(x): done
- * Active(x): x < g: should never happen
- * Snap(x): x >= g: fix children, freeing all SnapA(y) x == y;
- * SnapRO(x): wait until it hits SnapA
- *
- */
-
-
-struct Lump {
- int ref;
-
- Cache *c;
-
- VtLock *lk;
-
- int state;
- ulong gen;
-
- uchar *data;
- uchar score[VtScoreSize]; /* score of packet */
- uchar vscore[VtScoreSize]; /* venti score - when archived */
- u8int type; /* type of packet */
- int dir; /* part of a directory - extension of type */
- u16int asize; /* allocated size of block */
- Lump *next; /* doubly linked hash chains */
- Lump *prev;
- u32int heap; /* index in heap table */
- u32int used; /* last reference times */
- u32int used2;
-
- u32int addr; /* mutable block address */
+ u32int boff;
+ int i, n;
+ VacDir *buf;
};
+void _mbinit(MetaBlock*, u8int*, uint, uint);
+int _mbsearch(MetaBlock*, char*, int*, MetaEntry*);
diff --git a/src/cmd/vac/error.c b/src/cmd/vac/error.c
index 5c8ff29d..f28f9376 100644
--- a/src/cmd/vac/error.c
+++ b/src/cmd/vac/error.c
@@ -5,6 +5,8 @@
#include "error.h"
char ENoDir[] = "directory entry is not allocated";
+char ENoFile[] = "no such file or directory";
+char EBadPath[] = "bad path";
char EBadDir[] = "corrupted directory entry";
char EBadMeta[] = "corrupted meta data";
char ENotDir[] = "not a directory";
diff --git a/src/cmd/vac/error.h b/src/cmd/vac/error.h
index 742228cf..bbb97373 100644
--- a/src/cmd/vac/error.h
+++ b/src/cmd/vac/error.h
@@ -12,3 +12,5 @@ extern char ERemoved[];
extern char ENotEmpty[];
extern char EExists[];
extern char ERoot[];
+extern char ENoFile[];
+extern char EBadPath[];
diff --git a/src/cmd/vac/file.c b/src/cmd/vac/file.c
index 900422d2..cdcfd50a 100644
--- a/src/cmd/vac/file.c
+++ b/src/cmd/vac/file.c
@@ -8,382 +8,150 @@
* locking order is upwards. A thread can hold the lock for a VacFile
* and then acquire the lock of its parent
*/
+struct VacFile
+{
+ VacFs *fs; /* immutable */
-struct VacFile {
/* meta data for file: protected by the lk in the parent */
- int ref; /* holds this data structure up */
- VacFS *fs; /* immutable */
-
- int removed; /* file has been removed */
- int dirty; /* dir is dirty with respect to meta data in block */
- ulong block; /* block offset withing msource for this file's meta data */
-
- VacDir dir; /* meta data for this file */
-
- VacFile *up; /* parent file */
- VacFile *next; /* sibling */
-
- /* data for file */
- VtLock *lk; /* lock for source and msource */
- Source *source;
- Source *msource; /* for directories: meta data for children */
- VacFile *down; /* children */
+ int ref; /* holds this data structure up */
+
+ int partial; /* file was never really open */
+ int removed; /* file has been removed */
+ int dirty; /* dir is dirty with respect to meta data in block */
+ u32int boff; /* block offset within msource for this file's metadata */
+ VacDir dir; /* metadata for this file */
+ VacFile *up; /* parent file */
+ VacFile *next; /* sibling */
+
+ RWLock lk; /* lock for the following */
+ VtFile *source; /* actual data */
+ VtFile *msource; /* metadata for children in a directory */
+ VacFile *down; /* children */
+ int mode;
};
-static int vfMetaFlush(VacFile*);
-static ulong msAlloc(Source *ms, ulong, int n);
-
-static void
-vfRUnlock(VacFile *vf)
-{
- vtRUnlock(vf->lk);
-}
-
-
-static int
-vfRLock(VacFile *vf)
-{
- vtRLock(vf->lk);
- if(vf->source == nil) {
- vfRUnlock(vf);
- vtSetError(ERemoved);
- return 0;
- }
- return 1;
-}
-
-static void
-vfUnlock(VacFile *vf)
-{
- vtUnlock(vf->lk);
-}
-
-static int
-vfLock(VacFile *vf)
-{
- vtLock(vf->lk);
- if(vf->source == nil) {
- vfUnlock(vf);
- vtSetError(ERemoved);
- return 0;
- }
- return 1;
-}
-
-static void
-vfMetaLock(VacFile *vf)
-{
- assert(vf->up->msource != nil);
- vtLock(vf->up->lk);
-}
-
-static void
-vfMetaUnlock(VacFile *vf)
-{
- vtUnlock(vf->up->lk);
-}
-
-
-static void
-vfRAccess(VacFile* vf)
+static int filelock(VacFile*);
+static u32int filemetaalloc(VacFile*, VacDir*, u32int);
+static int filemetaflush2(VacFile*, char*);
+static void filemetalock(VacFile*);
+static void filemetaunlock(VacFile*);
+static void fileraccess(VacFile*);
+static int filerlock(VacFile*);
+static void filerunlock(VacFile*);
+static void fileunlock(VacFile*);
+static void filewaccess(VacFile*, char*);
+
+void mbinit(MetaBlock*, u8int*, uint, uint);
+int mbsearch(MetaBlock*, char*, int*, MetaEntry*);
+int mbresize(MetaBlock*, MetaEntry*, int);
+VacFile *vdlookup(VacFile*, char*);
+
+static VacFile*
+filealloc(VacFs *fs)
{
- vfMetaLock(vf);
- vf->dir.atime = time(0L);
- vf->dirty = 1;
- vfMetaUnlock(vf);
- vfMetaFlush(vf);
+ VacFile *f;
+
+ f = vtmallocz(sizeof(VacFile));
+ f->ref = 1;
+ f->fs = fs;
+ f->boff = NilBlock;
+ f->mode = fs->mode;
+ return f;
}
static void
-vfWAccess(VacFile* vf, char *mid)
-{
- vfMetaLock(vf);
- vf->dir.atime = vf->dir.mtime = time(0L);
- if(strcmp(vf->dir.mid, mid) != 0) {
- vtMemFree(vf->dir.mid);
- vf->dir.mid = vtStrDup(mid);
- }
- vf->dir.mcount++;
- vf->dirty = 1;
- vfMetaUnlock(vf);
- vfMetaFlush(vf);
-}
-
-void
-vdCleanup(VacDir *dir)
-{
- vtMemFree(dir->elem);
- dir->elem = nil;
- vtMemFree(dir->uid);
- dir->uid = nil;
- vtMemFree(dir->gid);
- dir->gid = nil;
- vtMemFree(dir->mid);
- dir->mid = nil;
-}
-
-void
-vdCopy(VacDir *dst, VacDir *src)
+filefree(VacFile *f)
{
- *dst = *src;
- dst->elem = vtStrDup(src->elem);
- dst->uid = vtStrDup(src->uid);
- dst->gid = vtStrDup(src->gid);
- dst->mid = vtStrDup(src->mid);
+ vtfileclose(f->source);
+ vtfileclose(f->msource);
+ vdcleanup(&f->dir);
+ memset(f, ~0, sizeof *f); /* paranoia */
+ vtfree(f);
}
-static int
-mbSearch(MetaBlock *mb, char *elem, int *ri, MetaEntry *me)
+/*
+ * the file is locked already
+ * f->msource is unlocked
+ */
+static VacFile*
+dirlookup(VacFile *f, char *elem)
{
int i;
- int b, t, x;
-
- /* binary search within block */
- b = 0;
- t = mb->nindex;
- while(b < t) {
- i = (b+t)>>1;
- if(!meUnpack(me, mb, i))
- return 0;
- if(mb->unbotch)
- x = meCmpNew(me, elem);
- else
- x = meCmp(me, elem);
-
- if(x == 0) {
- *ri = i;
- return 1;
- }
-
- if(x < 0)
- b = i+1;
- else /* x > 0 */
- t = i;
- }
-
- assert(b == t);
-
- *ri = b; /* b is the index to insert this entry */
- memset(me, 0, sizeof(*me));
-
- return 1;
-}
-
-static void
-mbInit(MetaBlock *mb, uchar *p, int n)
-{
- memset(mb, 0, sizeof(MetaBlock));
- mb->maxsize = n;
- mb->buf = p;
- mb->maxindex = n/100;
- mb->size = MetaHeaderSize + mb->maxindex*MetaIndexSize;
-}
-
-static int
-vfMetaFlush(VacFile *vf)
-{
- VacFile *vfp;
- Lump *u;
- MetaBlock mb;
- MetaEntry me, nme;
- uchar *p;
- int i, n, moved;
-
-//print("vfMetaFlush %s\n", vf->dir.elem);
-
- /* assume name has not changed for the moment */
-
- vfMetaLock(vf);
-
- vfp = vf->up;
- moved = 0;
-
- u = sourceGetLump(vfp->msource, vf->block, 0, 1);
- if(u == nil)
- goto Err;
-
- if(!mbUnpack(&mb, u->data, u->asize))
- goto Err;
- if(!mbSearch(&mb, vf->dir.elem, &i, &me) || me.p == nil)
- goto Err;
-
- nme = me;
- n = vdSize(&vf->dir);
-//print("old size %d new size %d\n", me.size, n);
- if(n <= nme.size) {
- nme.size = n;
- } else {
- /* try expand entry? */
- p = mbAlloc(&mb, n);
-//print("alloced %ld\n", p - mb.buf);
- if(p == nil) {
-assert(0);
- /* much more work */
- }
- nme.p = p;
- nme.size = n;
- }
-
- mbDelete(&mb, i, &me);
- memset(me.p, 0, me.size);
- if(!moved) {
- vdPack(&vf->dir, &nme);
- mbInsert(&mb, i, &nme);
- }
-
- mbPack(&mb);
- lumpDecRef(u, 1);
-
- vf->dirty = 0;
-
- vfMetaUnlock(vf);
- return 1;
-
-Err:
- lumpDecRef(u, 1);
- vfMetaUnlock(vf);
- return 0;
-}
-
-static VacFile *
-vfAlloc(VacFS *fs)
-{
- VacFile *vf;
-
- vf = vtMemAllocZ(sizeof(VacFile));
- vf->lk = vtLockAlloc();
- vf->ref = 1;
- vf->fs = fs;
- return vf;
-}
-
-static void
-vfFree(VacFile *vf)
-{
- sourceFree(vf->source);
- vtLockFree(vf->lk);
- sourceFree(vf->msource);
- vdCleanup(&vf->dir);
-
- vtMemFree(vf);
-}
-
-/* the file is locked already */
-static VacFile *
-dirLookup(VacFile *vf, char *elem)
-{
- int i, j, nb;
MetaBlock mb;
MetaEntry me;
- Lump *u;
- Source *meta;
- VacFile *nvf;
-
- meta = vf->msource;
- u = nil;
- nb = sourceGetNumBlocks(meta);
- for(i=0; i<nb; i++) {
- u = sourceGetLump(meta, i, 1, 1);
- if(u == nil)
- goto Err;
- if(!mbUnpack(&mb, u->data, u->asize))
+ VtBlock *b;
+ VtFile *meta;
+ VacFile *ff;
+ u32int bo, nb;
+
+ meta = f->msource;
+ b = nil;
+ if(vtfilelock(meta, -1) < 0)
+ return nil;
+ nb = (vtfilegetsize(meta)+meta->dsize-1)/meta->dsize;
+ for(bo=0; bo<nb; bo++){
+ b = vtfileblock(meta, bo, VtOREAD);
+ if(b == nil)
goto Err;
- if(!mbSearch(&mb, elem, &j, &me))
+ if(mbunpack(&mb, b->data, meta->dsize) < 0)
goto Err;
- if(me.p != nil) {
- nvf = vfAlloc(vf->fs);
- if(!vdUnpack(&nvf->dir, &me)) {
- vfFree(nvf);
+ if(mbsearch(&mb, elem, &i, &me) < 0){
+ ff = filealloc(f->fs);
+ if(vdunpack(&ff->dir, &me) < 0){
+ filefree(ff);
goto Err;
}
- lumpDecRef(u, 1);
- nvf->block = i;
- return nvf;
+ vtfileunlock(meta);
+ vtblockput(b);
+ ff->boff = bo;
+ ff->mode = f->mode;
+ return ff;
}
-
- lumpDecRef(u, 1);
- u = nil;
+
+ vtblockput(b);
+ b = nil;
}
- vtSetError("file does not exist");
+ werrstr(ENoFile);
/* fall through */
Err:
- lumpDecRef(u, 1);
+ vtfileunlock(meta);
+ vtblockput(b);
return nil;
}
-VacFile *
-vfRoot(VacFS *fs, uchar *score)
+VacFile*
+_vacfileroot(VacFs *fs, VtFile *r)
{
- VtEntry e;
- Lump *u, *v;
- Source *r, *r0, *r1, *r2;
+ VtBlock *b;
+ VtFile *r0, *r1, *r2;
MetaBlock mb;
MetaEntry me;
VacFile *root, *mr;
+ b = nil;
root = nil;
mr = nil;
- r0 = nil;
r1 = nil;
r2 = nil;
- v = nil;
- r = nil;
- u = cacheGetLump(fs->cache, score, VtDirType, fs->bsize);
- if(u == nil)
+ if(vtfilelock(r, -1) < 0)
+ return nil;
+ r0 = vtfileopen(r, 0, fs->mode);
+ if(r0 == nil)
goto Err;
- if(!fs->readOnly) {
- v = cacheAllocLump(fs->cache, VtDirType, fs->bsize, 1);
- if(v == nil) {
- vtUnlock(u->lk);
- goto Err;
- }
- v->gen = u->gen;
- v->asize = u->asize;
- v->state = LumpActive;
- memmove(v->data, u->data, v->asize);
- lumpDecRef(u, 1);
- u = v;
- v = nil;
- }
- vtUnlock(u->lk);
- vtEntryUnpack(&e, u->data, 2);
- if(e.flags == 0){ /* just one entry */
- r = sourceAlloc(fs->cache, u, 0, 0, fs->readOnly);
- if(r == nil)
- goto Err;
- r0 = sourceOpen(r, 0, fs->readOnly);
- if(r0 == nil)
- goto Err;
- r1 = sourceOpen(r, 1, fs->readOnly);
- if(r1 == nil)
- goto Err;
- r2 = sourceOpen(r, 2, fs->readOnly);
- if(r2 == nil)
- goto Err;
- sourceFree(r);
- r = nil;
- }else{
- r0 = sourceAlloc(fs->cache, u, 0, 0, fs->readOnly);
- if(r0 == nil)
- goto Err;
- r1 = sourceAlloc(fs->cache, u, 0, 1, fs->readOnly);
- if(r1 == nil)
- goto Err;
- r2 = sourceAlloc(fs->cache, u, 0, 2, fs->readOnly);
- if(r2 == nil)
- goto Err;
- }
- lumpDecRef(u, 0);
- u = sourceGetLump(r2, 0, 1, 0);
- if(u == nil)
+ r1 = vtfileopen(r, 1, fs->mode);
+ if(r1 == nil)
+ goto Err;
+ r2 = vtfileopen(r, 2, fs->mode);
+ if(r2 == nil)
goto Err;
- mr = vfAlloc(fs);
+ mr = filealloc(fs);
mr->msource = r2;
r2 = nil;
- root = vfAlloc(fs);
+ root = filealloc(fs);
+ root->boff = 0;
root->up = mr;
root->source = r0;
r0 = nil;
@@ -392,280 +160,404 @@ vfRoot(VacFS *fs, uchar *score)
mr->down = root;
- if(!mbUnpack(&mb, u->data, u->asize))
+ if(vtfilelock(mr->msource, -1) < 0)
goto Err;
-
- if(!meUnpack(&me, &mb, 0))
+ b = vtfileblock(mr->msource, 0, VtOREAD);
+ vtfileunlock(mr->msource);
+ if(b == nil)
goto Err;
- if(!vdUnpack(&root->dir, &me))
+
+ if(mbunpack(&mb, b->data, mr->msource->dsize) < 0)
goto Err;
- vfRAccess(root);
- lumpDecRef(u, 0);
- sourceFree(r2);
+ meunpack(&me, &mb, 0);
+ if(vdunpack(&root->dir, &me) < 0)
+ goto Err;
+ vtblockput(b);
+ vtfileunlock(r);
+ fileraccess(root);
return root;
Err:
- lumpDecRef(u, 0);
- lumpDecRef(v, 0);
+ vtblockput(b);
if(r0)
- sourceFree(r0);
+ vtfileclose(r0);
if(r1)
- sourceFree(r1);
+ vtfileclose(r1);
if(r2)
- sourceFree(r2);
- if(r)
- sourceFree(r);
+ vtfileclose(r2);
if(mr)
- vfFree(mr);
+ filefree(mr);
if(root)
- vfFree(root);
+ filefree(root);
+ vtfileunlock(r);
+
+ return nil;
+}
+static VtFile *
+fileopensource(VacFile *f, u32int offset, u32int gen, int dir, uint mode)
+{
+ VtFile *r;
+
+ if(vtfilelock(f->source, mode) < 0)
+ return nil;
+ r = vtfileopen(f->source, offset, mode);
+ vtfileunlock(f->source);
+ if(r == nil)
+ return nil;
+ if(r->gen != gen){
+ werrstr(ERemoved);
+ goto Err;
+ }
+ if(r->dir != dir && r->mode != -1){
+fprint(2, "fileopensource: dir mismatch %d %d\n", r->dir, dir);
+ werrstr(EBadMeta);
+ goto Err;
+ }
+ return r;
+Err:
+ vtfileclose(r);
return nil;
}
-VacFile *
-vfWalk(VacFile *vf, char *elem)
+VacFile*
+_filewalk(VacFile *f, char *elem, int partial)
{
- VacFile *nvf;
+ VacFile *ff;
- vfRAccess(vf);
+ fileraccess(f);
- if(elem[0] == 0) {
- vtSetError("illegal path element");
+ if(elem[0] == 0){
+ werrstr(EBadPath);
return nil;
}
- if(!vfIsDir(vf)) {
- vtSetError("not a directory");
+
+ if(!vacfileisdir(f)){
+ werrstr(ENotDir);
return nil;
}
- if(strcmp(elem, ".") == 0) {
- return vfIncRef(vf);
+ if(strcmp(elem, ".") == 0){
+ return vacfileincref(f);
}
- if(strcmp(elem, "..") == 0) {
- if(vfIsRoot(vf))
- return vfIncRef(vf);
- return vfIncRef(vf->up);
+ if(strcmp(elem, "..") == 0){
+ if(vacfileisroot(f))
+ return vacfileincref(f);
+ return vacfileincref(f->up);
}
- if(!vfLock(vf))
+ if(filelock(f) < 0)
return nil;
- for(nvf = vf->down; nvf; nvf=nvf->next) {
- if(strcmp(elem, nvf->dir.elem) == 0 && !nvf->removed) {
- nvf->ref++;
+ for(ff = f->down; ff; ff=ff->next){
+ if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
+ ff->ref++;
goto Exit;
}
}
- nvf = dirLookup(vf, elem);
- if(nvf == nil)
- goto Err;
- nvf->source = sourceOpen(vf->source, nvf->dir.entry, vf->fs->readOnly);
- if(nvf->source == nil)
+ ff = dirlookup(f, elem);
+ if(ff == nil)
goto Err;
- if(nvf->dir.mode & ModeDir) {
- nvf->msource = sourceOpen(vf->source, nvf->dir.mentry, vf->fs->readOnly);
- if(nvf->msource == nil)
+
+ if(ff->dir.mode & ModeSnapshot)
+ ff->mode = VtOREAD;
+
+ if(partial){
+ /*
+ * Do nothing. We're opening this file only so we can clri it.
+ * Usually the sources can't be opened, hence we won't even bother.
+ * Be VERY careful with the returned file. If you hand it to a routine
+ * expecting ff->source and/or ff->msource to be non-nil, we're
+ * likely to dereference nil. FileClri should be the only routine
+ * setting partial.
+ */
+ ff->partial = 1;
+ }else if(ff->dir.mode & ModeDir){
+ ff->source = fileopensource(f, ff->dir.entry, ff->dir.gen, 1, ff->mode);
+ ff->msource = fileopensource(f, ff->dir.mentry, ff->dir.mgen, 0, ff->mode);
+ if(ff->source == nil || ff->msource == nil)
+ goto Err;
+ }else{
+ ff->source = fileopensource(f, ff->dir.entry, ff->dir.gen, 0, ff->mode);
+ if(ff->source == nil)
goto Err;
}
/* link in and up parent ref count */
- nvf->next = vf->down;
- vf->down = nvf;
- nvf->up = vf;
- vfIncRef(vf);
+ ff->next = f->down;
+ f->down = ff;
+ ff->up = f;
+ vacfileincref(f);
Exit:
- vfUnlock(vf);
- return nvf;
+ fileunlock(f);
+ return ff;
Err:
- vfUnlock(vf);
- if(nvf != nil)
- vfFree(nvf);
+ fileunlock(f);
+ if(ff != nil)
+ vacfiledecref(ff);
return nil;
}
-VacFile *
-vfOpen(VacFS *fs, char *path)
+VacFile*
+vacfilewalk(VacFile *f, char *elem)
{
- VacFile *vf, *nvf;
- char *p, elem[VtMaxStringSize];
+ return _filewalk(f, elem, 0);
+}
+
+VacFile*
+_fileopen(VacFs *fs, char *path, int partial)
+{
+ VacFile *f, *ff;
+ char *p, elem[VtMaxStringSize], *opath;
int n;
- vf = fs->root;
- vfIncRef(vf);
- while(*path != 0) {
+ f = fs->root;
+ vacfileincref(f);
+ opath = path;
+ while(*path != 0){
for(p = path; *p && *p != '/'; p++)
;
n = p - path;
- if(n > 0) {
- if(n > VtMaxStringSize) {
- vtSetError("path element too long");
+ if(n > 0){
+ if(n > VtMaxStringSize){
+ werrstr("%s: element too long", EBadPath);
goto Err;
}
memmove(elem, path, n);
elem[n] = 0;
- nvf = vfWalk(vf, elem);
- if(nvf == nil)
+ ff = _filewalk(f, elem, partial && *p=='\0');
+ if(ff == nil){
+ werrstr("%.*s: %R", utfnlen(opath, p-opath), opath);
goto Err;
- vfDecRef(vf);
- vf = nvf;
+ }
+ vacfiledecref(f);
+ f = ff;
}
if(*p == '/')
p++;
path = p;
}
- return vf;
+ return f;
Err:
- vfDecRef(vf);
+ vacfiledecref(f);
return nil;
}
-VacFile *
-vfCreate(VacFile *vf, char *elem, ulong mode, char *user)
+VacFile*
+vacfileopen(VacFs *fs, char *path)
{
- VacFile *nvf;
+ return _fileopen(fs, path, 0);
+}
+
+#if 0
+static void
+filesettmp(VacFile *f, int istmp)
+{
+ int i;
+ VtEntry e;
+ VtFile *r;
+
+ for(i=0; i<2; i++){
+ if(i==0)
+ r = f->source;
+ else
+ r = f->msource;
+ if(r == nil)
+ continue;
+ if(vtfilegetentry(r, &e) < 0){
+ fprint(2, "vtfilegetentry failed (cannot happen): %r\n");
+ continue;
+ }
+ if(istmp)
+ e.flags |= VtEntryNoArchive;
+ else
+ e.flags &= ~VtEntryNoArchive;
+ if(vtfilesetentry(r, &e) < 0){
+ fprint(2, "vtfilesetentry failed (cannot happen): %r\n");
+ continue;
+ }
+ }
+}
+#endif
+
+VacFile*
+vacfilecreate(VacFile *f, char *elem, ulong mode, char *uid)
+{
+ VacFile *ff;
VacDir *dir;
- int n, i;
- uchar *p;
- Source *pr, *r, *mr;
+ VtFile *pr, *r, *mr;
int isdir;
- MetaBlock mb;
- MetaEntry me;
- Lump *u;
- if(!vfLock(vf))
+ if(filelock(f) < 0)
return nil;
r = nil;
mr = nil;
- u = nil;
-
- for(nvf = vf->down; nvf; nvf=nvf->next) {
- if(strcmp(elem, nvf->dir.elem) == 0 && !nvf->removed) {
- nvf = nil;
- vtSetError(EExists);
- goto Err;
+ for(ff = f->down; ff; ff=ff->next){
+ if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
+ ff = nil;
+ werrstr(EExists);
+ goto Err1;
}
}
- nvf = dirLookup(vf, elem);
- if(nvf != nil) {
- vtSetError(EExists);
- goto Err;
+ ff = dirlookup(f, elem);
+ if(ff != nil){
+ werrstr(EExists);
+ goto Err1;
+ }
+
+ pr = f->source;
+ if(pr->mode != VtORDWR){
+ werrstr(EReadOnly);
+ goto Err1;
}
- nvf = vfAlloc(vf->fs);
+ if(vtfilelock2(f->source, f->msource, -1) < 0)
+ goto Err1;
+
+ ff = filealloc(f->fs);
isdir = mode & ModeDir;
- pr = vf->source;
- r = sourceCreate(pr, pr->psize, pr->dsize, isdir, 0);
+ r = vtfilecreate(pr, pr->dsize, isdir, 0);
if(r == nil)
goto Err;
- if(isdir) {
- mr = sourceCreate(pr, pr->psize, pr->dsize, 0, r->block*pr->epb + r->entry);
+ if(isdir){
+ mr = vtfilecreate(pr, pr->dsize, 0, r->offset);
if(mr == nil)
goto Err;
}
-
- dir = &nvf->dir;
- dir->elem = vtStrDup(elem);
- dir->entry = r->block*pr->epb + r->entry;
+
+ dir = &ff->dir;
+ dir->elem = vtstrdup(elem);
+ dir->entry = r->offset;
dir->gen = r->gen;
- if(isdir) {
- dir->mentry = mr->block*pr->epb + mr->entry;
+ if(isdir){
+ dir->mentry = mr->offset;
dir->mgen = mr->gen;
}
dir->size = 0;
- dir->qid = vf->fs->qid++;
- dir->uid = vtStrDup(user);
- dir->gid = vtStrDup(vf->dir.gid);
- dir->mid = vtStrDup(user);
+ if(_vacfsnextqid(f->fs, &dir->qid) < 0)
+ goto Err;
+ dir->uid = vtstrdup(uid);
+ dir->gid = vtstrdup(f->dir.gid);
+ dir->mid = vtstrdup(uid);
dir->mtime = time(0L);
dir->mcount = 0;
dir->ctime = dir->mtime;
dir->atime = dir->mtime;
dir->mode = mode;
- n = vdSize(dir);
- nvf->block = msAlloc(vf->msource, 0, n);
- if(nvf->block == NilBlock)
- goto Err;
- u = sourceGetLump(vf->msource, nvf->block, 0, 1);
- if(u == nil)
- goto Err;
- if(!mbUnpack(&mb, u->data, u->asize))
+ ff->boff = filemetaalloc(f, dir, 0);
+ if(ff->boff == NilBlock)
goto Err;
- p = mbAlloc(&mb, n);
- if(p == nil)
- goto Err;
-
- if(!mbSearch(&mb, elem, &i, &me))
- goto Err;
- assert(me.p == nil);
- me.p = p;
- me.size = n;
- vdPack(dir, &me);
- mbInsert(&mb, i, &me);
- mbPack(&mb);
- lumpDecRef(u, 1);
+ vtfileunlock(f->source);
+ vtfileunlock(f->msource);
- nvf->source = r;
- nvf->msource = mr;
+ ff->source = r;
+ ff->msource = mr;
+
+#if 0
+ if(mode&ModeTemporary){
+ if(vtfilelock2(r, mr, -1) < 0)
+ goto Err1;
+ filesettmp(ff, 1);
+ vtfileunlock(r);
+ if(mr)
+ vtfileunlock(mr);
+ }
+#endif
+
+ /* committed */
/* link in and up parent ref count */
- nvf->next = vf->down;
- vf->down = nvf;
- nvf->up = vf;
- vfIncRef(vf);
+ ff->next = f->down;
+ f->down = ff;
+ ff->up = f;
+ vacfileincref(f);
- vfWAccess(vf, user);
+ filewaccess(f, uid);
- vfUnlock(vf);
- return nvf;
+ fileunlock(f);
+ return ff;
Err:
- lumpDecRef(u, 1);
- if(r)
- sourceRemove(r);
- if(mr)
- sourceRemove(mr);
- if(nvf)
- vfFree(nvf);
- vfUnlock(vf);
- return 0;
+ vtfileunlock(f->source);
+ vtfileunlock(f->msource);
+Err1:
+ if(r){
+ vtfilelock(r, -1);
+ vtfileremove(r);
+ }
+ if(mr){
+ vtfilelock(mr, -1);
+ vtfileremove(mr);
+ }
+ if(ff)
+ vacfiledecref(ff);
+ fileunlock(f);
+ return nil;
}
+int
+vacfileblockscore(VacFile *f, u32int bn, u8int *score)
+{
+ VtFile *s;
+ uvlong size;
+ int dsize, ret;
+
+ ret = -1;
+ if(filerlock(f) < 0)
+ return -1;
+ fileraccess(f);
+ if(vtfilelock(f->source, VtOREAD) < 0)
+ goto out;
+
+ s = f->source;
+ dsize = s->dsize;
+ size = vtfilegetsize(s);
+ if((uvlong)bn*dsize >= size)
+ goto out;
+ ret = vtfileblockscore(f->source, bn, score);
+
+out:
+ vtfileunlock(f->source);
+ filerunlock(f);
+ return ret;
+}
int
-vfRead(VacFile *vf, void *buf, int cnt, vlong offset)
+vacfileread(VacFile *f, void *buf, int cnt, vlong offset)
{
- Source *s;
+ VtFile *s;
uvlong size;
- ulong bn;
+ u32int bn;
int off, dsize, n, nn;
- Lump *u;
- uchar *b;
+ VtBlock *b;
+ uchar *p;
-if(0)fprint(2, "vfRead: %s %d, %lld\n", vf->dir.elem, cnt, offset);
+if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset);
- if(!vfRLock(vf))
+ if(filerlock(f) < 0)
return -1;
- s = vf->source;
+ if(offset < 0){
+ werrstr(EBadOffset);
+ goto Err1;
+ }
- dsize = s->dsize;
- size = sourceGetSize(s);
+ fileraccess(f);
- if(offset < 0) {
- vtSetError(EBadOffset);
- goto Err;
- }
+ if(vtfilelock(f->source, VtOREAD) < 0)
+ goto Err1;
- vfRAccess(vf);
+ s = f->source;
+ dsize = s->dsize;
+ size = vtfilegetsize(s);
if(offset >= size)
offset = size;
@@ -674,541 +566,1269 @@ if(0)fprint(2, "vfRead: %s %d, %lld\n", vf->dir.elem, cnt, offset);
cnt = size-offset;
bn = offset/dsize;
off = offset%dsize;
- b = buf;
- while(cnt > 0) {
- u = sourceGetLump(s, bn, 1, 0);
- if(u == nil)
- goto Err;
- if(u->asize <= off) {
- lumpDecRef(u, 0);
+ p = buf;
+ while(cnt > 0){
+ b = vtfileblock(s, bn, OREAD);
+ if(b == nil)
goto Err;
- }
n = cnt;
if(n > dsize-off)
n = dsize-off;
- nn = u->asize-off;
+ nn = dsize-off;
if(nn > n)
nn = n;
- memmove(b, u->data+off, nn);
- memset(b+nn, 0, n-nn);
+ memmove(p, b->data+off, nn);
+ memset(p+nn, 0, nn-n);
off = 0;
bn++;
cnt -= n;
- b += n;
- lumpDecRef(u, 0);
+ p += n;
+ vtblockput(b);
}
- vfRUnlock(vf);
- return b-(uchar*)buf;
+ vtfileunlock(s);
+ filerunlock(f);
+ return p-(uchar*)buf;
+
Err:
- vfRUnlock(vf);
+ vtfileunlock(s);
+Err1:
+ filerunlock(f);
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)
+{
+ int r;
+
+ if(filelock(f) < 0)
+ return -1;
+ r = 0;
+ 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;
+ r = vtfilesetsize(f->source, size);
+ vtfileunlock(f->source);
+Err:
+ fileunlock(f);
+ return r;
+}
+
int
-vfWrite(VacFile *vf, void *buf, int cnt, vlong offset, char *user)
+filewrite(VacFile *f, void *buf, int cnt, vlong offset, char *uid)
{
- Source *s;
+ VtFile *s;
ulong bn;
int off, dsize, n;
- Lump *u;
- uchar *b;
+ VtBlock *b;
+ uchar *p;
+ vlong eof;
- USED(user);
+if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset);
- if(!vfLock(vf))
+ if(filelock(f) < 0)
return -1;
- if(vf->fs->readOnly) {
- vtSetError(EReadOnly);
+ s = nil;
+ if(f->dir.mode & ModeDir){
+ werrstr(ENotFile);
goto Err;
}
- if(vf->dir.mode & ModeDir) {
- vtSetError(ENotFile);
+ if(f->source->mode != VtORDWR){
+ werrstr(EReadOnly);
goto Err;
}
-if(0)fprint(2, "vfWrite: %s %d, %lld\n", vf->dir.elem, cnt, offset);
-
- s = vf->source;
- dsize = s->dsize;
-
- if(offset < 0) {
- vtSetError(EBadOffset);
+ if(offset < 0){
+ werrstr(EBadOffset);
goto Err;
}
- vfWAccess(vf, user);
+ filewaccess(f, uid);
+
+ if(vtfilelock(f->source, -1) < 0)
+ goto Err;
+ s = f->source;
+ dsize = s->dsize;
+ eof = vtfilegetsize(s);
+ if(f->dir.mode & ModeAppend)
+ offset = eof;
bn = offset/dsize;
off = offset%dsize;
- b = buf;
- while(cnt > 0) {
+ p = buf;
+ while(cnt > 0){
n = cnt;
if(n > dsize-off)
n = dsize-off;
- if(!sourceSetDepth(s, offset+n))
- goto Err;
- u = sourceGetLump(s, bn, 0, 0);
- if(u == nil)
- goto Err;
- if(u->asize < dsize) {
- vtSetError("runt block");
- lumpDecRef(u, 0);
+ b = vtfileblock(s, bn, n<dsize?VtORDWR:VtOWRITE);
+ if(b == nil){
+ if(offset > eof)
+ vtfilesetsize(s, offset);
goto Err;
}
- memmove(u->data+off, b, n);
+ memmove(b->data+off, p, n);
off = 0;
cnt -= n;
- b += n;
+ p += n;
offset += n;
bn++;
- lumpDecRef(u, 0);
- if(!sourceSetSize(s, offset))
- goto Err;
+ vtblockdirty(b);
+ vtblockput(b);
}
- vfLock(vf);
- return b-(uchar*)buf;
+ if(offset > eof && vtfilesetsize(s, offset) < 0)
+ goto Err;
+ vtfileunlock(s);
+ fileunlock(f);
+ return p-(uchar*)buf;
Err:
- vfLock(vf);
+ if(s)
+ vtfileunlock(s);
+ fileunlock(f);
return -1;
}
int
-vfGetDir(VacFile *vf, VacDir *dir)
+vacfilegetdir(VacFile *f, VacDir *dir)
{
- if(!vfRLock(vf))
- return 0;
+ if(filerlock(f) < 0)
+ return -1;
- vfMetaLock(vf);
- vdCopy(dir, &vf->dir);
- vfMetaUnlock(vf);
+ filemetalock(f);
+ vdcopy(dir, &f->dir);
+ filemetaunlock(f);
- if(!vfIsDir(vf))
- dir->size = sourceGetSize(vf->source);
- vfRUnlock(vf);
+ if(vacfileisdir(f) < 0){
+ if(vtfilelock(f->source, VtOREAD) < 0){
+ filerunlock(f);
+ return -1;
+ }
+ dir->size = vtfilegetsize(f->source);
+ vtfileunlock(f->source);
+ }
+ filerunlock(f);
- return 1;
+ return 0;
+}
+
+int
+vacfiletruncate(VacFile *f, char *uid)
+{
+ if(vacfileisdir(f)){
+ werrstr(ENotFile);
+ return -1;
+ }
+
+ if(filelock(f) < 0)
+ return -1;
+
+ if(f->source->mode != VtORDWR){
+ werrstr(EReadOnly);
+ fileunlock(f);
+ return -1;
+ }
+ if(vtfilelock(f->source, -1) < 0){
+ fileunlock(f);
+ return -1;
+ }
+ if(vtfiletruncate(f->source) < 0){
+ vtfileunlock(f->source);
+ fileunlock(f);
+ return -1;
+ }
+ vtfileunlock(f->source);
+ fileunlock(f);
+
+ filewaccess(f, uid);
+
+ return 0;
+}
+
+int
+vacfilesetdir(VacFile *f, VacDir *dir, char *uid)
+{
+ VacFile *ff;
+ char *oelem;
+ u32int mask;
+ u64int size;
+
+ /* can not set permissions for the root */
+ if(vacfileisroot(f)){
+ werrstr(ERoot);
+ return -1;
+ }
+
+ if(filelock(f) < 0)
+ return -1;
+
+ if(f->source->mode != VtORDWR){
+ werrstr(EReadOnly);
+ fileunlock(f);
+ return -1;
+ }
+
+ filemetalock(f);
+
+ /* check new name does not already exist */
+ if(strcmp(f->dir.elem, dir->elem) != 0){
+ for(ff = f->up->down; ff; ff=ff->next){
+ if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){
+ werrstr(EExists);
+ goto Err;
+ }
+ }
+
+ ff = dirlookup(f->up, dir->elem);
+ if(ff != nil){
+ vacfiledecref(ff);
+ werrstr(EExists);
+ goto Err;
+ }
+ }
+
+ if(vtfilelock2(f->source, f->msource, -1) < 0)
+ goto Err;
+ if(!vacfileisdir(f)){
+ size = vtfilegetsize(f->source);
+ if(size != dir->size){
+ if(vtfilesetsize(f->source, dir->size) < 0){
+ vtfileunlock(f->source);
+ if(f->msource)
+ vtfileunlock(f->msource);
+ goto Err;
+ }
+ /* commited to changing it now */
+ }
+ }
+ /* commited to changing it now */
+#if 0
+ if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary))
+ filesettmp(f, dir->mode&ModeTemporary);
+#endif
+ vtfileunlock(f->source);
+ if(f->msource)
+ vtfileunlock(f->msource);
+
+ oelem = nil;
+ if(strcmp(f->dir.elem, dir->elem) != 0){
+ oelem = f->dir.elem;
+ f->dir.elem = vtstrdup(dir->elem);
+ }
+
+ if(strcmp(f->dir.uid, dir->uid) != 0){
+ vtfree(f->dir.uid);
+ f->dir.uid = vtstrdup(dir->uid);
+ }
+
+ if(strcmp(f->dir.gid, dir->gid) != 0){
+ vtfree(f->dir.gid);
+ f->dir.gid = vtstrdup(dir->gid);
+ }
+
+ f->dir.mtime = dir->mtime;
+ f->dir.atime = dir->atime;
+
+//fprint(2, "mode %x %x ", f->dir.mode, dir->mode);
+ mask = ~(ModeDir|ModeSnapshot);
+ f->dir.mode &= ~mask;
+ f->dir.mode |= mask & dir->mode;
+ f->dirty = 1;
+//fprint(2, "->%x\n", f->dir.mode);
+
+ filemetaflush2(f, oelem);
+ vtfree(oelem);
+
+ filemetaunlock(f);
+ fileunlock(f);
+
+ filewaccess(f->up, uid);
+
+ return 0;
+Err:
+ filemetaunlock(f);
+ fileunlock(f);
+ return -1;
+}
+
+int
+vacfilesetqidspace(VacFile *f, u64int offset, u64int max)
+{
+ int ret;
+
+ if(filelock(f) < 0)
+ return -1;
+ filemetalock(f);
+ f->dir.qidspace = 1;
+ f->dir.qidoffset = offset;
+ f->dir.qidmax = max;
+ ret = filemetaflush2(f, nil);
+ filemetaunlock(f);
+ fileunlock(f);
+ return ret;
}
uvlong
-vfGetId(VacFile *vf)
+vacfilegetid(VacFile *f)
{
/* immutable */
- return vf->dir.qid;
+ return f->dir.qid;
}
ulong
-vfGetMcount(VacFile *vf)
+vacfilegetmcount(VacFile *f)
{
ulong mcount;
-
- vfMetaLock(vf);
- mcount = vf->dir.mcount;
- vfMetaUnlock(vf);
+
+ filemetalock(f);
+ mcount = f->dir.mcount;
+ filemetaunlock(f);
return mcount;
}
+ulong
+vacfilegetmode(VacFile *f)
+{
+ ulong mode;
+
+ filemetalock(f);
+ mode = f->dir.mode;
+ filemetaunlock(f);
+ return mode;
+}
int
-vfIsDir(VacFile *vf)
+vacfileisdir(VacFile *f)
{
/* immutable */
- return (vf->dir.mode & ModeDir) != 0;
+ return (f->dir.mode & ModeDir) != 0;
}
int
-vfIsRoot(VacFile *vf)
+vacfileisroot(VacFile *f)
{
- return vf == vf->fs->root;
+ return f == f->fs->root;
}
int
-vfGetSize(VacFile *vf, uvlong *size)
+vacfilegetsize(VacFile *f, uvlong *size)
{
- if(!vfRLock(vf))
+ if(filerlock(f) < 0)
return 0;
- *size = sourceGetSize(vf->source);
- vfRUnlock(vf);
+ if(vtfilelock(f->source, VtOREAD) < 0){
+ filerunlock(f);
+ return -1;
+ }
+ *size = vtfilegetsize(f->source);
+ vtfileunlock(f->source);
+ filerunlock(f);
- return 1;
+ return 0;
+}
+
+int
+vacfilegetvtentry(VacFile *f, VtEntry *e)
+{
+ if(filerlock(f) < 0)
+ return 0;
+ if(vtfilelock(f->source, VtOREAD) < 0){
+ filerunlock(f);
+ return -1;
+ }
+ vtfilegetentry(f->source, e);
+ vtfileunlock(f->source);
+ filerunlock(f);
+
+ return 0;
+}
+
+void
+vacfilemetaflush(VacFile *f, int rec)
+{
+ VacFile **kids, *p;
+ int nkids;
+ int i;
+
+ filemetalock(f);
+ filemetaflush2(f, nil);
+ filemetaunlock(f);
+
+ if(!rec || !vacfileisdir(f))
+ return;
+
+ if(filelock(f) < 0)
+ return;
+ nkids = 0;
+ for(p=f->down; p; p=p->next)
+ nkids++;
+ kids = vtmalloc(nkids*sizeof(VacFile*));
+ i = 0;
+ for(p=f->down; p; p=p->next){
+ kids[i++] = p;
+ p->ref++;
+ }
+ fileunlock(f);
+
+ for(i=0; i<nkids; i++){
+ vacfilemetaflush(kids[i], 1);
+ vacfiledecref(kids[i]);
+ }
+ vtfree(kids);
}
+/* assumes metaLock is held */
static int
-vfMetaRemove(VacFile *vf, char *user)
+filemetaflush2(VacFile *f, char *oelem)
{
- Lump *u;
+ VacFile *fp;
+ VtBlock *b, *bb;
MetaBlock mb;
- MetaEntry me;
- int i;
- VacFile *vfp;
+ MetaEntry me, me2;
+ int i, n;
+ u32int boff;
- vfp = vf->up;
+ if(!f->dirty)
+ return 0;
- vfWAccess(vfp, user);
+ if(oelem == nil)
+ oelem = f->dir.elem;
- vfMetaLock(vf);
+ fp = f->up;
- u = sourceGetLump(vfp->msource, vf->block, 0, 1);
- if(u == nil)
+ if(vtfilelock(fp->msource, -1) < 0)
+ return 0;
+ /* can happen if source is clri'ed out from under us */
+ if(f->boff == NilBlock)
+ goto Err1;
+ b = vtfileblock(fp->msource, f->boff, VtORDWR);
+ if(b == nil)
+ goto Err1;
+
+ if(mbunpack(&mb, b->data, fp->msource->dsize) < 0)
goto Err;
-
- if(!mbUnpack(&mb, u->data, u->asize))
+ if(mbsearch(&mb, oelem, &i, &me) < 0)
goto Err;
- if(!mbSearch(&mb, vf->dir.elem, &i, &me) || me.p == nil)
+
+ n = vdsize(&f->dir);
+if(0)fprint(2, "old size %d new size %d\n", me.size, n);
+
+ 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);
+ mbinsert(&mb, i, &me);
+ mbpack(&mb);
+ vtblockdirty(b);
+ vtblockput(b);
+ vtfileunlock(fp->msource);
+ f->dirty = 0;
+ return -1;
+ }
+
+ /*
+ * moving entry to another block
+ * it is feasible for the fs to crash leaving two copies
+ * of the directory entry. This is just too much work to
+ * fix. Given that entries are only allocated in a block that
+ * is less than PercentageFull, most modifications of meta data
+ * will fit within the block. i.e. this code should almost
+ * never be executed.
+ */
+ boff = filemetaalloc(fp, &f->dir, f->boff+1);
+ if(boff == NilBlock){
+ /* mbResize might have modified block */
+ mbpack(&mb);
+ vtblockdirty(b);
goto Err;
-print("deleting %d entry\n", i);
- mbDelete(&mb, i, &me);
- memset(me.p, 0, me.size);
- mbPack(&mb);
-
- lumpDecRef(u, 1);
-
- vf->removed = 1;
- vf->block = NilBlock;
-
- vfMetaUnlock(vf);
- return 1;
+ }
+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);
+ vtfileunlock(fp->msource);
+
+ f->dirty = 0;
-Err:
- lumpDecRef(u, 1);
- vfMetaUnlock(vf);
return 0;
+
+Err:
+ vtblockput(b);
+Err1:
+ vtfileunlock(fp->msource);
+ return -1;
}
+static int
+filemetaremove(VacFile *f, char *uid)
+{
+ VtBlock *b;
+ MetaBlock mb;
+ MetaEntry me;
+ int i;
+ VacFile *up;
+
+ b = nil;
+ up = f->up;
+ filewaccess(up, uid);
+ filemetalock(f);
+
+ if(vtfilelock(up->msource, VtORDWR) < 0)
+ goto Err;
+ b = vtfileblock(up->msource, f->boff, VtORDWR);
+ if(b == nil)
+ goto Err;
+
+ if(mbunpack(&mb, b->data, up->msource->dsize) < 0)
+ goto Err;
+ if(mbsearch(&mb, f->dir.elem, &i, &me) < 0)
+ goto Err;
+ mbdelete(&mb, i, &me);
+ mbpack(&mb);
+ vtfileunlock(up->msource);
+
+ vtblockdirty(b);
+ vtblockput(b);
+ f->removed = 1;
+ f->boff = NilBlock;
+ f->dirty = 0;
+
+ filemetaunlock(f);
+ return 0;
+
+Err:
+ vtfileunlock(up->msource);
+ vtblockput(b);
+ filemetaunlock(f);
+ return -1;
+}
+
+/* assume file is locked, assume f->msource is locked */
static int
-vfCheckEmpty(VacFile *vf)
+filecheckempty(VacFile *f)
{
- int i, n;
- Lump *u;
+ u32int i, n;
+ VtBlock *b;
MetaBlock mb;
- Source *r;
+ VtFile *r;
- r = vf->msource;
- n = sourceGetNumBlocks(r);
- for(i=0; i<n; i++) {
- u = sourceGetLump(r, i, 1, 1);
- if(u == nil)
+ r = f->msource;
+ n = (vtfilegetsize(r)+r->dsize-1)/r->dsize;
+ for(i=0; i<n; i++){
+ b = vtfileblock(r, i, VtORDWR);
+ if(b == nil)
goto Err;
- if(!mbUnpack(&mb, u->data, u->asize))
+ if(mbunpack(&mb, b->data, r->dsize) < 0)
goto Err;
- if(mb.nindex > 0) {
- vtSetError(ENotEmpty);
+ if(mb.nindex > 0){
+ werrstr(ENotEmpty);
goto Err;
}
- lumpDecRef(u, 1);
+ vtblockput(b);
}
- return 1;
-Err:
- lumpDecRef(u, 1);
return 0;
+Err:
+ vtblockput(b);
+ return -1;
}
int
-vfRemove(VacFile *vf, char *user)
-{
+vacfileremove(VacFile *f, char *muid)
+{
+ VacFile *ff;
+
/* can not remove the root */
- if(vfIsRoot(vf)) {
- vtSetError(ERoot);
- return 0;
+ if(vacfileisroot(f)){
+ werrstr(ERoot);
+ return -1;
}
- if(!vfLock(vf))
- return 0;
+ if(filelock(f) < 0)
+ return -1;
- if(vfIsDir(vf) && !vfCheckEmpty(vf))
+ if(f->source->mode != VtORDWR){
+ werrstr(EReadOnly);
+ goto Err1;
+ }
+ if(vtfilelock2(f->source, f->msource, -1) < 0)
+ goto Err1;
+ if(vacfileisdir(f) && filecheckempty(f)<0)
goto Err;
-
- assert(vf->down == nil);
-
- sourceRemove(vf->source);
- vf->source = nil;
- if(vf->msource) {
- sourceRemove(vf->msource);
- vf->msource = nil;
- }
-
- vfUnlock(vf);
-
- if(!vfMetaRemove(vf, user))
- return 0;
-
- return 1;
-
-Err:
- vfUnlock(vf);
+
+ for(ff=f->down; ff; ff=ff->next)
+ assert(ff->removed);
+
+ vtfileremove(f->source);
+ f->source = nil;
+ if(f->msource){
+ vtfileremove(f->msource);
+ f->msource = nil;
+ }
+
+ fileunlock(f);
+
+ if(filemetaremove(f, muid) < 0)
+ return -1;
+
return 0;
-}
-VacFile *
-vfIncRef(VacFile *vf)
-{
- vfMetaLock(vf);
- assert(vf->ref > 0);
- vf->ref++;
- vfMetaUnlock(vf);
- return vf;
+Err:
+ vtfileunlock(f->source);
+ if(f->msource)
+ vtfileunlock(f->msource);
+Err1:
+ fileunlock(f);
+ return -1;
}
-void
-vfDecRef(VacFile *vf)
+static int
+clri(VacFile *f, char *uid)
{
- VacFile *p, *q, **qq;
-
- if(vf->up == nil) {
- vfFree(vf);
- return;
- }
+ int r;
- vfMetaLock(vf);
- vf->ref--;
- if(vf->ref > 0) {
- vfMetaUnlock(vf);
- return;
+ if(f == nil)
+ return -1;
+ if(f->up->source->mode != VtORDWR){
+ werrstr(EReadOnly);
+ vacfiledecref(f);
+ return -1;
}
- assert(vf->ref == 0);
- assert(vf->down == nil);
-
- p = vf->up;
- qq = &p->down;
- for(q = *qq; q; qq=&q->next,q=*qq)
- if(q == vf)
- break;
- assert(q != nil);
- *qq = vf->next;
-
- vfMetaUnlock(vf);
- vfFree(vf);
+ r = filemetaremove(f, uid);
+ vacfiledecref(f);
+ return r;
+}
- vfDecRef(p);
+int
+vacfileclripath(VacFs *fs, char *path, char *uid)
+{
+ return clri(_fileopen(fs, path, 1), uid);
}
int
-vfGetVtEntry(VacFile *vf, VtEntry *e)
+vacfileclri(VacFile *dir, char *elem, char *uid)
{
- int res;
+ return clri(_filewalk(dir, elem, 1), uid);
+}
- if(!vfRLock(vf))
- return 0;
- res = sourceGetVtEntry(vf->source, e);
- vfRUnlock(vf);
- return res;
+VacFile*
+vacfileincref(VacFile *vf)
+{
+ filemetalock(vf);
+ assert(vf->ref > 0);
+ vf->ref++;
+ filemetaunlock(vf);
+ return vf;
}
int
-vfGetBlockScore(VacFile *vf, ulong bn, uchar score[VtScoreSize])
+vacfiledecref(VacFile *f)
{
- Lump *u;
- int ret, off;
- Source *r;
+ VacFile *p, *q, **qq;
- if(!vfRLock(vf))
+ if(f->up == nil){
+ /* never linked in */
+ assert(f->ref == 1);
+ filefree(f);
return 0;
+ }
- r = vf->source;
-
- u = sourceWalk(r, bn, 1, &off);
- if(u == nil){
- vfRUnlock(vf);
- return 0;
+ filemetalock(f);
+ f->ref--;
+ if(f->ref > 0){
+ filemetaunlock(f);
+ return -1;
}
+ assert(f->ref == 0);
+ assert(f->down == nil);
- ret = lumpGetScore(u, off, score);
- lumpDecRef(u, 0);
- vfRUnlock(vf);
+ filemetaflush2(f, nil);
- return ret;
+ p = f->up;
+ qq = &p->down;
+ for(q = *qq; q; q = *qq){
+ if(q == f)
+ break;
+ qq = &q->next;
+ }
+ assert(q != nil);
+ *qq = f->next;
+
+ filemetaunlock(f);
+ filefree(f);
+ vacfiledecref(p);
+ return 0;
}
-VacFile *
-vfGetParent(VacFile *vf)
+VacFile*
+filegetparent(VacFile *f)
{
- if(vfIsRoot(vf))
- return vfIncRef(vf);
- return vfIncRef(vf->up);
+ if(vacfileisroot(f))
+ return vacfileincref(f);
+ return vacfileincref(f->up);
}
-static VacDirEnum *
-vdeAlloc(VacFile *vf)
+VacDirEnum*
+vdeopen(VacFile *f)
{
- VacDirEnum *ds;
+ VacDirEnum *vde;
+ VacFile *p;
- if(!(vf->dir.mode & ModeDir)) {
- vtSetError(ENotDir);
- vfDecRef(vf);
+ if(!vacfileisdir(f)){
+ werrstr(ENotDir);
return nil;
}
- ds = vtMemAllocZ(sizeof(VacDirEnum));
- ds->file = vf;
-
- return ds;
-}
-
-VacDirEnum *
-vdeOpen(VacFS *fs, char *path)
-{
- VacFile *vf;
-
- vf = vfOpen(fs, path);
- if(vf == nil)
+ /* flush out meta data */
+ if(filelock(f) < 0)
return nil;
+ for(p=f->down; p; p=p->next)
+ filemetaflush2(p, nil);
+ fileunlock(f);
- return vdeAlloc(vf);
-}
+ vde = vtmallocz(sizeof(VacDirEnum));
+ vde->file = vacfileincref(f);
-VacDirEnum *
-vfDirEnum(VacFile *vf)
-{
- return vdeAlloc(vfIncRef(vf));
+ return vde;
}
static int
-dirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size)
+direntrysize(VtFile *s, ulong elem, ulong gen, uvlong *size)
{
- Lump *u;
+ VtBlock *b;
ulong bn;
VtEntry e;
+ int epb;
- bn = elem/s->epb;
- elem -= bn*s->epb;
+ epb = s->dsize/VtEntrySize;
+ bn = elem/epb;
+ elem -= bn*epb;
- u = sourceGetLump(s, bn, 1, 1);
- if(u == nil)
+ b = vtfileblock(s, bn, VtOREAD);
+ if(b == nil)
goto Err;
- if(u->asize < (elem+1)*VtEntrySize) {
- vtSetError(ENoDir);
+ if(vtentryunpack(&e, b->data, elem) < 0)
goto Err;
- }
- vtEntryUnpack(&e, u->data, elem);
- if(!(e.flags & VtEntryActive) || e.gen != gen) {
-fprint(2, "gen mismatch\n");
- vtSetError(ENoDir);
- goto Err;
- }
- *size = e.size;
- lumpDecRef(u, 1);
- return 1;
+ /* hanging entries are returned as zero size */
+ if(!(e.flags & VtEntryActive) || e.gen != gen)
+ *size = 0;
+ else
+ *size = e.size;
+ vtblockput(b);
+ return 0;
Err:
- lumpDecRef(u, 1);
- return 0;
+ vtblockput(b);
+ return -1;
}
-int
-vdeRead(VacDirEnum *ds, VacDir *dir, int n)
+static int
+vdefill(VacDirEnum *vde)
{
- ulong nb;
- int i;
- Source *meta, *source;
+ int i, n;
+ VtFile *meta, *source;
MetaBlock mb;
MetaEntry me;
- Lump *u;
+ VacFile *f;
+ VtBlock *b;
+ VacDir *de;
- vfRAccess(ds->file);
+ /* clean up first */
+ for(i=vde->i; i<vde->n; i++)
+ vdcleanup(vde->buf+i);
+ vtfree(vde->buf);
+ vde->buf = nil;
+ vde->i = 0;
+ vde->n = 0;
- if(!vfRLock(ds->file))
- return -1;
+ f = vde->file;
- i = 0;
- u = nil;
- source = ds->file->source;
- meta = ds->file->msource;
- nb = (sourceGetSize(meta) + meta->dsize - 1)/meta->dsize;
-
- if(ds->block >= nb)
- goto Exit;
- u = sourceGetLump(meta, ds->block, 1, 1);
- if(u == nil)
+ source = f->source;
+ meta = f->msource;
+
+ b = vtfileblock(meta, vde->boff, VtOREAD);
+ if(b == nil)
goto Err;
- if(!mbUnpack(&mb, u->data, u->asize))
+ if(mbunpack(&mb, b->data, meta->dsize) < 0)
goto Err;
- for(i=0; i<n; i++) {
- while(ds->index >= mb.nindex) {
- lumpDecRef(u, 1);
- u = nil;
- ds->index = 0;
- ds->block++;
- if(ds->block >= nb)
- goto Exit;
- u = sourceGetLump(meta, ds->block, 1, 1);
- if(u == nil)
- goto Err;
- if(!mbUnpack(&mb, u->data, u->asize))
- goto Err;
- }
- if(!meUnpack(&me, &mb, ds->index))
+ n = mb.nindex;
+ vde->buf = vtmalloc(n * sizeof(VacDir));
+
+ for(i=0; i<n; i++){
+ de = vde->buf + i;
+ meunpack(&me, &mb, i);
+ if(vdunpack(de, &me) < 0)
+ goto Err;
+ vde->n++;
+ if(!(de->mode & ModeDir))
+ if(direntrysize(source, de->entry, de->gen, &de->size) < 0)
goto Err;
- if(dir != nil) {
- if(!vdUnpack(&dir[i], &me))
- goto Err;
- if(!(dir[i].mode & ModeDir))
- if(!dirEntrySize(source, dir[i].entry, dir[i].gen, &dir[i].size))
- goto Err;
- }
- ds->index++;
}
-Exit:
- lumpDecRef(u, 1);
- vfRUnlock(ds->file);
- return i;
+ vde->boff++;
+ vtblockput(b);
+ return 0;
Err:
- lumpDecRef(u, 1);
- vfRUnlock(ds->file);
- n = i;
- for(i=0; i<n ; i++)
- vdCleanup(&dir[i]);
+ vtblockput(b);
return -1;
}
+int
+vderead(VacDirEnum *vde, VacDir *de)
+{
+ int ret, didread;
+ VacFile *f;
+ u32int nb;
+
+ f = vde->file;
+ if(filerlock(f) < 0)
+ return -1;
+
+ if(vtfilelock2(f->source, f->msource, VtOREAD) < 0){
+ filerunlock(f);
+ return -1;
+ }
+
+ nb = (vtfilegetsize(f->msource)+f->msource->dsize-1)/f->msource->dsize;
+
+ didread = 0;
+ while(vde->i >= vde->n){
+ if(vde->boff >= nb){
+ ret = 0;
+ goto Return;
+ }
+ didread = 1;
+ if(vdefill(vde) < 0){
+ ret = -1;
+ goto Return;
+ }
+ }
+
+ memmove(de, vde->buf + vde->i, sizeof(VacDir));
+ vde->i++;
+ ret = 1;
+
+Return:
+ vtfileunlock(f->source);
+ vtfileunlock(f->msource);
+ filerunlock(f);
+
+ if(didread)
+ fileraccess(f);
+ return ret;
+}
+
void
-vdeFree(VacDirEnum *ds)
+vdeclose(VacDirEnum *vde)
{
- if(ds == nil)
+ int i;
+ if(vde == nil)
return;
- vfDecRef(ds->file);
- vtMemFree(ds);
+ for(i=vde->i; i<vde->n; i++)
+ vdcleanup(vde->buf+i);
+ vtfree(vde->buf);
+ vacfiledecref(vde->file);
+ vtfree(vde);
}
-static ulong
-msAlloc(Source *ms, ulong start, int n)
+/*
+ * caller must lock f->source and f->msource
+ * caller must NOT lock the source and msource
+ * referenced by dir.
+ */
+static u32int
+filemetaalloc(VacFile *f, VacDir *dir, u32int start)
{
- ulong nb, i;
- Lump *u;
+ u32int nb, bo;
+ VtBlock *b, *bb;
MetaBlock mb;
+ int nn;
+ uchar *p;
+ int i, n, epb;
+ MetaEntry me;
+ VtFile *s, *ms;
+
+ s = f->source;
+ ms = f->msource;
- nb = sourceGetNumBlocks(ms);
- u = nil;
+ n = vdsize(dir);
+ nb = (vtfilegetsize(ms)+ms->dsize-1)/ms->dsize;
+ b = nil;
if(start > nb)
start = nb;
- for(i=start; i<nb; i++) {
- u = sourceGetLump(ms, i, 1, 1);
- if(u == nil)
+ for(bo=start; bo<nb; bo++){
+ b = vtfileblock(ms, bo, VtORDWR);
+ if(b == nil)
goto Err;
- if(!mbUnpack(&mb, u->data, ms->dsize))
+ if(mbunpack(&mb, b->data, ms->dsize) < 0)
goto Err;
- if(mb.maxsize - mb.size + mb.free >= n && mb.nindex < mb.maxindex)
+ nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free;
+ if(n <= nn && mb.nindex < mb.maxindex)
break;
- lumpDecRef(u, 1);
- u = nil;
+ vtblockput(b);
+ b = nil;
}
+
/* add block to meta file */
- if(i == nb) {
- if(!sourceSetDepth(ms, (i+1)*ms->dsize))
- goto Err;
- u = sourceGetLump(ms, i, 0, 1);
- if(u == nil)
+ if(b == nil){
+ b = vtfileblock(ms, bo, VtORDWR);
+ if(b == nil)
goto Err;
- sourceSetSize(ms, (nb+1)*ms->dsize);
- mbInit(&mb, u->data, u->asize);
- mbPack(&mb);
+ vtfilesetsize(ms, (nb+1)*ms->dsize);
+ mbinit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry);
+ }
+
+ p = mballoc(&mb, n);
+ if(p == nil){
+ /* mbAlloc might have changed block */
+ mbpack(&mb);
+ vtblockdirty(b);
+ werrstr(EBadMeta);
+ goto Err;
}
- lumpDecRef(u, 1);
- return i;
+
+ mbsearch(&mb, dir->elem, &i, &me);
+ assert(me.p == nil);
+ me.p = p;
+ me.size = n;
+ vdpack(dir, &me);
+ 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:
- lumpDecRef(u, 1);
+ vtblockput(b);
return NilBlock;
}
+static int
+chksource(VacFile *f)
+{
+ if(f->partial)
+ return 0;
+
+ if(f->source == nil || (f->dir.mode & ModeDir) && f->msource == nil){
+ werrstr(ERemoved);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+filerlock(VacFile *f)
+{
+// assert(!canwlock(&f->fs->elk));
+ rlock(&f->lk);
+ if(chksource(f) < 0){
+ runlock(&f->lk);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+filerunlock(VacFile *f)
+{
+ runlock(&f->lk);
+}
+
+static int
+filelock(VacFile *f)
+{
+// assert(!canwlock(&f->fs->elk));
+ wlock(&f->lk);
+ if(chksource(f) < 0){
+ wunlock(&f->lk);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+fileunlock(VacFile *f)
+{
+ wunlock(&f->lk);
+}
+
+/*
+ * f->source and f->msource must NOT be locked.
+ * fileMetaFlush locks the fileMeta and then the source (in fileMetaFlush2).
+ * We have to respect that ordering.
+ */
+static void
+filemetalock(VacFile *f)
+{
+ assert(f->up != nil);
+// assert(!canwlock(&f->fs->elk));
+ wlock(&f->up->lk);
+}
+
+static void
+filemetaunlock(VacFile *f)
+{
+ wunlock(&f->up->lk);
+}
+
+/*
+ * f->source and f->msource must NOT be locked.
+ * see filemetalock.
+ */
+static void
+fileraccess(VacFile* f)
+{
+ if(f->mode == VtOREAD)
+ return;
+
+ filemetalock(f);
+ f->dir.atime = time(0L);
+ f->dirty = 1;
+ filemetaunlock(f);
+}
+
+/*
+ * f->source and f->msource must NOT be locked.
+ * see filemetalock.
+ */
+static void
+filewaccess(VacFile* f, char *mid)
+{
+ if(f->mode == VtOREAD)
+ return;
+
+ filemetalock(f);
+ f->dir.atime = f->dir.mtime = time(0L);
+ if(strcmp(f->dir.mid, mid) != 0){
+ vtfree(f->dir.mid);
+ f->dir.mid = vtstrdup(mid);
+ }
+ f->dir.mcount++;
+ f->dirty = 1;
+ filemetaunlock(f);
+
+/*RSC: let's try this */
+/*presotto - lets not
+ if(f->up)
+ filewaccess(f->up, mid);
+*/
+}
+
+#if 0
+static void
+markCopied(Block *b)
+{
+ VtBlock *lb;
+ Label l;
+
+ if(globalToLocal(b->score) == NilBlock)
+ return;
+
+ if(!(b->l.state & BsCopied)){
+ /*
+ * We need to record that there are now pointers in
+ * b that are not unique to b. We do this by marking
+ * b as copied. Since we don't return the label block,
+ * the caller can't get the dependencies right. So we have
+ * to flush the block ourselves. This is a rare occurrence.
+ */
+ l = b->l;
+ l.state |= BsCopied;
+ lb = _blockSetLabel(b, &l);
+ WriteAgain:
+ while(!blockWrite(lb)){
+ fprint(2, "getEntry: could not write label block\n");
+ sleep(10*1000);
+ }
+ while(lb->iostate != BioClean && lb->iostate != BioDirty){
+ assert(lb->iostate == BioWriting);
+ vtSleep(lb->ioready);
+ }
+ if(lb->iostate == BioDirty)
+ goto WriteAgain;
+ vtblockput(lb);
+ }
+}
+
+static int
+getEntry(VtFile *r, Entry *e, int mark)
+{
+ Block *b;
+
+ if(r == nil){
+ memset(&e, 0, sizeof e);
+ return 1;
+ }
+
+ b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, VtOREAD);
+ if(b == nil)
+ return 0;
+ if(!entryUnpack(e, b->data, r->offset % r->epb)){
+ vtblockput(b);
+ return 0;
+ }
+
+ if(mark)
+ markCopied(b);
+ vtblockput(b);
+ return 1;
+}
+
+static int
+setEntry(Source *r, Entry *e)
+{
+ Block *b;
+ Entry oe;
+
+ b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, VtORDWR);
+ if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score);
+ if(b == nil)
+ return 0;
+ if(!entryUnpack(&oe, b->data, r->offset % r->epb)){
+ vtblockput(b);
+ return 0;
+ }
+ e->gen = oe.gen;
+ entryPack(e, b->data, r->offset % r->epb);
+
+ /* BUG b should depend on the entry pointer */
+
+ markCopied(b);
+ vtblockdirty(b);
+ vtblockput(b);
+ return 1;
+}
+
+/* assumes hold elk */
+int
+fileSnapshot(VacFile *dst, VacFile *src, u32int epoch, int doarchive)
+{
+ Entry e, ee;
+
+ /* add link to snapshot */
+ if(!getEntry(src->source, &e, 1) || !getEntry(src->msource, &ee, 1))
+ return 0;
+
+ e.snap = epoch;
+ e.archive = doarchive;
+ ee.snap = epoch;
+ ee.archive = doarchive;
+
+ if(!setEntry(dst->source, &e) || !setEntry(dst->msource, &ee))
+ return 0;
+ return 1;
+}
+
+int
+fileGetSources(VacFile *f, Entry *e, Entry *ee, int mark)
+{
+ if(!getEntry(f->source, e, mark)
+ || !getEntry(f->msource, ee, mark))
+ return 0;
+ return 1;
+}
+
+int
+fileWalkSources(VacFile *f)
+{
+ if(f->mode == VtOREAD)
+ return 1;
+ if(!sourceLock2(f->source, f->msource, VtORDWR))
+ return 0;
+ vtfileunlock(f->source);
+ vtfileunlock(f->msource);
+ return 1;
+}
+
+#endif
diff --git a/src/cmd/vac/fns.h b/src/cmd/vac/fns.h
index f013f126..335d85c9 100644
--- a/src/cmd/vac/fns.h
+++ b/src/cmd/vac/fns.h
@@ -1,46 +1,17 @@
-Source *sourceAlloc(Cache*, Lump *u, ulong block, int elem, int readonly);
-Source *sourceOpen(Source*, ulong entry, int readOnly);
-Source *sourceCreate(Source*, int psize, int dsize, int isdir, ulong entry);
-Lump *sourceGetLump(Source*, ulong block, int readOnly, int lock);
-Lump *sourceWalk(Source *r, ulong block, int readOnly, int *);
-int sourceSetDepth(Source *r, uvlong size);
-int sourceSetSize(Source *r, uvlong size);
-uvlong sourceGetSize(Source *r);
-int sourceSetDirSize(Source *r, ulong size);
-ulong sourceGetDirSize(Source *r);
-void sourceRemove(Source*);
-void sourceFree(Source*);
-int sourceGetVtEntry(Source *r, VtEntry *dir);
-ulong sourceGetNumBlocks(Source *r);
+int mbunpack(MetaBlock *mb, uchar *p, int n);
+void mbinsert(MetaBlock *mb, int i, MetaEntry*);
+void mbdelete(MetaBlock *mb, int i, MetaEntry*);
+void mbpack(MetaBlock *mb);
+uchar *mballoc(MetaBlock *mb, int n);
-Lump *lumpWalk(Lump *u, int offset, int type, int size, int readOnly, int lock);
-int lumpGetScore(Lump *u, int offset, uchar score[VtScoreSize]);
-void lumpDecRef(Lump*, int unlock);
-Lump *lumpIncRef(Lump*);
-void lumpFreeEntry(Lump *u, int entry);
+int meunpack(MetaEntry*, MetaBlock *mb, int i);
+int mecmp(MetaEntry*, char *s);
+int mecmpnew(MetaEntry*, char *s);
-Cache *cacheAlloc(VtSession *z, int blockSize, long nblocks);
-Lump *cacheAllocLump(Cache *c, int type, int size, int dir);
-void cacheFree(Cache *c);
-long cacheGetSize(Cache*);
-int cacheSetSize(Cache*, long);
-int cacheGetBlockSize(Cache *c);
-Lump *cacheGetLump(Cache *c, uchar score[VtScoreSize], int type, int size);
-void cacheCheck(Cache*);
+int vdsize(VacDir *dir);
+int vdunpack(VacDir *dir, MetaEntry*);
+void vdpack(VacDir *dir, MetaEntry*);
-int mbUnpack(MetaBlock *mb, uchar *p, int n);
-void mbInsert(MetaBlock *mb, int i, MetaEntry*);
-void mbDelete(MetaBlock *mb, int i, MetaEntry*);
-void mbPack(MetaBlock *mb);
-uchar *mbAlloc(MetaBlock *mb, int n);
-
-int meUnpack(MetaEntry*, MetaBlock *mb, int i);
-int meCmp(MetaEntry*, char *s);
-int meCmpNew(MetaEntry*, char *s);
-
-int vdSize(VacDir *dir);
-int vdUnpack(VacDir *dir, MetaEntry*);
-void vdPack(VacDir *dir, MetaEntry*);
-
-VacFile *vfRoot(VacFS *fs, uchar *score);
+VacFile *_vacfileroot(VacFs *fs, VtFile *file);
+int _vacfsnextqid(VacFs *fs, uvlong *qid);
diff --git a/src/cmd/vac/fs.c b/src/cmd/vac/fs.c
index 568e2ece..e6902d59 100644
--- a/src/cmd/vac/fs.c
+++ b/src/cmd/vac/fs.c
@@ -5,100 +5,107 @@
static char EBadVacFormat[] = "bad format for vac file";
-static VacFS *
-vfsAlloc(VtSession *z, int bsize, long ncache)
+static VacFs *
+vacfsalloc(VtConn *z, int bsize, int ncache, int mode)
{
- VacFS *fs;
+ VacFs *fs;
- fs = vtMemAllocZ(sizeof(VacFS));
+ fs = vtmallocz(sizeof(VacFs));
fs->ref = 1;
fs->z = z;
fs->bsize = bsize;
- fs->cache = cacheAlloc(z, bsize, ncache);
+ fs->cache = vtcachealloc(z, bsize, ncache, mode);
return fs;
}
static int
-readScore(int fd, uchar score[VtScoreSize])
+readscore(int fd, uchar score[VtScoreSize])
{
- char buf[44];
- int i, n, c;
+ char buf[45], *pref;
+ int n;
- n = readn(fd, buf, sizeof(buf));
+ n = readn(fd, buf, sizeof(buf)-1);
if(n < sizeof(buf)) {
- vtSetError("short read");
- return 0;
+ werrstr("short read");
+ return -1;
}
- if(strncmp(buf, "vac:", 4) != 0) {
- vtSetError("not a vac file");
- return 0;
+ buf[n] = 0;
+
+ if(vtparsescore(buf, &pref, score) < 0){
+ werrstr(EBadVacFormat);
+ return -1;
}
- memset(score, 0, VtScoreSize);
- for(i=4; i<sizeof(buf); 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 {
- vtSetError("bad format for venti score");
- return 0;
- }
- if((i & 1) == 0)
- c <<= 4;
-
- score[(i>>1)-2] |= c;
+ if(pref==nil || strcmp(pref, "vac") != 0) {
+ werrstr("not a vac file");
+ return -1;
}
- return 1;
+ return 0;
}
-VacFS *
-vfsOpen(VtSession *z, char *file, int readOnly, long ncache)
+VacFs*
+vacfsopen(VtConn *z, char *file, int mode, int ncache)
{
- VacFS *fs;
- int n, fd;
- VtRoot rt;
- uchar score[VtScoreSize], buf[VtRootSize];
- VacFile *root;
+ int fd;
+ uchar score[VtScoreSize];
fd = open(file, OREAD);
- if(fd < 0) {
- vtOSError();
+ if(fd < 0)
return nil;
- }
- if(!readScore(fd, score)) {
+ if(readscore(fd, score) < 0){
close(fd);
return nil;
}
close(fd);
- n = vtRead(z, score, VtRootType, buf, VtRootSize);
+ return vacfsopenscore(z, score, mode, ncache);
+}
+
+VacFs*
+vacfsopenscore(VtConn *z, u8int *score, int mode, int ncache)
+{
+ VacFs *fs;
+ int n;
+ VtRoot rt;
+ uchar buf[VtRootSize];
+ VacFile *root;
+ VtFile *r;
+ VtEntry e;
+
+ n = vtread(z, score, VtRootType, buf, VtRootSize);
if(n < 0)
return nil;
- if(n != VtRootSize) {
- vtSetError("vtRead on root too short");
- return nil;
- }
-
- if(!vtSha1Check(score, buf, VtRootSize)) {
- vtSetError("vtSha1Check failed on root block");
+ if(n != VtRootSize){
+ werrstr("vtread on root too short");
return nil;
}
- if(!vtRootUnpack(&rt, buf))
+ if(vtrootunpack(&rt, buf) < 0)
return nil;
if(strcmp(rt.type, "vac") != 0) {
- vtSetError("not a vac root");
+ werrstr("not a vac root");
return nil;
}
- fs = vfsAlloc(z, rt.blockSize, ncache);
+ fs = vacfsalloc(z, rt.blocksize, ncache, mode);
memmove(fs->score, score, VtScoreSize);
- fs->readOnly = readOnly;
- root = vfRoot(fs, rt.score);
+ fs->mode = mode;
+
+ memmove(e.score, score, VtScoreSize);
+ e.gen = 0;
+ e.psize = (rt.blocksize/VtEntrySize)*VtEntrySize;
+ e.dsize = rt.blocksize;
+ e.type = VtDirType;
+ e.flags = VtEntryActive;
+ e.size = 3*VtEntrySize;
+
+ root = nil;
+ if((r = vtfileopenroot(fs->cache, &e)) == nil)
+ goto Err;
+
+ root = _vacfileroot(fs, r);
+ vtfileclose(r);
if(root == nil)
goto Err;
fs->root = root;
@@ -106,83 +113,63 @@ vfsOpen(VtSession *z, char *file, int readOnly, long ncache)
return fs;
Err:
if(root)
- vfDecRef(root);
- vfsClose(fs);
+ vacfiledecref(root);
+ vacfsclose(fs);
return nil;
}
-VacFS *
-vacFsCreate(VtSession *z, int bsize, long ncache)
+VacFs *
+vacfscreate(VtConn *z, int bsize, int ncache)
{
- VacFS *fs;
-
- fs = vfsAlloc(z, bsize, ncache);
- return fs;
+ return vacfsalloc(z, bsize, ncache, VtORDWR);
}
int
-vfsIsReadOnly(VacFS *fs)
+vacfsmode(VacFs *fs)
{
- return fs->readOnly != 0;
+ return fs->mode;
}
-VacFile *
-vfsGetRoot(VacFS *fs)
+VacFile*
+vacfsgetroot(VacFs *fs)
{
- return vfIncRef(fs->root);
+ return vacfileincref(fs->root);
}
int
-vfsGetBlockSize(VacFS *fs)
+vacfsgetblocksize(VacFs *fs)
{
return fs->bsize;
}
int
-vfsGetScore(VacFS *fs, uchar score[VtScoreSize])
-{
- memmove(fs, score, VtScoreSize);
- return 1;
-}
-
-long
-vfsGetCacheSize(VacFS *fs)
+vacfsgetscore(VacFs *fs, u8int *score)
{
- return cacheGetSize(fs->cache);
+ memmove(score, fs->score, VtScoreSize);
+ return 0;
}
int
-vfsSetCacheSize(VacFS *fs, long size)
+_vacfsnextqid(VacFs *fs, uvlong *qid)
{
- return cacheSetSize(fs->cache, size);
+ ++fs->qid;
+ *qid = fs->qid;
+ return 0;
}
int
-vfsSnapshot(VacFS *fs, char *src, char *dst)
+vacfssync(VacFs *fs)
{
- USED(fs);
- USED(src);
- USED(dst);
- return 1;
+ return 0;
}
-int
-vfsSync(VacFS*)
-{
- return 1;
-}
-
-int
-vfsClose(VacFS *fs)
+void
+vacfsclose(VacFs *fs)
{
if(fs->root)
- vfDecRef(fs->root);
+ vacfiledecref(fs->root);
fs->root = nil;
- cacheCheck(fs->cache);
- cacheFree(fs->cache);
- memset(fs, 0, sizeof(VacFS));
- vtMemFree(fs);
- return 1;
+ vtcachefree(fs->cache);
+ vtfree(fs);
}
-
diff --git a/src/cmd/vac/mkfile b/src/cmd/vac/mkfile
index ac33ab32..a4b7a298 100644
--- a/src/cmd/vac/mkfile
+++ b/src/cmd/vac/mkfile
@@ -2,13 +2,12 @@ PLAN9=../../..
<$PLAN9/src/mkhdr
LIBFILES=\
- cache\
error\
file\
fs\
- source\
pack\
+SHORTLIB=venti sec thread mux bio 9
LIB=${LIBFILES:%=%.$O}
HFILES=\
diff --git a/src/cmd/vac/pack.c b/src/cmd/vac/pack.c
index b16834d9..074152ea 100644
--- a/src/cmd/vac/pack.c
+++ b/src/cmd/vac/pack.c
@@ -12,7 +12,7 @@ struct MetaChunk {
ushort index;
};
-static int stringUnpack(char **s, uchar **p, int *n);
+static int stringunpack(char **s, uchar **p, int *n);
/*
* integer conversion routines
@@ -23,35 +23,35 @@ static int stringUnpack(char **s, uchar **p, int *n);
#define U48GET(p) (((uvlong)U16GET(p)<<32)|(uvlong)U32GET((p)+2))
#define U64GET(p) (((uvlong)U32GET(p)<<32)|(uvlong)U32GET((p)+4))
-#define U8PUT(p,v) (p)[0]=(v)
-#define U16PUT(p,v) (p)[0]=(v)>>8;(p)[1]=(v)
-#define U32PUT(p,v) (p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
+#define U8PUT(p,v) (p)[0]=(v)&0xFF
+#define U16PUT(p,v) (p)[0]=((v)>>8)&0xFF;(p)[1]=(v)&0xFF
+#define U32PUT(p,v) (p)[0]=((v)>>24)&0xFF;(p)[1]=((v)>>16)&0xFF;(p)[2]=((v)>>8)&0xFF;(p)[3]=(v)&0xFF
#define U48PUT(p,v,t32) t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
#define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
static int
-stringUnpack(char **s, uchar **p, int *n)
+stringunpack(char **s, uchar **p, int *n)
{
int nn;
if(*n < 2)
- return 0;
+ return -1;
nn = U16GET(*p);
*p += 2;
*n -= 2;
if(nn > *n)
- return 0;
- *s = vtMemAlloc(nn+1);
+ return -1;
+ *s = vtmalloc(nn+1);
memmove(*s, *p, nn);
(*s)[nn] = 0;
*p += nn;
*n -= nn;
- return 1;
+ return 0;
}
static int
-stringPack(char *s, uchar *p)
+stringpack(char *s, uchar *p)
{
int n;
@@ -63,7 +63,7 @@ stringPack(char *s, uchar *p)
int
-mbUnpack(MetaBlock *mb, uchar *p, int n)
+mbunpack(MetaBlock *mb, uchar *p, int n)
{
u32int magic;
@@ -72,13 +72,13 @@ mbUnpack(MetaBlock *mb, uchar *p, int n)
if(n == 0) {
memset(mb, 0, sizeof(MetaBlock));
- return 1;
+ return 0;
}
magic = U32GET(p);
if(magic != MetaMagic && magic != MetaMagic+1) {
- vtSetError("bad meta block magic");
- return 0;
+ werrstr("bad meta block magic");
+ return -1;
}
mb->size = U16GET(p+4);
mb->free = U16GET(p+6);
@@ -87,22 +87,22 @@ mbUnpack(MetaBlock *mb, uchar *p, int n)
mb->unbotch = (magic == MetaMagic+1);
if(mb->size > n) {
- vtSetError("bad meta block size");
- return 0;
+ werrstr("bad meta block size");
+ return -1;
}
p += MetaHeaderSize;
n -= MetaHeaderSize;
USED(p);
if(n < mb->maxindex*MetaIndexSize) {
- vtSetError("truncated meta block 2");
- return 0;
+ werrstr("truncated meta block 2");
+ return -1;
}
- return 1;
+ return 0;
}
void
-mbPack(MetaBlock *mb)
+mbpack(MetaBlock *mb)
{
uchar *p;
@@ -117,7 +117,7 @@ mbPack(MetaBlock *mb)
void
-mbDelete(MetaBlock *mb, int i, MetaEntry *me)
+mbdelete(MetaBlock *mb, int i, MetaEntry *me)
{
uchar *p;
int n;
@@ -137,7 +137,7 @@ mbDelete(MetaBlock *mb, int i, MetaEntry *me)
}
void
-mbInsert(MetaBlock *mb, int i, MetaEntry *me)
+mbinsert(MetaBlock *mb, int i, MetaEntry *me)
{
uchar *p;
int o, n;
@@ -161,14 +161,14 @@ mbInsert(MetaBlock *mb, int i, MetaEntry *me)
}
int
-meUnpack(MetaEntry *me, MetaBlock *mb, int i)
+meunpack(MetaEntry *me, MetaBlock *mb, int i)
{
uchar *p;
int eo, en;
if(i < 0 || i >= mb->nindex) {
- vtSetError("bad meta entry index");
- return 0;
+ werrstr("bad meta entry index");
+ return -1;
}
p = mb->buf + MetaHeaderSize + i*MetaIndexSize;
@@ -177,32 +177,32 @@ meUnpack(MetaEntry *me, MetaBlock *mb, int i)
if(0)print("eo = %d en = %d\n", eo, en);
if(eo < MetaHeaderSize + mb->maxindex*MetaIndexSize) {
- vtSetError("corrupted entry in meta block");
- return 0;
+ werrstr("corrupted entry in meta block");
+ return -1;
}
if(eo+en > mb->size) {
- vtSetError("truncated meta block");
- return 0;
+ werrstr("truncated meta block");
+ return -1;
}
p = mb->buf + eo;
/* make sure entry looks ok and includes an elem name */
if(en < 8 || U32GET(p) != DirMagic || en < 8 + U16GET(p+6)) {
- vtSetError("corrupted meta block entry");
- return 0;
+ werrstr("corrupted meta block entry");
+ return -1;
}
me->p = p;
me->size = en;
- return 1;
+ return 0;
}
/* assumes a small amount of checking has been done in mbEntry */
int
-meCmp(MetaEntry *me, char *s)
+mecmp(MetaEntry *me, char *s)
{
int n;
uchar *p;
@@ -230,7 +230,7 @@ meCmp(MetaEntry *me, char *s)
}
int
-meCmpNew(MetaEntry *me, char *s)
+mecmpnew(MetaEntry *me, char *s)
{
int n;
uchar *p;
@@ -258,9 +258,9 @@ meCmpNew(MetaEntry *me, char *s)
}
static int
-offsetCmp(void *s0, void *s1)
+offsetcmp(const void *s0, const void *s1)
{
- MetaChunk *mc0, *mc1;
+ const MetaChunk *mc0, *mc1;
mc0 = s0;
mc1 = s1;
@@ -272,13 +272,13 @@ offsetCmp(void *s0, void *s1)
}
static MetaChunk *
-metaChunks(MetaBlock *mb)
+metachunks(MetaBlock *mb)
{
MetaChunk *mc;
int oo, o, n, i;
uchar *p;
- mc = vtMemAlloc(mb->nindex*sizeof(MetaChunk));
+ mc = vtmalloc(mb->nindex*sizeof(MetaChunk));
p = mb->buf + MetaHeaderSize;
for(i = 0; i<mb->nindex; i++) {
mc[i].offset = U16GET(p);
@@ -287,7 +287,7 @@ metaChunks(MetaBlock *mb)
p += MetaIndexSize;
}
- qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp);
+ qsort(mc, mb->nindex, sizeof(MetaChunk), offsetcmp);
/* check block looks ok */
oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;
@@ -307,12 +307,12 @@ metaChunks(MetaBlock *mb)
return mc;
Err:
- vtMemFree(mc);
+ vtfree(mc);
return nil;
}
static void
-mbCompact(MetaBlock *mb, MetaChunk *mc)
+mbcompact(MetaBlock *mb, MetaChunk *mc)
{
int oo, o, n, i;
@@ -333,7 +333,7 @@ mbCompact(MetaBlock *mb, MetaChunk *mc)
}
uchar *
-mbAlloc(MetaBlock *mb, int n)
+mballoc(MetaBlock *mb, int n)
{
int i, o;
MetaChunk *mc;
@@ -346,33 +346,33 @@ mbAlloc(MetaBlock *mb, int n)
if(mb->maxsize - mb->size + mb->free < n)
return nil;
- mc = metaChunks(mb);
+ mc = metachunks(mb);
/* look for hole */
o = MetaHeaderSize + mb->maxindex*MetaIndexSize;
for(i=0; i<mb->nindex; i++) {
if(mc[i].offset - o >= n) {
- vtMemFree(mc);
+ vtfree(mc);
return mb->buf + o;
}
o = mc[i].offset + mc[i].size;
}
if(mb->maxsize - o >= n) {
- vtMemFree(mc);
+ vtfree(mc);
return mb->buf + o;
}
/* compact and return off the end */
- mbCompact(mb, mc);
- vtMemFree(mc);
+ mbcompact(mb, mc);
+ vtfree(mc);
assert(mb->maxsize - mb->size >= n);
return mb->buf + mb->size;
}
int
-vdSize(VacDir *dir)
+vdsize(VacDir *dir)
{
int n;
@@ -399,17 +399,17 @@ vdSize(VacDir *dir)
n += 2 + strlen(dir->mid);
/* optional sections */
- if(dir->qidSpace) {
+ if(dir->qidspace) {
n += 3 + /* option header */
- 8 + /* qidOffset */
- 8; /* qid Max */
+ 8 + /* qid offset */
+ 8; /* qid max */
}
return n;
}
void
-vdPack(VacDir *dir, MetaEntry *me)
+vdpack(VacDir *dir, MetaEntry *me)
{
uchar *p;
ulong t32;
@@ -420,7 +420,7 @@ vdPack(VacDir *dir, MetaEntry *me)
U16PUT(p+4, 9); /* version */
p += 6;
- p += stringPack(dir->elem, p);
+ p += stringpack(dir->elem, p);
U32PUT(p, dir->entry);
U32PUT(p+4, dir->gen);
@@ -429,9 +429,9 @@ vdPack(VacDir *dir, MetaEntry *me)
U64PUT(p+16, dir->qid, t32);
p += 24;
- p += stringPack(dir->uid, p);
- p += stringPack(dir->gid, p);
- p += stringPack(dir->mid, p);
+ p += stringpack(dir->uid, p);
+ p += stringpack(dir->gid, p);
+ p += stringpack(dir->mid, p);
U32PUT(p, dir->mtime);
U32PUT(p+4, dir->mcount);
@@ -440,12 +440,12 @@ vdPack(VacDir *dir, MetaEntry *me)
U32PUT(p+16, dir->mode);
p += 5*4;
- if(dir->qidSpace) {
+ if(dir->qidspace) {
U8PUT(p, DirQidSpaceEntry);
U16PUT(p+1, 2*8);
p += 3;
- U64PUT(p, dir->qidOffset, t32);
- U64PUT(p+8, dir->qidMax, t32);
+ U64PUT(p, dir->qidoffset, t32);
+ U64PUT(p+8, dir->qidmax, t32);
}
assert(p == me->p + me->size);
@@ -453,7 +453,7 @@ vdPack(VacDir *dir, MetaEntry *me)
int
-vdUnpack(VacDir *dir, MetaEntry *me)
+vdunpack(VacDir *dir, MetaEntry *me)
{
int t, nn, n, version;
uchar *p;
@@ -483,7 +483,7 @@ if(0)print("vdUnpack: got magic\n");
if(0)print("vdUnpack: got version\n");
/* elem */
- if(!stringUnpack(&dir->elem, &p, &n))
+ if(stringunpack(&dir->elem, &p, &n) < 0)
goto Err;
if(0)print("vdUnpack: got elem\n");
@@ -532,15 +532,15 @@ if(0)print("vdUnpack: got qid\n");
}
/* uid */
- if(!stringUnpack(&dir->uid, &p, &n))
+ if(stringunpack(&dir->uid, &p, &n) < 0)
goto Err;
/* gid */
- if(!stringUnpack(&dir->gid, &p, &n))
+ if(stringunpack(&dir->gid, &p, &n) < 0)
goto Err;
/* mid */
- if(!stringUnpack(&dir->mid, &p, &n))
+ if(stringunpack(&dir->mid, &p, &n) < 0)
goto Err;
if(0)print("vdUnpack: got ids\n");
@@ -584,11 +584,11 @@ if(0)print("vdUnpack: got times\n");
break;
break;
case DirQidSpaceEntry:
- if(dir->qidSpace || nn != 16)
+ if(dir->qidspace || nn != 16)
goto Err;
- dir->qidSpace = 1;
- dir->qidOffset = U64GET(p);
- dir->qidMax = U64GET(p+8);
+ dir->qidspace = 1;
+ dir->qidoffset = U64GET(p);
+ dir->qidmax = U64GET(p+8);
break;
}
p += nn;
@@ -600,10 +600,112 @@ if(0)print("vdUnpack: got options\n");
goto Err;
if(0)print("vdUnpack: correct size\n");
- return 1;
+ return 0;
Err:
if(0)print("vdUnpack: XXXXXXXXXXXX EbadMeta\n");
- vtSetError(EBadMeta);
- vdCleanup(dir);
- return 0;
+ werrstr(EBadMeta);
+ vdcleanup(dir);
+ return -1;
+}
+
+void
+vdcleanup(VacDir *dir)
+{
+ vtfree(dir->elem);
+ dir->elem = nil;
+ vtfree(dir->uid);
+ dir->uid = nil;
+ vtfree(dir->gid);
+ dir->gid = nil;
+ vtfree(dir->mid);
+ dir->mid = nil;
+}
+
+void
+vdcopy(VacDir *dst, VacDir *src)
+{
+ *dst = *src;
+ dst->elem = vtstrdup(dst->elem);
+ dst->uid = vtstrdup(dst->uid);
+ dst->gid = vtstrdup(dst->gid);
+ dst->mid = vtstrdup(dst->mid);
+}
+
+int
+mbsearch(MetaBlock *mb, char *elem, int *ri, MetaEntry *me)
+{
+ int i;
+ int b, t, x;
+
+ /* binary search within block */
+ b = 0;
+ t = mb->nindex;
+ while(b < t) {
+ i = (b+t)>>1;
+ if(meunpack(me, mb, i) < 0)
+ return 0;
+ if(mb->unbotch)
+ x = mecmpnew(me, elem);
+ else
+ x = mecmp(me, elem);
+
+ if(x == 0) {
+ *ri = i;
+ return 1;
+ }
+
+ if(x < 0)
+ b = i+1;
+ else /* x > 0 */
+ t = i;
+ }
+
+ assert(b == t);
+
+ *ri = b; /* b is the index to insert this entry */
+ memset(me, 0, sizeof(*me));
+
+ return 1;
+}
+
+void
+mbinit(MetaBlock *mb, uchar *p, int n)
+{
+ memset(mb, 0, sizeof(MetaBlock));
+ mb->maxsize = n;
+ mb->buf = p;
+ mb->maxindex = n/100;
+ mb->size = MetaHeaderSize + mb->maxindex*MetaIndexSize;
+}
+
+int
+mbresize(MetaBlock *mb, MetaEntry *me, int n)
+{
+ uchar *p, *ep;
+
+ /* easy case */
+ if(n <= me->size){
+ me->size = n;
+ return 0;
+ }
+
+ /* try and expand entry */
+
+ p = me->p + me->size;
+ ep = mb->buf + mb->maxsize;
+ while(p < ep && *p == 0)
+ p++;
+ if(n <= p - me->p){
+ me->size = n;
+ return 0;
+ }
+
+ p = mballoc(mb, n);
+ if(p != nil){
+ me->p = p;
+ me->size = n;
+ return 0;
+ }
+
+ return -1;
}
diff --git a/src/cmd/vac/source.c b/src/cmd/vac/source.c
deleted file mode 100644
index e7245a2f..00000000
--- a/src/cmd/vac/source.c
+++ /dev/null
@@ -1,390 +0,0 @@
-#include "stdinc.h"
-#include "vac.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-
-static int sizeToDepth(uvlong s, int psize, int dsize);
-
-static int
-sizeToDepth(uvlong s, int psize, int dsize)
-{
- int np;
- int d;
-
- /* determine pointer depth */
- np = psize/VtScoreSize;
- s = (s + dsize - 1)/dsize;
- for(d = 0; s > 1; d++)
- s = (s + np - 1)/np;
- return d;
-}
-
-/* assumes u is lock? */
-Source *
-sourceAlloc(Cache *c, Lump *u, ulong block, int entry, int readOnly)
-{
- Source *r;
- VtEntry d;
-
- if(u->asize < (entry+1)*VtEntrySize) {
- vtSetError(ENoDir);
- return nil;
- }
-
- if(!vtEntryUnpack(&d, u->data, entry))
- return nil;
-
- if(!(d.flags & VtEntryActive)) {
-fprint(2, "bad flags %#ux %V\n", d.flags, d.score);
- vtSetError(ENoDir);
- return nil;
- }
-
- /* HACK for backwards compatiblity - should go away at some point */
- if(d.depth == 0) {
-if(d.size > d.dsize) fprint(2, "depth == 0! size = %ulld\n", d.size);
- d.depth = sizeToDepth(d.size, d.psize, d.dsize);
- }
-
- if(d.depth < sizeToDepth(d.size, d.psize, d.dsize)) {
- vtSetError(EBadDir);
- return nil;
- }
-
- r = vtMemAllocZ(sizeof(Source));
- r->lk = vtLockAlloc();
- r->cache = c;
- r->readOnly = readOnly;
- r->lump = lumpIncRef(u);
- r->block = block;
- r->entry = entry;
- r->gen = d.gen;
- r->dir = (d.flags & VtEntryDir) != 0;
- r->depth = d.depth;
- r->psize = d.psize;
- r->dsize = d.dsize;
- r->size = d.size;
-
- r->epb = r->dsize/VtEntrySize;
-
- return r;
-}
-
-Source *
-sourceOpen(Source *r, ulong entry, int readOnly)
-{
- ulong bn;
- Lump *u;
-
-if(0)fprint(2, "sourceOpen: %V:%d: %lud\n", r->lump->score, r->entry, entry);
- if(r->readOnly && !readOnly) {
- vtSetError(EReadOnly);
- return nil;
- }
-
- bn = entry/r->epb;
-
- u = sourceGetLump(r, bn, readOnly, 1);
- if(u == nil)
- return nil;
-
- r = sourceAlloc(r->cache, u, bn, entry%r->epb, readOnly);
- lumpDecRef(u, 1);
- return r;
-}
-
-Source *
-sourceCreate(Source *r, int psize, int dsize, int isdir, ulong entry)
-{
- Source *rr;
- int i;
- Lump *u;
- ulong bn;
- VtEntry dir;
-
- if(r->readOnly) {
- vtSetError(EReadOnly);
- return nil;
- }
-
- if(entry == 0) {
- /*
- * look at a random block to see if we can find an empty entry
- */
- entry = sourceGetDirSize(r);
- entry = r->epb*lnrand(entry/r->epb+1);
- }
-
- /*
- * need to loop since multiple threads could be trying to allocate
- */
- for(;;) {
- bn = entry/r->epb;
- sourceSetDepth(r, (uvlong)(bn+1)*r->dsize);
- u = sourceGetLump(r, bn, 0, 1);
- if(u == nil)
- return nil;
- for(i=entry%r->epb; i<r->epb; i++) {
- vtEntryUnpack(&dir, u->data, i);
- if((dir.flags&VtEntryActive) == 0 && dir.gen != ~0)
- goto Found;
- }
- lumpDecRef(u, 1);
- entry = sourceGetDirSize(r);
- }
-Found:
- /* found an entry */
- dir.psize = psize;
- dir.dsize = dsize;
- dir.flags = VtEntryActive;
- if(isdir)
- dir.flags |= VtEntryDir;
- dir.depth = 0;
- dir.size = 0;
- memmove(dir.score, vtZeroScore, VtScoreSize);
- vtEntryPack(&dir, u->data, i);
-
- sourceSetDirSize(r, bn*r->epb + i + 1);
- rr = sourceAlloc(r->cache, u, bn, i, 0);
-
- lumpDecRef(u, 1);
- return rr;
-}
-
-void
-sourceRemove(Source *r)
-{
- lumpFreeEntry(r->lump, r->entry);
- sourceFree(r);
-}
-
-int
-sourceSetDepth(Source *r, uvlong size)
-{
- Lump *u, *v;
- VtEntry dir;
- int depth;
-
- if(r->readOnly){
- vtSetError(EReadOnly);
- return 0;
- }
-
- depth = sizeToDepth(size, r->psize, r->dsize);
-
- assert(depth >= 0);
-
- if(depth > VtPointerDepth) {
- vtSetError(ETooBig);
- return 0;
- }
-
- vtLock(r->lk);
-
- if(r->depth >= depth) {
- vtUnlock(r->lk);
- return 1;
- }
-
- u = r->lump;
- vtLock(u->lk);
- if(!vtEntryUnpack(&dir, u->data, r->entry)) {
- vtUnlock(u->lk);
- vtUnlock(r->lk);
- return 0;
- }
- while(dir.depth < depth) {
- v = cacheAllocLump(r->cache, VtPointerType0+r->depth, r->psize, r->dir);
- if(v == nil)
- break;
- memmove(v->data, dir.score, VtScoreSize);
- memmove(dir.score, v->score, VtScoreSize);
- dir.depth++;
- vtUnlock(v->lk);
- }
- vtEntryPack(&dir, u->data, r->entry);
- vtUnlock(u->lk);
-
- r->depth = dir.depth;
- vtUnlock(r->lk);
-
- return dir.depth == depth;
-}
-
-int
-sourceGetVtEntry(Source *r, VtEntry *dir)
-{
- Lump *u;
-
- u = r->lump;
- vtLock(u->lk);
- if(!vtEntryUnpack(dir, u->data, r->entry)) {
- vtUnlock(u->lk);
- return 0;
- }
- vtUnlock(u->lk);
- return 1;
-}
-
-uvlong
-sourceGetSize(Source *r)
-{
- uvlong size;
-
- vtLock(r->lk);
- size = r->size;
- vtUnlock(r->lk);
-
- return size;
-}
-
-
-int
-sourceSetSize(Source *r, uvlong size)
-{
- Lump *u;
- VtEntry dir;
- int depth;
-
- if(r->readOnly) {
- vtSetError(EReadOnly);
- return 0;
- }
-
- if(size > VtMaxFileSize || size > ((uvlong)MaxBlock)*r->dsize) {
- vtSetError(ETooBig);
- return 0;
- }
-
- vtLock(r->lk);
- depth = sizeToDepth(size, r->psize, r->dsize);
- if(size < r->size) {
- vtUnlock(r->lk);
- return 1;
- }
- if(depth > r->depth) {
- vtSetError(EBadDir);
- vtUnlock(r->lk);
- return 0;
- }
-
- u = r->lump;
- vtLock(u->lk);
- vtEntryUnpack(&dir, u->data, r->entry);
- dir.size = size;
- vtEntryPack(&dir, u->data, r->entry);
- vtUnlock(u->lk);
- r->size = size;
- vtUnlock(r->lk);
- return 1;
-}
-
-int
-sourceSetDirSize(Source *r, ulong ds)
-{
- uvlong size;
-
- size = (uvlong)r->dsize*(ds/r->epb);
- size += VtEntrySize*(ds%r->epb);
- return sourceSetSize(r, size);
-}
-
-ulong
-sourceGetDirSize(Source *r)
-{
- ulong ds;
- uvlong size;
-
- size = sourceGetSize(r);
- ds = r->epb*(size/r->dsize);
- ds += (size%r->dsize)/VtEntrySize;
- return ds;
-}
-
-ulong
-sourceGetNumBlocks(Source *r)
-{
- return (sourceGetSize(r)+r->dsize-1)/r->dsize;
-}
-
-Lump *
-sourceWalk(Source *r, ulong block, int readOnly, int *off)
-{
- int depth;
- int i, np;
- Lump *u, *v;
- int elem[VtPointerDepth+1];
- ulong b;
-
- if(r->readOnly && !readOnly) {
- vtSetError(EReadOnly);
- return nil;
- }
-
- vtLock(r->lk);
- np = r->psize/VtScoreSize;
- b = block;
- for(i=0; i<r->depth; i++) {
- elem[i] = b % np;
- b /= np;
- }
- if(b != 0) {
- vtUnlock(r->lk);
- vtSetError(EBadOffset);
- return nil;
- }
- elem[i] = r->entry;
- u = lumpIncRef(r->lump);
- depth = r->depth;
- *off = elem[0];
- vtUnlock(r->lk);
-
- for(i=depth; i>0; i--) {
- v = lumpWalk(u, elem[i], VtPointerType0+i-1, r->psize, readOnly, 0);
- lumpDecRef(u, 0);
- if(v == nil)
- return nil;
- u = v;
- }
-
- return u;
-}
-
-Lump *
-sourceGetLump(Source *r, ulong block, int readOnly, int lock)
-{
- int type, off;
- Lump *u, *v;
-
- if(r->readOnly && !readOnly) {
- vtSetError(EReadOnly);
- return nil;
- }
- if(block == NilBlock) {
- vtSetError(ENilBlock);
- return nil;
- }
-if(0)fprint(2, "sourceGetLump: %V:%d %lud\n", r->lump->score, r->entry, block);
- u = sourceWalk(r, block, readOnly, &off);
- if(u == nil)
- return nil;
- if(r->dir)
- type = VtDirType;
- else
- type = VtDataType;
- v = lumpWalk(u, off, type, r->dsize, readOnly, lock);
- lumpDecRef(u, 0);
- return v;
-}
-
-void
-sourceFree(Source *k)
-{
- if(k == nil)
- return;
- lumpDecRef(k->lump, 0);
- vtLockFree(k->lk);
- memset(k, ~0, sizeof(*k));
- vtMemFree(k);
-}
diff --git a/src/cmd/vac/stdinc.h b/src/cmd/vac/stdinc.h
index aca405fc..bf72d3fd 100644
--- a/src/cmd/vac/stdinc.h
+++ b/src/cmd/vac/stdinc.h
@@ -1,8 +1,5 @@
#include <u.h>
#include <libc.h>
-
-#include "venti.h"
-
-typedef uvlong u64int;
-typedef uchar u8int;
-typedef ushort u16int;
+#include <thread.h>
+#include <venti.h>
+#include <libsec.h>
diff --git a/src/cmd/vac/vac.c b/src/cmd/vac/vac.c
index 8153c37b..f6efb917 100644
--- a/src/cmd/vac/vac.c
+++ b/src/cmd/vac/vac.c
@@ -1,30 +1,174 @@
-#include <u.h>
-#include <libc.h>
-#include <venti.h>
+#include "stdinc.h"
+#include "vac.h"
+#include "dat.h"
+#include "fns.h"
-int bsize;
-char *host;
-VtConn *z;
+typedef struct Sink Sink;
+typedef struct MetaSink MetaSink;
+typedef struct DirSink DirSink;
-void
+struct Sink {
+ VtConn *z;
+ VtEntry dir;
+ uchar *buf;
+ uchar *pbuf[VtPointerDepth+1];
+};
+
+struct DirSink {
+ Sink *sink;
+ MetaSink *msink;
+ ulong nentry;
+ uchar *buf;
+ uchar *p; /* current pointer */
+ uchar *ep; /* end pointer */
+};
+
+struct MetaSink {
+ Sink *sink;
+ uchar *buf;
+ int maxindex;
+ int nindex;
+ uchar *rp; /* start of current record */
+ uchar *p; /* current pointer */
+ uchar *ep; /* end pointer */
+};
+
+static void usage(void);
+static int strpcmp(const void*, const void*);
+static void warn(char *fmt, ...);
+static void cleanup(void);
+static u64int unittoull(char *s);
+static void vac(VtConn *z, char *argv[]);
+static void vacfile(DirSink *dsink, char *lname, char *sname, VacFile*);
+static void vacstdin(DirSink *dsink, char *name, VacFile *vf);
+static void vacdata(DirSink *dsink, int fd, char *lname, VacFile*, Dir*);
+static void vacdir(DirSink *dsink, int fd, char *lname, char *sname, VacFile*);
+static int vacmerge(DirSink *dsink, char *lname, char *sname);
+
+Sink *sinkalloc(VtConn *z, int psize, int dsize);
+void sinkwrite(Sink *k, uchar *data, int n);
+void sinkwritescore(Sink *k, uchar *score, int n);
+void sinkclose(Sink *k);
+void sinkfree(Sink *k);
+
+DirSink *dirsinkalloc(VtConn *z, int psize, int dsize);
+void dirsinkwrite(DirSink *k, VtEntry*);
+void dirsinkwritesink(DirSink *k, Sink*);
+int dirsinkwritefile(DirSink *k, VacFile *vf);
+void dirsinkclose(DirSink *k);
+void dirsinkfree(DirSink *k);
+
+MetaSink *metasinkalloc(VtConn *z, int psize, int dsize);
+void metasinkputc(MetaSink *k, int c);
+void metasinkputstring(MetaSink *k, char *s);
+void metasinkputuint32(MetaSink *k, ulong x);
+void metasinkputuint64(MetaSink *k, uvlong x);
+void metasinkwrite(MetaSink *k, uchar *data, int n);
+void metasinkwritedir(MetaSink *ms, VacDir *vd);
+void metasinkeor(MetaSink *k);
+void metasinkclose(MetaSink *k);
+void metasinkfree(MetaSink *k);
+void plan9tovacdir(VacDir*, Dir*, ulong entry, uvlong qid);
+
+enum {
+ Version = 8,
+ BlockSize = 8*1024,
+ MaxExclude = 1000,
+};
+
+struct {
+ ulong file;
+ ulong sfile;
+ ulong data;
+ ulong sdata;
+ ulong skip;
+ ulong meta;
+} stats;
+
+int bsize = BlockSize;
+int maxbsize;
+char *oname, *dfile;
+int verbose;
+uvlong fileid = 1;
+int qdiff;
+char *exclude[MaxExclude];
+int nexclude;
+int nowrite;
+int merge;
+char *isi;
+
+static void
usage(void)
{
- fprint(2, "usage: vac [-b blocksize] [-h host] file\n");
+ fprint(2, "usage: %s [-amqsv] [-h host] [-d vacfile] [-b blocksize] [-i name] [-e exclude] [-f vacfile] file ... \n", argv0);
+ exits("usage");
}
void
-main(int argc, char *argv[])
+threadmain(int argc, char *argv[])
{
+ VtConn *z;
+ char *p;
+ char *host = nil;
+ int statsflag = 0;
+
+ atexit(cleanup);
+
ARGBEGIN{
default:
usage();
case 'b':
- bsize = unittoull(EARGF(usage()));
+ p = ARGF();
+ if(p == 0)
+ usage();
+ bsize = unittoull(p);
+ if(bsize == ~0)
+ usage();
+ break;
+ case 'd':
+ dfile = ARGF();
+ if(dfile == nil)
+ usage();
+ break;
+ case 'e':
+ if(nexclude >= MaxExclude)
+ sysfatal("too many exclusions\n");
+ exclude[nexclude] = ARGF();
+ if(exclude[nexclude] == nil)
+ usage();
+ nexclude++;
+ break;
+ case 'f':
+ oname = ARGF();
+ if(oname == 0)
+ usage();
break;
case 'h':
- host = EARGF(usage());
+ host = ARGF();
+ if(host == nil)
+ usage();
+ break;
+ case 'i':
+ isi = ARGF();
+ if(isi == nil)
+ usage();
+ break;
+ case 'n':
+ nowrite++;
+ break;
+ case 'm':
+ merge++;
+ break;
+ case 'q':
+ qdiff++;
break;
- }ARGEND
+ case 's':
+ statsflag++;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ }ARGEND;
if(bsize < 512)
bsize = 512;
@@ -32,45 +176,73 @@ main(int argc, char *argv[])
bsize = VtMaxLumpSize;
maxbsize = bsize;
- vtAttach();
+ fmtinstall('V', vtscorefmt);
- fmtinstall('V', vtScoreFmt);
- fmtinstall('R', vtErrFmt);
-
- z = vtDial(host, 0);
+ z = vtdial(host);
if(z == nil)
- vtFatal("could not connect to server: %R");
+ sysfatal("could not connect to server: %r");
- if(!vtConnect(z, 0))
- vtFatal("vtConnect: %R");
+ if(vtconnect(z) < 0)
+ sysfatal("vtconnect: %r");
- qsort(exclude, nexclude, sizeof(char*), strpCmp);
+ qsort(exclude, nexclude, sizeof(char*), strpcmp);
vac(z, argv);
- if(!vtSync(z))
+
+ 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();
- vtClose(z);
- vtDetach();
+ vthangup(z);
- exits(0);
+ threadexitsall(0);
}
static int
-vac(VtSession *z, char *argv[])
+strpcmp(const void *p0, const void *p1)
+{
+ return strcmp(*(char**)p0, *(char**)p1);
+}
+
+int
+vacwrite(VtConn *z, uchar score[VtScoreSize], int type, uchar *buf, int n)
+{
+ assert(n > 0);
+ if(nowrite){
+ sha1(buf, n, score, nil);
+ return 0;
+ }
+sha1(buf, n, score, nil);
+fprint(2, "write %V %d\n", score, type);
+ return vtwrite(z, score, type, buf, n);
+}
+
+static char*
+lastelem(char *oname)
+{
+ char *p;
+
+ if(oname == nil)
+ abort();
+ if((p = strrchr(oname, '/')) == nil)
+ return oname;
+ return p+1;
+}
+
+static void
+vac(VtConn *z, char *argv[])
{
DirSink *dsink, *ds;
MetaSink *ms;
VtRoot root;
uchar score[VtScoreSize], buf[VtRootSize];
char cwd[2048];
- int cd, i;
+ int cd;
char *cp2, *cp;
- VacFS *fs;
+ VacFs *fs;
VacFile *vff;
int fd;
Dir *dir;
@@ -79,13 +251,13 @@ vac(VtSession *z, char *argv[])
if(getwd(cwd, sizeof(cwd)) == 0)
sysfatal("can't find current directory: %r\n");
- dsink = dirSinkAlloc(z, bsize, bsize);
+ dsink = dirsinkalloc(z, bsize, bsize);
fs = nil;
if(dfile != nil) {
- fs = vfsOpen(z, dfile, 1, 10000);
+ fs = vacfsopen(z, dfile, VtOREAD, 1000);
if(fs == nil)
- fprint(2, "could not open diff: %s: %s\n", dfile, vtGetError());
+ fprint(2, "could not open diff: %s: %r\n", dfile);
}
@@ -99,6 +271,10 @@ vac(VtSession *z, char *argv[])
dir = dirfstat(fd);
if(dir == nil)
sysfatal("dirfstat failed: %r");
+ if(oname)
+ dir->name = lastelem(oname);
+ else
+ dir->name = "stdin";
for(; *argv; argv++) {
cp2 = *argv;
@@ -115,10 +291,10 @@ vac(VtSession *z, char *argv[])
}
vff = nil;
if(fs)
- vff = vfOpen(fs, cp2);
- vacFile(dsink, argv[0], cp2, vff);
+ vff = vacfileopen(fs, cp2);
+ vacfile(dsink, argv[0], cp2, vff);
if(vff)
- vfDecRef(vff);
+ vacfiledecref(vff);
if(cd && chdir(cwd) < 0)
sysfatal("can't cd back to %s: %r\n", cwd);
}
@@ -126,68 +302,63 @@ vac(VtSession *z, char *argv[])
if(isi) {
vff = nil;
if(fs)
- vff = vfOpen(fs, isi);
- vacStdin(dsink, isi, vff);
+ vff = vacfileopen(fs, isi);
+ vacstdin(dsink, isi, vff);
if(vff)
- vfDecRef(vff);
+ vacfiledecref(vff);
}
- dirSinkClose(dsink);
+ dirsinkclose(dsink);
/* build meta information for the root */
- ms = metaSinkAlloc(z, bsize, bsize);
+ ms = metasinkalloc(z, bsize, bsize);
/* fake into a directory */
dir->mode |= (dir->mode&0444)>>2;
dir->qid.type |= QTDIR;
dir->mode |= DMDIR;
- plan9ToVacDir(&vd, dir, 0, fileid++);
+ plan9tovacdir(&vd, dir, 0, fileid++);
if(strcmp(vd.elem, "/") == 0){
- vtMemFree(vd.elem);
- vd.elem = vtStrDup("root");
+ vtfree(vd.elem);
+ vd.elem = vtstrdup("root");
}
- metaSinkWriteDir(ms, &vd);
- vdCleanup(&vd);
- metaSinkClose(ms);
+ metasinkwritedir(ms, &vd);
+ vdcleanup(&vd);
+ metasinkclose(ms);
- ds = dirSinkAlloc(z, bsize, bsize);
- dirSinkWriteSink(ds, dsink->sink);
- dirSinkWriteSink(ds, dsink->msink->sink);
- dirSinkWriteSink(ds, ms->sink);
- dirSinkClose(ds);
+ ds = dirsinkalloc(z, bsize, bsize);
+ dirsinkwritesink(ds, dsink->sink);
+ dirsinkwritesink(ds, dsink->msink->sink);
+ dirsinkwritesink(ds, ms->sink);
+ dirsinkclose(ds);
memset(&root, 0, sizeof(root));
- root.version = VtRootVersion;
strncpy(root.name, dir->name, sizeof(root.name));
root.name[sizeof(root.name)-1] = 0;
free(dir);
sprint(root.type, "vac");
memmove(root.score, ds->sink->dir.score, VtScoreSize);
- root.blockSize = maxbsize;
+ root.blocksize = maxbsize;
if(fs != nil)
- vfsGetScore(fs, root.prev);
+ vacfsgetscore(fs, root.prev);
- metaSinkFree(ms);
- dirSinkFree(ds);
- dirSinkFree(dsink);
+ metasinkfree(ms);
+ dirsinkfree(ds);
+ dirsinkfree(dsink);
if(fs != nil)
- vfsClose(fs);
-
- vtRootPack(&root, buf);
- if(!vacWrite(z, score, VtRootType, buf, VtRootSize))
- vtFatal("vacWrite failed: %s", vtGetError());
-
- fprint(fd, "vac:");
- for(i=0; i<VtScoreSize; i++)
- fprint(fd, "%.2x", score[i]);
- fprint(fd, "\n");
+ vacfsclose(fs);
+ vtrootpack(&root, buf);
+ if(vacwrite(z, score, VtRootType, buf, VtRootSize) < 0)
+ sysfatal("vacWrite failed: %r");
+
+ fprint(fd, "vac:%V\n", score);
+
/* avoid remove at cleanup */
oname = nil;
- return 1;
}
static int
-isExcluded(char *name)
+isexcluded(char *name)
{
int bot, top, i, x;
@@ -207,24 +378,24 @@ isExcluded(char *name)
}
static void
-vacFile(DirSink *dsink, char *lname, char *sname, VacFile *vf)
+vacfile(DirSink *dsink, char *lname, char *sname, VacFile *vf)
{
int fd;
Dir *dir;
VacDir vd;
ulong entry;
- if(isExcluded(lname)) {
+ if(isexcluded(lname)) {
warn("excluding: %s", lname);
return;
}
- if(merge && vacMerge(dsink, lname, sname))
+ if(merge && vacmerge(dsink, lname, sname) >= 0)
return;
fd = open(sname, OREAD);
if(fd < 0) {
- warn("could not open file: %s: %s", lname, vtOSError());
+ warn("could not open file: %s: %r", lname);
return;
}
@@ -237,24 +408,25 @@ vacFile(DirSink *dsink, char *lname, char *sname, VacFile *vf)
close(fd);
return;
}
+ dir->name = lastelem(sname);
entry = dsink->nentry;
if(dir->mode & DMDIR)
- vacDir(dsink, fd, lname, sname, vf);
+ vacdir(dsink, fd, lname, sname, vf);
else
- vacData(dsink, fd, lname, vf, dir);
+ vacdata(dsink, fd, lname, vf, dir);
- plan9ToVacDir(&vd, dir, entry, fileid++);
- metaSinkWriteDir(dsink->msink, &vd);
- vdCleanup(&vd);
+ plan9tovacdir(&vd, dir, entry, fileid++);
+ metasinkwritedir(dsink->msink, &vd);
+ vdcleanup(&vd);
free(dir);
close(fd);
}
static void
-vacStdin(DirSink *dsink, char *name, VacFile *vf)
+vacstdin(DirSink *dsink, char *name, VacFile *vf)
{
Dir *dir;
VacDir vd;
@@ -268,21 +440,33 @@ vacStdin(DirSink *dsink, char *name, VacFile *vf)
warn("can't stat <stdio>: %r");
return;
}
+ dir->name = "stdin";
entry = dsink->nentry;
- vacData(dsink, 0, "<stdin>", vf, dir);
+ vacdata(dsink, 0, "<stdin>", vf, dir);
- plan9ToVacDir(&vd, dir, entry, fileid++);
- vd.elem = vtStrDup(name);
- metaSinkWriteDir(dsink->msink, &vd);
- vdCleanup(&vd);
+ plan9tovacdir(&vd, dir, entry, fileid++);
+ vd.elem = vtstrdup(name);
+ metasinkwritedir(dsink->msink, &vd);
+ vdcleanup(&vd);
free(dir);
}
+static int
+sha1check(u8int *score, uchar *buf, int n)
+{
+ char score2[VtScoreSize];
+
+ sha1(buf, n, score, nil);
+ if(memcmp(score, score2, VtScoreSize) == 0)
+ return 0;
+ return -1;
+}
+
static ulong
-vacDataSkip(Sink *sink, VacFile *vf, int fd, ulong blocks, uchar *buf, char *lname)
+vacdataskip(Sink *sink, VacFile *vf, int fd, ulong blocks, uchar *buf, char *lname)
{
int n;
ulong i;
@@ -293,24 +477,24 @@ vacDataSkip(Sink *sink, VacFile *vf, int fd, ulong blocks, uchar *buf, char *lna
warn("error seeking: %s", lname);
goto Err;
}
- n = readBlock(fd, buf, bsize);
+ n = readn(fd, buf, bsize);
if(n < bsize) {
warn("error checking append only file: %s", lname);
goto Err;
}
- if(!vfGetBlockScore(vf, blocks-1, score) || !vtSha1Check(score, buf, n)) {
+ if(vacfileblockscore(vf, blocks-1, score)<0 || sha1check(score, buf, n)<0) {
warn("last block of append file did not match: %s", lname);
goto Err;
}
for(i=0; i<blocks; i++) {
- if(!vfGetBlockScore(vf, i, score)) {
+ if(vacfileblockscore(vf, i, score) < 0) {
warn("could not get score: %s: %lud", lname, i);
seek(fd, i*bsize, 0);
return i;
}
stats.skip++;
- sinkWriteScore(sink, score, bsize);
+ sinkwritescore(sink, score, bsize);
}
return i;
@@ -320,7 +504,7 @@ Err:
}
static void
-vacData(DirSink *dsink, int fd, char *lname, VacFile *vf, Dir *dir)
+vacdata(DirSink *dsink, int fd, char *lname, VacFile *vf, Dir *dir)
{
uchar *buf;
Sink *sink;
@@ -332,13 +516,13 @@ vacData(DirSink *dsink, int fd, char *lname, VacFile *vf, Dir *dir)
vfblocks = 0;
if(vf != nil && qdiff) {
- vfGetDir(vf, &vd);
+ vacfilegetdir(vf, &vd);
if(vd.mtime == dir->mtime)
if(vd.size == dir->length)
if(!vd.plan9 || /* vd.p9path == dir->qid.path && */ vd.p9version == dir->qid.vers)
- if(dirSinkWriteFile(dsink, vf)) {
+ if(dirsinkwritefile(dsink, vf)) {
stats.sfile++;
- vdCleanup(&vd);
+ vdcleanup(&vd);
return;
}
@@ -349,30 +533,30 @@ vacData(DirSink *dsink, int fd, char *lname, VacFile *vf, Dir *dir)
if(vd.p9path == dir->qid.path)
vfblocks = vd.size/bsize;
- vdCleanup(&vd);
+ vdcleanup(&vd);
}
stats.file++;
- buf = vtMemAlloc(bsize);
- sink = sinkAlloc(dsink->sink->z, bsize, bsize);
+ buf = vtmalloc(bsize);
+ sink = sinkalloc(dsink->sink->z, bsize, bsize);
block = 0;
same = stats.sdata+stats.skip;
if(vfblocks > 1)
- block += vacDataSkip(sink, vf, fd, vfblocks, buf, lname);
+ block += vacdataskip(sink, vf, fd, vfblocks, buf, lname);
if(0) fprint(2, "vacData: %s: %ld\n", lname, block);
for(;;) {
- n = readBlock(fd, buf, bsize);
+ n = readn(fd, buf, bsize);
if(0 && n < 0)
- warn("file truncated due to read error: %s: %s", lname, vtOSError());
+ warn("file truncated due to read error: %s: %r", lname);
if(n <= 0)
break;
- if(vf != nil && vfGetBlockScore(vf, block, score) && vtSha1Check(score, buf, n)) {
+ if(vf != nil && vacfileblockscore(vf, block, score) && sha1check(score, buf, n)>=0) {
stats.sdata++;
- sinkWriteScore(sink, score, n);
+ sinkwritescore(sink, score, n);
} else
- sinkWrite(sink, buf, n);
+ sinkwrite(sink, buf, n);
block++;
}
same = stats.sdata+stats.skip - same;
@@ -381,15 +565,15 @@ if(0) fprint(2, "vacData: %s: %ld\n", lname, block);
if(0)fprint(2, "%s: total %lud same %lud:%lud diff %lud\n",
lname, block, same, vfblocks, block-same);
- sinkClose(sink);
- dirSinkWriteSink(dsink, sink);
- sinkFree(sink);
+ sinkclose(sink);
+ dirsinkwritesink(dsink, sink);
+ sinkfree(sink);
free(buf);
}
static void
-vacDir(DirSink *dsink, int fd, char *lname, char *sname, VacFile *vf)
+vacdir(DirSink *dsink, int fd, char *lname, char *sname, VacFile *vf)
{
Dir *dirs;
char *ln, *sn;
@@ -398,58 +582,58 @@ vacDir(DirSink *dsink, int fd, char *lname, char *sname, VacFile *vf)
VacFile *vvf;
char *name;
- ds = dirSinkAlloc(dsink->sink->z, bsize, bsize);
+ ds = dirsinkalloc(dsink->sink->z, bsize, bsize);
while((nd = dirread(fd, &dirs)) > 0){
for(i = 0; i < nd; i++){
name = dirs[i].name;
/* check for bad file names */
if(name[0] == 0 || strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
continue;
- ln = vtMemAlloc(strlen(lname) + strlen(name) + 2);
- sn = vtMemAlloc(strlen(sname) + strlen(name) + 2);
+ ln = vtmalloc(strlen(lname) + strlen(name) + 2);
+ sn = vtmalloc(strlen(sname) + strlen(name) + 2);
sprint(ln, "%s/%s", lname, name);
sprint(sn, "%s/%s", sname, name);
if(vf != nil)
- vvf = vfWalk(vf, name);
+ vvf = vacfilewalk(vf, name);
else
vvf = nil;
- vacFile(ds, ln, sn, vvf);
+ vacfile(ds, ln, sn, vvf);
if(vvf != nil)
- vfDecRef(vvf);
- vtMemFree(ln);
- vtMemFree(sn);
+ vacfiledecref(vvf);
+ vtfree(ln);
+ vtfree(sn);
}
free(dirs);
}
- dirSinkClose(ds);
- dirSinkWriteSink(dsink, ds->sink);
- dirSinkWriteSink(dsink, ds->msink->sink);
- dirSinkFree(ds);
+ dirsinkclose(ds);
+ dirsinkwritesink(dsink, ds->sink);
+ dirsinkwritesink(dsink, ds->msink->sink);
+ dirsinkfree(ds);
}
static int
-vacMergeFile(DirSink *dsink, VacFile *vf, VacDir *dir, uvlong offset, uvlong *max)
+vacmergefile(DirSink *dsink, VacFile *vf, VacDir *dir, uvlong offset, uvlong *max)
{
uchar buf[VtEntrySize];
VtEntry dd, md;
int e;
- if(vfRead(vf, buf, VtEntrySize, (uvlong)dir->entry*VtEntrySize) != VtEntrySize) {
+ if(vacfileread(vf, buf, VtEntrySize, (uvlong)dir->entry*VtEntrySize) != VtEntrySize) {
warn("could not read venti dir entry: %s\n", dir->elem);
- return 0;
+ return -1;
}
- vtEntryUnpack(&dd, buf, 0);
+ vtentryunpack(&dd, buf, 0);
if(dir->mode & ModeDir) {
e = dir->mentry;
if(e == 0)
e = dir->entry + 1;
- if(vfRead(vf, buf, VtEntrySize, e*VtEntrySize) != VtEntrySize) {
+ if(vacfileread(vf, buf, VtEntrySize, e*VtEntrySize) != VtEntrySize) {
warn("could not read venti dir entry: %s\n", dir->elem);
return 0;
}
- vtEntryUnpack(&md, buf, 0);
+ vtentryunpack(&md, buf, 0);
}
/* max might incorrect in some old dumps */
@@ -461,27 +645,27 @@ vacMergeFile(DirSink *dsink, VacFile *vf, VacDir *dir, uvlong offset, uvlong *ma
dir->qid += offset;
dir->entry = dsink->nentry;
- if(dir->qidSpace) {
- dir->qidOffset += offset;
+ if(dir->qidspace) {
+ dir->qidoffset += offset;
} else {
- dir->qidSpace = 1;
- dir->qidOffset = offset;
- dir->qidMax = *max;
+ dir->qidspace = 1;
+ dir->qidoffset = offset;
+ dir->qidmax = *max;
}
- dirSinkWrite(dsink, &dd);
+ dirsinkwrite(dsink, &dd);
if(dir->mode & ModeDir)
- dirSinkWrite(dsink, &md);
- metaSinkWriteDir(dsink->msink, dir);
+ dirsinkwrite(dsink, &md);
+ metasinkwritedir(dsink->msink, dir);
- return 1;
+ return 0;
}
static int
-vacMerge(DirSink *dsink, char *lname, char *sname)
+vacmerge(DirSink *dsink, char *lname, char *sname)
{
char *p;
- VacFS *fs;
+ VacFs *fs;
VacFile *vf;
VacDirEnum *d;
VacDir dir;
@@ -492,67 +676,67 @@ vacMerge(DirSink *dsink, char *lname, char *sname)
return 0;
d = nil;
- fs = vfsOpen(dsink->sink->z, sname, 1, 100);
+ fs = vacfsopen(dsink->sink->z, sname, VtOREAD, 100);
if(fs == nil)
- return 0;
+ return -1;
- vf = vfOpen(fs, "/");
+ vf = vacfileopen(fs, "/");
if(vf == nil)
goto Done;
- max = vfGetId(vf);
- d = vdeOpen(fs, "/");
+ max = vacfilegetid(vf);
+ d = vdeopen(vf);
if(d == nil)
goto Done;
if(verbose)
fprint(2, "merging: %s\n", lname);
- if(maxbsize < vfsGetBlockSize(fs))
- maxbsize = vfsGetBlockSize(fs);
+ if(maxbsize < fs->bsize)
+ maxbsize = fs->bsize;
for(;;) {
- if(vdeRead(d, &dir, 1) < 1)
+ if(vderead(d, &dir) < 1)
break;
- vacMergeFile(dsink, vf, &dir, fileid, &max);
- vdCleanup(&dir);
+ vacmergefile(dsink, vf, &dir, fileid, &max);
+ vdcleanup(&dir);
}
fileid += max;
Done:
if(d != nil)
- vdeFree(d);
+ vdeclose(d);
if(vf != nil)
- vfDecRef(vf);
- vfsClose(fs);
- return 1;
+ vacfiledecref(vf);
+ vacfsclose(fs);
+ return 0;
}
Sink *
-sinkAlloc(VtSession *z, int psize, int dsize)
+sinkalloc(VtConn *z, int psize, int dsize)
{
Sink *k;
int i;
if(psize < 512 || psize > VtMaxLumpSize)
- vtFatal("sinkAlloc: bad psize");
+ sysfatal("sinkalloc: bad psize");
if(dsize < 512 || dsize > VtMaxLumpSize)
- vtFatal("sinkAlloc: bad psize");
+ sysfatal("sinkalloc: bad psize");
psize = VtScoreSize*(psize/VtScoreSize);
- k = vtMemAllocZ(sizeof(Sink));
+ k = vtmallocz(sizeof(Sink));
k->z = z;
k->dir.flags = VtEntryActive;
k->dir.psize = psize;
k->dir.dsize = dsize;
- k->buf = vtMemAllocZ(VtPointerDepth*k->dir.psize + VtScoreSize);
+ k->buf = vtmallocz(VtPointerDepth*k->dir.psize + VtScoreSize);
for(i=0; i<=VtPointerDepth; i++)
k->pbuf[i] = k->buf + i*k->dir.psize;
return k;
}
void
-sinkWriteScore(Sink *k, uchar score[VtScoreSize], int n)
+sinkwritescore(Sink *k, uchar score[VtScoreSize], int n)
{
int i;
uchar *p;
@@ -567,11 +751,11 @@ sinkWriteScore(Sink *k, uchar score[VtScoreSize], int n)
if(k->pbuf[i] < k->buf + d->psize*(i+1))
break;
if(i == VtPointerDepth-1)
- vtFatal("file too big");
+ sysfatal("file too big");
p = k->buf+i*d->psize;
stats.meta++;
- if(!vacWrite(k->z, k->pbuf[i+1], VtPointerType0+i, p, d->psize))
- vtFatal("vacWrite failed: %s", vtGetError());
+ if(vacwrite(k->z, k->pbuf[i+1], VtDataType+1+i, p, d->psize) < 0)
+ sysfatal("vacwrite failed: %r");
k->pbuf[i] = p;
}
@@ -582,29 +766,29 @@ sinkWriteScore(Sink *k, uchar score[VtScoreSize], int n)
}
void
-sinkWrite(Sink *k, uchar *p, int n)
+sinkwrite(Sink *k, uchar *p, int n)
{
int type;
uchar score[VtScoreSize];
if(n > k->dir.dsize)
- vtFatal("sinkWrite: size too big");
+ sysfatal("sinkWrite: size too big");
- if(k->dir.flags & VtEntryDir) {
+ if((k->dir.type&~VtTypeDepthMask) == VtDirType){
type = VtDirType;
stats.meta++;
} else {
type = VtDataType;
stats.data++;
}
- if(!vacWrite(k->z, score, type, p, n))
- vtFatal("vacWrite failed: %s", vtGetError());
+ if(vacwrite(k->z, score, type, p, n) < 0)
+ sysfatal("vacWrite failed: %r");
- sinkWriteScore(k, score, n);
+ sinkwritescore(k, score, n);
}
static int
-sizeToDepth(uvlong s, int psize, int dsize)
+sizetodepth(uvlong s, int psize, int dsize)
{
int np;
int d;
@@ -618,9 +802,9 @@ sizeToDepth(uvlong s, int psize, int dsize)
}
void
-sinkClose(Sink *k)
+sinkclose(Sink *k)
{
- int i, n;
+ int i, n, base;
uchar *p;
VtEntry *kd;
@@ -628,7 +812,7 @@ sinkClose(Sink *k)
/* empty */
if(kd->size == 0) {
- memmove(kd->score, vtZeroScore, VtScoreSize);
+ memmove(kd->score, vtzeroscore, VtScoreSize);
return;
}
@@ -636,7 +820,10 @@ sinkClose(Sink *k)
if(k->pbuf[n] > k->buf + kd->psize*n)
break;
- kd->depth = sizeToDepth(kd->size, kd->psize, kd->dsize);
+fprint(2, "type %d -> ", kd->type);
+ base = kd->type&~VtTypeDepthMask;
+ kd->type = base + sizetodepth(kd->size, kd->psize, kd->dsize);
+fprint(2, "%d ", kd->type);
/* skip full part of tree */
for(i=0; i<n && k->pbuf[i] == k->buf + kd->psize*i; i++)
@@ -644,6 +831,7 @@ sinkClose(Sink *k)
/* is the tree completely full */
if(i == n && k->pbuf[n] == k->buf + kd->psize*n + VtScoreSize) {
+fprint(2, "full\n");
memmove(kd->score, k->pbuf[n] - VtScoreSize, VtScoreSize);
return;
}
@@ -653,93 +841,95 @@ sinkClose(Sink *k)
for(; i<n; i++) {
p = k->buf+i*kd->psize;
stats.meta++;
- if(!vacWrite(k->z, k->pbuf[i+1], VtPointerType0+i, p, k->pbuf[i]-p))
- vtFatal("vacWrite failed: %s", vtGetError());
+ if(vacwrite(k->z, k->pbuf[i+1], base+1+i, p, k->pbuf[i]-p) < 0)
+ sysfatal("vacWrite failed: %r");
k->pbuf[i+1] += VtScoreSize;
}
memmove(kd->score, k->pbuf[i] - VtScoreSize, VtScoreSize);
+fprint(2, "%V\n", kd->score);
}
void
-sinkFree(Sink *k)
+sinkfree(Sink *k)
{
- vtMemFree(k->buf);
- vtMemFree(k);
+ vtfree(k->buf);
+ vtfree(k);
}
DirSink *
-dirSinkAlloc(VtSession *z, int psize, int dsize)
+dirsinkalloc(VtConn *z, int psize, int dsize)
{
DirSink *k;
int ds;
ds = VtEntrySize*(dsize/VtEntrySize);
- k = vtMemAllocZ(sizeof(DirSink));
- k->sink = sinkAlloc(z, psize, ds);
- k->sink->dir.flags |= VtEntryDir;
- k->msink = metaSinkAlloc(z, psize, dsize);
- k->buf = vtMemAlloc(ds);
+ k = vtmallocz(sizeof(DirSink));
+ k->sink = sinkalloc(z, psize, ds);
+ k->sink->dir.type = VtDirType;
+ k->msink = metasinkalloc(z, psize, dsize);
+ k->buf = vtmalloc(ds);
k->p = k->buf;
k->ep = k->buf + ds;
return k;
}
void
-dirSinkWrite(DirSink *k, VtEntry *dir)
+dirsinkwrite(DirSink *k, VtEntry *dir)
{
if(k->p + VtEntrySize > k->ep) {
- sinkWrite(k->sink, k->buf, k->p - k->buf);
+ sinkwrite(k->sink, k->buf, k->p - k->buf);
k->p = k->buf;
}
- vtEntryPack(dir, k->p, 0);
+fprint(2, "write entry %V %d\n", dir->score, dir->type);
+ vtentrypack(dir, k->p, 0);
k->nentry++;
k->p += VtEntrySize;
}
void
-dirSinkWriteSink(DirSink *k, Sink *sink)
+dirsinkwritesink(DirSink *k, Sink *sink)
{
- dirSinkWrite(k, &sink->dir);
+ dirsinkwrite(k, &sink->dir);
}
int
-dirSinkWriteFile(DirSink *k, VacFile *vf)
+dirsinkwritefile(DirSink *k, VacFile *vf)
{
VtEntry dir;
- if(!vfGetVtEntry(vf, &dir))
- return 0;
- dirSinkWrite(k, &dir);
- return 1;
+ if(vacfilegetvtentry(vf, &dir) < 0)
+ return -1;
+ dirsinkwrite(k, &dir);
+ return 0;
}
void
-dirSinkClose(DirSink *k)
+dirsinkclose(DirSink *k)
{
- metaSinkClose(k->msink);
+ metasinkclose(k->msink);
if(k->p != k->buf)
- sinkWrite(k->sink, k->buf, k->p - k->buf);
- sinkClose(k->sink);
+ sinkwrite(k->sink, k->buf, k->p - k->buf);
+ sinkclose(k->sink);
}
void
-dirSinkFree(DirSink *k)
+dirsinkfree(DirSink *k)
{
- sinkFree(k->sink);
- metaSinkFree(k->msink);
- vtMemFree(k->buf);
- vtMemFree(k);
+ sinkfree(k->sink);
+ metasinkfree(k->msink);
+ vtfree(k->buf);
+ vtfree(k);
}
-MetaSink *
-metaSinkAlloc(VtSession *z, int psize, int dsize)
+MetaSink*
+metasinkalloc(VtConn *z, int psize, int dsize)
{
MetaSink *k;
- k = vtMemAllocZ(sizeof(MetaSink));
- k->sink = sinkAlloc(z, psize, dsize);
- k->buf = vtMemAlloc(dsize);
+ k = vtmallocz(sizeof(MetaSink));
+ k->sink = sinkalloc(z, psize, dsize);
+ k->buf = vtmalloc(dsize);
k->maxindex = dsize/100; /* 100 byte entries seems reasonable */
if(k->maxindex < 1)
k->maxindex = 1;
@@ -749,22 +939,22 @@ metaSinkAlloc(VtSession *z, int psize, int dsize)
}
/* hack to get base to compare routine - not reentrant */
-uchar *blockBase;
+uchar *blockbase;
int
-dirCmp(void *p0, void *p1)
+dircmp(const void *p0, const void *p1)
{
uchar *q0, *q1;
int n0, n1, r;
/* name is first element of entry */
- q0 = p0;
- q0 = blockBase + (q0[0]<<8) + q0[1];
+ q0 = (uchar*)p0;
+ q0 = blockbase + (q0[0]<<8) + q0[1];
n0 = (q0[6]<<8) + q0[7];
q0 += 8;
- q1 = p1;
- q1 = blockBase + (q1[0]<<8) + q1[1];
+ q1 = (uchar*)p1;
+ q1 = blockbase + (q1[0]<<8) + q1[1];
n1 = (q1[6]<<8) + q1[7];
q1 += 8;
@@ -780,7 +970,7 @@ dirCmp(void *p0, void *p1)
}
void
-metaSinkFlush(MetaSink *k)
+metasinkflush(MetaSink *k)
{
uchar *p;
int n;
@@ -798,19 +988,19 @@ metaSinkFlush(MetaSink *k)
mb.nindex = k->nindex;
mb.maxindex = k->maxindex;
mb.buf = p;
- mbPack(&mb);
+ mbpack(&mb);
p += MetaHeaderSize;
/* XXX this is not reentrant! */
- blockBase = k->buf;
- qsort(p, k->nindex, MetaIndexSize, dirCmp);
+ blockbase = k->buf;
+ qsort(p, k->nindex, MetaIndexSize, dircmp);
p += k->nindex*MetaIndexSize;
memset(p, 0, (k->maxindex-k->nindex)*MetaIndexSize);
p += (k->maxindex-k->nindex)*MetaIndexSize;
- sinkWrite(k->sink, k->buf, n);
+ sinkwrite(k->sink, k->buf, n);
/* move down partial entry */
n = k->p - k->rp;
@@ -821,109 +1011,109 @@ metaSinkFlush(MetaSink *k)
}
void
-metaSinkPutc(MetaSink *k, int c)
+metasinkputc(MetaSink *k, int c)
{
if(k->p+1 > k->ep)
- metaSinkFlush(k);
+ metasinkflush(k);
if(k->p+1 > k->ep)
- vtFatal("directory entry too large");
+ sysfatal("directory entry too large");
k->p[0] = c;
k->p++;
}
void
-metaSinkPutString(MetaSink *k, char *s)
+metasinkputstring(MetaSink *k, char *s)
{
int n = strlen(s);
- metaSinkPutc(k, n>>8);
- metaSinkPutc(k, n);
- metaSinkWrite(k, (uchar*)s, n);
+ metasinkputc(k, n>>8);
+ metasinkputc(k, n);
+ metasinkwrite(k, (uchar*)s, n);
}
void
-metaSinkPutUint32(MetaSink *k, ulong x)
+metasinkputuint32(MetaSink *k, ulong x)
{
- metaSinkPutc(k, x>>24);
- metaSinkPutc(k, x>>16);
- metaSinkPutc(k, x>>8);
- metaSinkPutc(k, x);
+ metasinkputc(k, x>>24);
+ metasinkputc(k, x>>16);
+ metasinkputc(k, x>>8);
+ metasinkputc(k, x);
}
void
-metaSinkPutUint64(MetaSink *k, uvlong x)
+metasinkputuint64(MetaSink *k, uvlong x)
{
- metaSinkPutUint32(k, x>>32);
- metaSinkPutUint32(k, x);
+ metasinkputuint32(k, x>>32);
+ metasinkputuint32(k, x);
}
void
-metaSinkWrite(MetaSink *k, uchar *data, int n)
+metasinkwrite(MetaSink *k, uchar *data, int n)
{
if(k->p + n > k->ep)
- metaSinkFlush(k);
+ metasinkflush(k);
if(k->p + n > k->ep)
- vtFatal("directory entry too large");
+ sysfatal("directory entry too large");
memmove(k->p, data, n);
k->p += n;
}
void
-metaSinkWriteDir(MetaSink *ms, VacDir *dir)
+metasinkwritedir(MetaSink *ms, VacDir *dir)
{
- metaSinkPutUint32(ms, DirMagic);
- metaSinkPutc(ms, Version>>8);
- metaSinkPutc(ms, Version);
- metaSinkPutString(ms, dir->elem);
- metaSinkPutUint32(ms, dir->entry);
- metaSinkPutUint64(ms, dir->qid);
- metaSinkPutString(ms, dir->uid);
- metaSinkPutString(ms, dir->gid);
- metaSinkPutString(ms, dir->mid);
- metaSinkPutUint32(ms, dir->mtime);
- metaSinkPutUint32(ms, dir->mcount);
- metaSinkPutUint32(ms, dir->ctime);
- metaSinkPutUint32(ms, dir->atime);
- metaSinkPutUint32(ms, dir->mode);
+ metasinkputuint32(ms, DirMagic);
+ metasinkputc(ms, Version>>8);
+ metasinkputc(ms, Version);
+ metasinkputstring(ms, dir->elem);
+ metasinkputuint32(ms, dir->entry);
+ metasinkputuint64(ms, dir->qid);
+ metasinkputstring(ms, dir->uid);
+ metasinkputstring(ms, dir->gid);
+ metasinkputstring(ms, dir->mid);
+ metasinkputuint32(ms, dir->mtime);
+ metasinkputuint32(ms, dir->mcount);
+ metasinkputuint32(ms, dir->ctime);
+ metasinkputuint32(ms, dir->atime);
+ metasinkputuint32(ms, dir->mode);
if(dir->plan9) {
- metaSinkPutc(ms, DirPlan9Entry); /* plan9 extra info */
- metaSinkPutc(ms, 0); /* plan9 extra size */
- metaSinkPutc(ms, 12); /* plan9 extra size */
- metaSinkPutUint64(ms, dir->p9path);
- metaSinkPutUint32(ms, dir->p9version);
+ metasinkputc(ms, DirPlan9Entry); /* plan9 extra info */
+ metasinkputc(ms, 0); /* plan9 extra size */
+ metasinkputc(ms, 12); /* plan9 extra size */
+ metasinkputuint64(ms, dir->p9path);
+ metasinkputuint32(ms, dir->p9version);
}
- if(dir->qidSpace != 0) {
- metaSinkPutc(ms, DirQidSpaceEntry);
- metaSinkPutc(ms, 0);
- metaSinkPutc(ms, 16);
- metaSinkPutUint64(ms, dir->qidOffset);
- metaSinkPutUint64(ms, dir->qidMax);
+ if(dir->qidspace != 0) {
+ metasinkputc(ms, DirQidSpaceEntry);
+ metasinkputc(ms, 0);
+ metasinkputc(ms, 16);
+ metasinkputuint64(ms, dir->qidoffset);
+ metasinkputuint64(ms, dir->qidmax);
}
if(dir->gen != 0) {
- metaSinkPutc(ms, DirGenEntry);
- metaSinkPutc(ms, 0);
- metaSinkPutc(ms, 4);
- metaSinkPutUint32(ms, dir->gen);
+ metasinkputc(ms, DirGenEntry);
+ metasinkputc(ms, 0);
+ metasinkputc(ms, 4);
+ metasinkputuint32(ms, dir->gen);
}
- metaSinkEOR(ms);
+ metasinkeor(ms);
}
void
-plan9ToVacDir(VacDir *vd, Dir *dir, ulong entry, uvlong qid)
+plan9tovacdir(VacDir *vd, Dir *dir, ulong entry, uvlong qid)
{
memset(vd, 0, sizeof(VacDir));
- vd->elem = vtStrDup(dir->name);
+ vd->elem = vtstrdup(dir->name);
vd->entry = entry;
vd->qid = qid;
- vd->uid = vtStrDup(dir->uid);
- vd->gid = vtStrDup(dir->gid);
- vd->mid = vtStrDup(dir->muid);
+ vd->uid = vtstrdup(dir->uid);
+ vd->gid = vtstrdup(dir->gid);
+ vd->mid = vtstrdup(dir->muid);
vd->mtime = dir->mtime;
vd->mcount = 0;
vd->ctime = dir->mtime; /* ctime: not available on plan 9 */
@@ -944,7 +1134,7 @@ plan9ToVacDir(VacDir *vd, Dir *dir, ulong entry, uvlong qid)
void
-metaSinkEOR(MetaSink *k)
+metasinkeor(MetaSink *k)
{
uchar *p;
int o, n;
@@ -960,22 +1150,22 @@ metaSinkEOR(MetaSink *k)
k->rp = k->p;
k->nindex++;
if(k->nindex == k->maxindex)
- metaSinkFlush(k);
+ metasinkflush(k);
}
void
-metaSinkClose(MetaSink *k)
+metasinkclose(MetaSink *k)
{
- metaSinkFlush(k);
- sinkClose(k->sink);
+ metasinkflush(k);
+ sinkclose(k->sink);
}
void
-metaSinkFree(MetaSink *k)
+metasinkfree(MetaSink *k)
{
- sinkFree(k->sink);
- vtMemFree(k->buf);
- vtMemFree(k);
+ sinkfree(k->sink);
+ vtfree(k->buf);
+ vtfree(k);
}
static void
diff --git a/src/cmd/vac/vac.h b/src/cmd/vac/vac.h
index 549c441c..28e4706d 100644
--- a/src/cmd/vac/vac.h
+++ b/src/cmd/vac/vac.h
@@ -1,4 +1,4 @@
-typedef struct VacFS VacFS;
+typedef struct VacFs VacFs;
typedef struct VacDir VacDir;
typedef struct VacFile VacFile;
typedef struct VacDirEnum VacDirEnum;
@@ -6,7 +6,8 @@ typedef struct VacDirEnum VacDirEnum;
/*
* Mode bits
*/
-enum {
+enum
+{
ModeOtherExec = (1<<0),
ModeOtherWrite = (1<<1),
ModeOtherRead = (1<<2),
@@ -30,7 +31,8 @@ enum {
ModeSnapshot = (1<<20), /* read only snapshot */
};
-enum {
+enum
+{
MetaMagic = 0x5656fc79,
MetaHeaderSize = 12,
MetaIndexSize = 4,
@@ -38,14 +40,16 @@ enum {
DirMagic = 0x1c4d9072,
};
-enum {
+enum
+{
DirPlan9Entry = 1, /* not valid in version >= 9 */
DirNTEntry, /* not valid in version >= 9 */
DirQidSpaceEntry,
DirGenEntry, /* not valid in version >= 9 */
};
-struct VacDir {
+struct VacDir
+{
char *elem; /* path element */
ulong entry; /* entry in directory for data */
ulong gen; /* generation of data entry */
@@ -69,58 +73,67 @@ struct VacDir {
ulong p9version;
/* sub space of qid */
- int qidSpace;
- uvlong qidOffset; /* qid offset */
- uvlong qidMax; /* qid maximum */
+ int qidspace;
+ uvlong qidoffset; /* qid offset */
+ uvlong qidmax; /* qid maximum */
};
-VacFS *vfsOpen(VtSession *z, char *file, int readOnly, long ncache);
-VacFS *vfsCreate(VtSession *z, int bsize, long ncache);
-int vfsGetBlockSize(VacFS*);
-int vfsIsReadOnly(VacFS*);
-VacFile *vfsGetRoot(VacFS*);
-long vfsGetCacheSize(VacFS*);
-int vfsSetCacheSize(VacFS*, long);
-int vfsSnapshot(VacFS*, char *src, char *dst);
-int vfsSync(VacFS*);
-int vfsClose(VacFS*);
-int vfsGetScore(VacFS*, uchar score[VtScoreSize]);
+struct VacFs
+{
+ int ref;
+ uchar score[VtScoreSize];
+ VacFile *root;
+ VtConn *z;
+ int mode;
+ int bsize;
+ uvlong qid;
+ VtCache *cache;
+};
+
+VacFs *vacfsopen(VtConn *z, char *file, int mode, int ncache);
+VacFs *vacfsopenscore(VtConn *z, u8int *score, int mode, int ncache);
+VacFs *vacfscreate(VtConn *z, int bsize, int ncache);
+void vacfsclose(VacFs *fs);
+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*);
+ * VacFs *vfsSnapshot(VacFs*, char *src);
+ * int vfsGraft(VacFs*, char *name, VacFs*);
*/
-VacFile *vfOpen(VacFS*, char *path);
-VacFile *vfCreate(VacFile*, char *elem, ulong perm, char *user);
-VacFile *vfWalk(VacFile*, char *elem);
-int vfRemove(VacFile*, char*);
-int vfRead(VacFile*, void *, int n, vlong offset);
-int vfWrite(VacFile*, void *, int n, vlong offset, char *user);
-int vfReadPacket(VacFile*, Packet**, vlong offset);
-int vfWritePacket(VacFile*, Packet*, vlong offset, char *user);
-uvlong vfGetId(VacFile*);
-ulong vfGetMcount(VacFile*);
-int vfIsDir(VacFile*);
-int vfGetBlockScore(VacFile*, ulong bn, uchar score[VtScoreSize]);
-int vfGetSize(VacFile*, uvlong *size);
-int vfGetDir(VacFile*, VacDir*);
-int vfSetDir(VacFile*, VacDir*);
-int vfGetVtEntry(VacFile*, VtEntry*);
-VacFile *vfGetParent(VacFile*);
-int vfSync(VacFile*);
-VacFile *vfIncRef(VacFile*);
-void vfDecRef(VacFile*);
-VacDirEnum *vfDirEnum(VacFile*);
-int vfIsRoot(VacFile *vf);
+VacFile *vacfileopen(VacFs *fs, char *path);
+VacFile *vacfilecreate(VacFile *file, char *elem, ulong perm, char *muid);
+VacFile *vacfilewalk(VacFile *file, char *elem);
+int vacfileremove(VacFile *file, char *muid);
+int vacfileread(VacFile *file, void *buf, int n, vlong offset);
+int vacfileblockscore(VacFile *file, u32int, u8int*);
+int vacfilewrite(VacFile *file, void *buf, int n, vlong offset, char *muid);
+int vacfilereadpacket(VacFile *file, Packet **pp, vlong offset);
+int vacfilewritepacket(VacFile *file, Packet *p, vlong offset, char *muid);
+uvlong vacfilegetid(VacFile *file);
+ulong vacfilegetmcount(VacFile *file);
+int vacfileisdir(VacFile *file);
+int vacfileisroot(VacFile *file);
+int vacfilegetblocksize(VacFile *file, u32int bn, u8int *score);
+int vacfilegetsize(VacFile *file, uvlong *size);
+int vacfilegetdir(VacFile *file, VacDir *dir);
+int vacfilesetdir(VacFile *file, VacDir *dir, char *muid);
+int vacfilegetvtentry(VacFile *file, VtEntry *entry);
+VacFile *vacfilegetparent(VacFile *file);
+int vacfilesync(VacFile*);
+VacFile *vacfileincref(VacFile*);
+int vacfiledecref(VacFile*);
+
+void vdcleanup(VacDir *dir);
+void vdcopy(VacDir *dst, VacDir *src);
-void vdCleanup(VacDir *dir);
-void vdCopy(VacDir *dst, VacDir *src);
-VacDirEnum *vdeOpen(VacFS*, char *path);
-int vdeRead(VacDirEnum*, VacDir *, int n);
-void vdeFree(VacDirEnum*);
+VacDirEnum *vdeopen(VacFile*);
+int vderead(VacDirEnum*, VacDir *);
+void vdeclose(VacDirEnum*);
diff --git a/src/cmd/vac/vtdump.c b/src/cmd/vac/vtdump.c
index 963e4689..daabedc6 100644
--- a/src/cmd/vac/vtdump.c
+++ b/src/cmd/vac/vtdump.c
@@ -24,20 +24,19 @@ int cmp;
int all;
int find;
uchar fscore[VtScoreSize];
-VtSession *z;
+VtConn *z;
-int vtGetUint16(uchar *p);
-ulong vtGetUint32(uchar *p);
-uvlong vtGetUint48(uchar *p);
+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(VtRoot*, uchar *score, char *file);
-int dumpDir(Source*, int indent);
+void readroot(VtRoot*, uchar *score, char *file);
+int dumpdir(Source*, int indent);
void
-main(int argc, char *argv[])
+threadmain(int argc, char *argv[])
{
- char *host = nil;
+ char *host = nil, *pref;
uchar score[VtScoreSize];
Source source;
uchar buf[VtMaxLumpSize];
@@ -54,7 +53,7 @@ main(int argc, char *argv[])
case 'f':
find++;
p = ARGF();
- if(p == nil || !parseScore(fscore, p, strlen(p)))
+ if(p == nil || vtparsescore(p, &pref, fscore) < 0 || !pref || strcmp(pref, "vac") != 0)
usage();
break;
case 'a':
@@ -62,46 +61,33 @@ main(int argc, char *argv[])
break;
}ARGEND
- vtAttach();
-
- bout = vtMemAllocZ(sizeof(Biobuf));
+ bout = vtmallocz(sizeof(Biobuf));
Binit(bout, 1, OWRITE);
if(argc > 1)
usage();
- vtAttach();
-
- fmtinstall('V', vtScoreFmt);
- fmtinstall('R', vtErrFmt);
+ fmtinstall('V', vtscorefmt);
+ fmtinstall('H', encodefmt);
- z = vtDial(host, 0);
+ z = vtdial(host);
if(z == nil)
- vtFatal("could not connect to server: %s", vtGetError());
+ sysfatal("could not connect to server: %r");
- if(!vtConnect(z, 0))
- sysfatal("vtConnect: %r");
+ if(vtconnect(z) < 0)
+ sysfatal("vtconnect: %r");
- readRoot(&root, score, argv[0]);
- ver = root.version;
- bsize = root.blockSize;
+ readroot(&root, score, argv[0]);
+ bsize = root.blocksize;
if(!find) {
Bprint(bout, "score: %V\n", score);
- Bprint(bout, "version: %d\n", ver);
Bprint(bout, "name: %s\n", root.name);
Bprint(bout, "type: %s\n", root.type);
Bprint(bout, "bsize: %d\n", bsize);
Bprint(bout, "prev: %V\n", root.prev);
}
- switch(ver) {
- default:
- sysfatal("unknown version");
- case VtRootVersion:
- break;
- }
-
- n = vtRead(z, root.score, VtDirType, buf, bsize);
+ n = vtread(z, root.score, VtDirType, buf, bsize);
if(n < 0)
sysfatal("could not read root dir");
@@ -115,17 +101,16 @@ main(int argc, char *argv[])
source.depth = 0;
source.size = n;
- dumpDir(&source, 0);
+ dumpdir(&source, 0);
Bterm(bout);
- vtClose(z);
- vtDetach();
- exits(0);
+ vthangup(z);
+ threadexitsall(0);
}
void
-sourcePrint(Source *s, int indent, int entry)
+sourceprint(Source *s, int indent, int entry)
{
int i;
uvlong size;
@@ -165,11 +150,11 @@ parse(Source *s, uchar *p)
VtEntry dir;
memset(s, 0, sizeof(*s));
- if(!vtEntryUnpack(&dir, p, 0))
- return 0;
+ if(vtentryunpack(&dir, p, 0) < 0)
+ return -1;
if(!(dir.flags & VtEntryActive))
- return 1;
+ return 0;
s->active = 1;
s->gen = dir.gen;
@@ -177,21 +162,23 @@ parse(Source *s, uchar *p)
s->dsize = dir.size;
s->size = dir.size;
memmove(s->score, dir.score, VtScoreSize);
- if(dir.flags & VtEntryDir)
+ if((dir.type&~VtTypeDepthMask) == VtDirType)
s->dir = 1;
- s->depth = dir.depth;
- return 1;
-
+fprint(2, "sdir %d type %d %.*H\n", s->dir, dir.type, VtEntrySize, p);
+ s->depth = dir.type&VtTypeDepthMask;
+ return 0;
}
int
-sourceRead(Source *s, ulong block, uchar *p, int n)
+sourceread(Source *s, ulong block, uchar *p, int n)
{
- uchar buf[VtMaxLumpSize];
+ uchar *buf;
uchar score[VtScoreSize];
int i, nn, np, type;
int elem[VtPointerDepth];
+ buf = vtmalloc(VtMaxLumpSize);
+
memmove(score, s->score, VtScoreSize);
np = s->psize/VtScoreSize;
@@ -202,17 +189,17 @@ sourceRead(Source *s, ulong block, uchar *p, int n)
assert(block == 0);
for(i=s->depth-1; i>=0; i--) {
- nn = vtRead(z, score, VtPointerType0+i, buf, s->psize);
- if(nn < 0)
- return -1;
-
- if(!vtSha1Check(score, buf, nn)) {
- vtSetError("vtSha1Check failed on root block");
+ nn = vtread(z, score, (s->dir ? VtDirType : VtDataType)+1+i, buf, s->psize);
+ if(nn < 0){
+fprint(2, "vtread %V %d: %r\n", score, (s->dir ? VtDirType : VtDataType)+1+i);
+ free(buf);
return -1;
}
- if((elem[i]+1)*VtScoreSize > nn)
+ if((elem[i]+1)*VtScoreSize > nn){
+ free(buf);
return 0;
+ }
memmove(score, buf + elem[i]*VtScoreSize, VtScoreSize);
}
@@ -221,20 +208,20 @@ sourceRead(Source *s, ulong block, uchar *p, int n)
else
type = VtDataType;
- nn = vtRead(z, score, type, p, n);
- if(nn < 0)
- return -1;
-
- if(!vtSha1Check(score, p, nn)) {
- vtSetError("vtSha1Check failed on root block");
+ nn = vtread(z, score, type, p, n);
+ if(nn < 0){
+fprint(2, "vtread %V %d: %r\n", score, type);
+abort();
+ free(buf);
return -1;
}
+ free(buf);
return nn;
}
void
-dumpFileContents(Source *s)
+dumpfilecontents(Source *s)
{
int nb, lb, i, n;
uchar buf[VtMaxLumpSize];
@@ -243,9 +230,9 @@ dumpFileContents(Source *s)
lb = s->size%s->dsize;
for(i=0; i<nb; i++) {
memset(buf, 0, s->dsize);
- n = sourceRead(s, i, buf, s->dsize);
+ n = sourceread(s, i, buf, s->dsize);
if(n < 0) {
- fprint(2, "could not read block: %d: %s\n", i, vtGetError());
+ fprint(2, "could not read block: %d: %r\n", i);
continue;
}
if(i < nb-1)
@@ -256,42 +243,45 @@ dumpFileContents(Source *s)
}
void
-dumpFile(Source *s, int indent)
+dumpfile(Source *s, int indent)
{
int nb, i, j, n;
- uchar buf[VtMaxLumpSize];
+ uchar *buf;
uchar score[VtScoreSize];
+ buf = vtmalloc(VtMaxLumpSize);
nb = (s->size + s->dsize - 1)/s->dsize;
for(i=0; i<nb; i++) {
memset(buf, 0, s->dsize);
- n = sourceRead(s, i, buf, s->dsize);
+ n = sourceread(s, i, buf, s->dsize);
if(n < 0) {
- fprint(2, "could not read block: %d: %s\n", i, vtGetError());
+ fprint(2, "could not read block: %d: %r\n", i);
continue;
}
for(j=0; j<indent; j++)
Bprint(bout, " ");
- vtSha1(score, buf, n);
+ sha1(buf, n, score, nil);
Bprint(bout, "%4d: size: %ud: %V\n", i, n, score);
}
+ vtfree(buf);
}
int
-dumpDir(Source *s, int indent)
+dumpdir(Source *s, int indent)
{
int pb, ne, nb, i, j, n, entry;
- uchar buf[VtMaxLumpSize];
Source ss;
+ uchar *buf;
+ buf = vtmalloc(VtMaxLumpSize);
pb = s->dsize/VtEntrySize;
ne = pb*(s->size/s->dsize) + (s->size%s->dsize)/VtEntrySize;
nb = (s->size + s->dsize - 1)/s->dsize;
for(i=0; i<nb; i++) {
memset(buf, 0, s->dsize);
- n = sourceRead(s, i, buf, s->dsize);
+ n = sourceread(s, i, buf, s->dsize);
if(n < 0) {
- fprint(2, "could not read block: %d: %s\n", i, vtGetError());
+ fprint(2, "could not read block: %d: %r\n", i);
continue;
}
for(j=0; j<pb; j++) {
@@ -301,63 +291,40 @@ dumpDir(Source *s, int indent)
parse(&ss, buf + j * VtEntrySize);
if(!find)
- sourcePrint(&ss, indent, entry);
+ sourceprint(&ss, indent, entry);
else if(memcmp(ss.score, fscore, VtScoreSize) == 0) {
- dumpFileContents(&ss);
- return 0;
+ dumpfilecontents(&ss);
+ free(buf);
+ return -1;
}
if(ss.dir) {
- if(!dumpDir(&ss, indent+1))
- return 0;
+ if(dumpdir(&ss, indent+1) < 0){
+ free(buf);
+ return -1;
+ }
} else if(all)
- dumpFile(&ss, indent+1);
+ dumpfile(&ss, indent+1);
}
}
- return 1;
+ free(buf);
+ return 0;
}
void
usage(void)
{
fprint(2, "%s: [file]\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;
+ threadexits("usage");
}
void
-readRoot(VtRoot *root, uchar *score, char *file)
+readroot(VtRoot *root, uchar *score, char *file)
{
int fd;
- uchar buf[VtRootSize];
- int i, n, nn;
+ char *pref;
+ char buf[VtRootSize];
+ int n, nn;
if(file == 0)
fd = 0;
@@ -369,23 +336,17 @@ readRoot(VtRoot *root, uchar *score, char *file)
n = readn(fd, buf, sizeof(buf)-1);
if(n < 0)
sysfatal("read failed: %r\n");
- buf[n] = 0;
+ if(n==0 || buf[n-1] != '\n')
+ sysfatal("not a root file");
+ buf[n-1] = 0;
close(fd);
- for(i=0; i<n; i++) {
- if(!parseScore(score, (char*)(buf+i), n-i))
- continue;
- nn = vtRead(z, score, VtRootType, buf, VtRootSize);
- if(nn >= 0) {
- if(nn != VtRootSize)
- sysfatal("vtRead on root too short");
- if(!vtSha1Check(score, buf, VtRootSize))
- sysfatal("vtSha1Check failed on root block");
- if(!vtRootUnpack(root, buf))
- sysfatal("could not parse root: %r");
- return;
- }
+ if(vtparsescore(buf, &pref, score) < 0){
+ sysfatal("not a root file");
}
-
- sysfatal("could not find root");
+ nn = vtread(z, score, VtRootType, buf, VtRootSize);
+ if(nn < 0)
+ sysfatal("cannot read root %V", score);
+ if(vtrootunpack(root, buf) < 0)
+ sysfatal("cannot parse root: %r");
}