Fs * fsOpen(char *file, VtSession *z, int32_t ncache, int mode) { int fd, m; uint8_t oscore[VtScoreSize]; Block *b, *bs; Disk *disk; Fs *fs; Super super; switch(mode){ default: vtSetError(EBadMode); return nil; case OReadOnly: m = OREAD; break; case OReadWrite: m = ORDWR; break; } fd = open(file, m); if(fd < 0){ vtSetError("open %s: %r", file); return nil; } bwatchInit(); disk = diskAlloc(fd); if(disk == nil){ vtSetError("diskAlloc: %R"); close(fd); return nil; } fs = vtMemAllocZ(sizeof(Fs)); fs->mode = mode; fs->name = vtStrDup(file); fs->blockSize = diskBlockSize(disk); fs->elk = vtLockAlloc(); fs->cache = cacheAlloc(disk, z, ncache, mode); if(mode == OReadWrite && z) fs->arch = archInit(fs->cache, disk, fs, z); fs->z = z; b = cacheLocal(fs->cache, PartSuper, 0, mode); if(b == nil) goto Err; if(!superUnpack(&super, b->data)){ blockPut(b); vtSetError("bad super block"); goto Err; } blockPut(b); fs->ehi = super.epochHigh; fs->elo = super.epochLow; //fprint(2, "%s: fs->ehi %d fs->elo %d active=%d\n", argv0, fs->ehi, fs->elo, super.active); fs->source = sourceRoot(fs, super.active, mode); if(fs->source == nil){ /* * Perhaps it failed because the block is copy-on-write. * Do the copy and try again. */ if(mode == OReadOnly || strcmp(vtGetError(), EBadRoot) != 0) goto Err; b = cacheLocalData(fs->cache, super.active, BtDir, RootTag, OReadWrite, 0); if(b == nil){ vtSetError("cacheLocalData: %R"); goto Err; } if(b->l.epoch == fs->ehi){ blockPut(b); vtSetError("bad root source block"); goto Err; } b = blockCopy(b, RootTag, fs->ehi, fs->elo); if(b == nil) goto Err; localToGlobal(super.active, oscore); super.active = b->addr; bs = cacheLocal(fs->cache, PartSuper, 0, OReadWrite); if(bs == nil){ blockPut(b); vtSetError("cacheLocal: %R"); goto Err; } superPack(&super, bs->data); blockDependency(bs, b, 0, oscore, nil); blockPut(b); blockDirty(bs); blockRemoveLink(bs, globalToLocal(oscore), BtDir, RootTag, 0); blockPut(bs); fs->source = sourceRoot(fs, super.active, mode); if(fs->source == nil){ vtSetError("sourceRoot: %R"); goto Err; } } //fprint(2, "%s: got fs source\n", argv0); vtRLock(fs->elk); fs->file = fileRoot(fs->source); fs->source->file = fs->file; /* point back */ vtRUnlock(fs->elk); if(fs->file == nil){ vtSetError("fileRoot: %R"); goto Err; } //fprint(2, "%s: got file root\n", argv0); if(mode == OReadWrite){ fs->metaFlush = periodicAlloc(fsMetaFlush, fs, 1000); fs->snap = snapInit(fs); } return fs; Err: fprint(2, "%s: fsOpen error\n", argv0); fsClose(fs); return nil; }
void main(int argc, char *argv[]) { int fd, force; Header h; ulong bn; Entry e; char *label = "vfs"; char *host = nil; char *score = nil; u32int root; Dir *d; force = 0; ARGBEGIN{ default: usage(); case 'b': bsize = unittoull(EARGF(usage())); if(bsize == ~0) usage(); break; case 'h': host = EARGF(usage()); break; case 'i': iso9660file = EARGF(usage()); iso9660off = atoi(EARGF(usage())); break; case 'l': label = EARGF(usage()); break; case 'v': score = EARGF(usage()); break; /* * This is -y instead of -f because flchk has a * (frequently used) -f option. I type flfmt instead * of flchk all the time, and want to make it hard * to reformat my file system accidentally. */ case 'y': force = 1; break; }ARGEND if(argc != 1) usage(); if(iso9660file && score) vtFatal("cannot use -i with -v"); vtAttach(); fmtinstall('V', scoreFmt); fmtinstall('R', vtErrFmt); fmtinstall('L', labelFmt); fd = open(argv[0], ORDWR); if(fd < 0) vtFatal("could not open file: %s: %r", argv[0]); buf = vtMemAllocZ(bsize); if(pread(fd, buf, bsize, HeaderOffset) != bsize) vtFatal("could not read fs header block: %r"); if(headerUnpack(&h, buf) && !force && !confirm("fs header block already exists; are you sure?")) goto Out; if((d = dirfstat(fd)) == nil) vtFatal("dirfstat: %r"); if(d->type == 'M' && !force && !confirm("fs file is mounted via devmnt (is not a kernel device); are you sure?")) goto Out; partition(fd, bsize, &h); headerPack(&h, buf); if(pwrite(fd, buf, bsize, HeaderOffset) < bsize) vtFatal("could not write fs header: %r"); disk = diskAlloc(fd); if(disk == nil) vtFatal("could not open disk: %r"); if(iso9660file) iso9660init(fd, &h, iso9660file, iso9660off); /* zero labels */ memset(buf, 0, bsize); for(bn = 0; bn < diskSize(disk, PartLabel); bn++) blockWrite(PartLabel, bn); if(iso9660file) iso9660labels(disk, buf, blockWrite); if(score) root = ventiRoot(host, score); else{ rootMetaInit(&e); root = rootInit(&e); } superInit(label, root, vtZeroScore); diskFree(disk); if(score == nil) topLevel(argv[0]); Out: vtDetach(); exits(0); }