| #include "stdinc.h" |
| #include "vac.h" |
| #include "dat.h" |
| #include "fns.h" |
| |
| #define debug 0 |
| |
| static char EBadVacFormat[] = "bad format for vac file"; |
| |
| static VacFs * |
| vacfsalloc(VtConn *z, int bsize, int ncache, int mode) |
| { |
| VacFs *fs; |
| |
| fs = vtmallocz(sizeof(VacFs)); |
| fs->ref = 1; |
| fs->z = z; |
| fs->bsize = bsize; |
| fs->cache = vtcachealloc(z, bsize, ncache); |
| return fs; |
| } |
| |
| static int |
| readscore(int fd, uchar score[VtScoreSize]) |
| { |
| char buf[45], *pref; |
| int n; |
| |
| n = readn(fd, buf, sizeof(buf)-1); |
| if(n < sizeof(buf)-1) { |
| werrstr("short read"); |
| return -1; |
| } |
| buf[n] = 0; |
| |
| if(vtparsescore(buf, &pref, score) < 0){ |
| werrstr(EBadVacFormat); |
| return -1; |
| } |
| if(pref==nil || strcmp(pref, "vac") != 0) { |
| werrstr("not a vac file"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| VacFs* |
| vacfsopen(VtConn *z, char *file, int mode, int ncache) |
| { |
| int fd; |
| uchar score[VtScoreSize]; |
| |
| fd = open(file, OREAD); |
| if(fd < 0) |
| return nil; |
| |
| if(readscore(fd, score) < 0){ |
| close(fd); |
| return nil; |
| } |
| close(fd); |
| |
| 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){ |
| werrstr("vtread on root too short"); |
| return nil; |
| } |
| |
| if(vtrootunpack(&rt, buf) < 0) |
| return nil; |
| |
| if(strcmp(rt.type, "vac") != 0) { |
| werrstr("not a vac root"); |
| return nil; |
| } |
| |
| fs = vacfsalloc(z, rt.blocksize, ncache, mode); |
| memmove(fs->score, score, VtScoreSize); |
| fs->mode = mode; |
| |
| memmove(e.score, rt.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; |
| if(debug) |
| fprint(2, "r %p\n", r); |
| root = _vacfileroot(fs, r); |
| if(debug) |
| fprint(2, "root %p\n", root); |
| vtfileclose(r); |
| if(root == nil) |
| goto Err; |
| fs->root = root; |
| return fs; |
| Err: |
| if(root) |
| vacfiledecref(root); |
| vacfsclose(fs); |
| return nil; |
| } |
| |
| VacFs * |
| vacfscreate(VtConn *z, int bsize, int ncache) |
| { |
| return vacfsalloc(z, bsize, ncache, VtORDWR); |
| } |
| |
| int |
| vacfsmode(VacFs *fs) |
| { |
| return fs->mode; |
| } |
| |
| VacFile* |
| vacfsgetroot(VacFs *fs) |
| { |
| return vacfileincref(fs->root); |
| } |
| |
| int |
| vacfsgetblocksize(VacFs *fs) |
| { |
| return fs->bsize; |
| } |
| |
| int |
| vacfsgetscore(VacFs *fs, u8int *score) |
| { |
| memmove(score, fs->score, VtScoreSize); |
| return 0; |
| } |
| |
| int |
| _vacfsnextqid(VacFs *fs, uvlong *qid) |
| { |
| ++fs->qid; |
| *qid = fs->qid; |
| return 0; |
| } |
| |
| int |
| vacfssync(VacFs *fs) |
| { |
| return 0; |
| } |
| |
| void |
| vacfsclose(VacFs *fs) |
| { |
| if(fs->root) |
| vacfiledecref(fs->root); |
| fs->root = nil; |
| vtcachefree(fs->cache); |
| vtfree(fs); |
| } |
| |