#include "stdinc.h" #include "vac.h" #include "dat.h" #include "fns.h" static char EBadVacFormat[] = "bad format for vac file"; static VacFS * vfsAlloc(VtSession *z, int bsize, long ncache) { VacFS *fs; fs = vtMemAllocZ(sizeof(VacFS)); fs->ref = 1; fs->z = z; fs->bsize = bsize; fs->cache = cacheAlloc(z, bsize, ncache); return fs; } static int readScore(int fd, uchar score[VtScoreSize]) { char buf[44]; int i, n, c; n = readn(fd, buf, sizeof(buf)); if(n < sizeof(buf)) { vtSetError("short read"); return 0; } if(strncmp(buf, "vac:", 4) != 0) { vtSetError("not a vac file"); return 0; } memset(score, 0, VtScoreSize); for(i=4; 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; } return 1; } VacFS * vfsOpen(VtSession *z, char *file, int readOnly, long ncache) { VacFS *fs; int n, fd; VtRoot rt; uchar score[VtScoreSize], buf[VtRootSize]; VacFile *root; fd = open(file, OREAD); if(fd < 0) { vtOSError(); return nil; } if(!readScore(fd, score)) { close(fd); return nil; } close(fd); 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"); return nil; } if(!vtRootUnpack(&rt, buf)) return nil; if(strcmp(rt.type, "vac") != 0) { vtSetError("not a vac root"); return nil; } fs = vfsAlloc(z, rt.blockSize, ncache); memmove(fs->score, score, VtScoreSize); fs->readOnly = readOnly; root = vfRoot(fs, rt.score); if(root == nil) goto Err; fs->root = root; return fs; Err: if(root) vfDecRef(root); vfsClose(fs); return nil; } VacFS * vacFsCreate(VtSession *z, int bsize, long ncache) { VacFS *fs; fs = vfsAlloc(z, bsize, ncache); return fs; } int vfsIsReadOnly(VacFS *fs) { return fs->readOnly != 0; } VacFile * vfsGetRoot(VacFS *fs) { return vfIncRef(fs->root); } int vfsGetBlockSize(VacFS *fs) { return fs->bsize; } int vfsGetScore(VacFS *fs, uchar score[VtScoreSize]) { memmove(fs, score, VtScoreSize); return 1; } long vfsGetCacheSize(VacFS *fs) { return cacheGetSize(fs->cache); } int vfsSetCacheSize(VacFS *fs, long size) { return cacheSetSize(fs->cache, size); } int vfsSnapshot(VacFS *fs, char *src, char *dst) { USED(fs); USED(src); USED(dst); return 1; } int vfsSync(VacFS*) { return 1; } int vfsClose(VacFS *fs) { if(fs->root) vfDecRef(fs->root); fs->root = nil; cacheCheck(fs->cache); cacheFree(fs->cache); memset(fs, 0, sizeof(VacFS)); vtMemFree(fs); return 1; }