bool CipherFileIO::writeOneBlock(const IORequest &req) { if (haveHeader && fsConfig->reverseEncryption) { VLOG(1) << "writing to a reverse mount with per-file IVs is not implemented"; return false; } int bs = blockSize(); off_t blockNum = req.offset / bs; if (haveHeader && fileIV == 0) initHeader(); bool ok; if (req.dataLen != bs) { ok = streamWrite(req.data, (int)req.dataLen, blockNum ^ fileIV); } else { ok = blockWrite(req.data, (int)req.dataLen, blockNum ^ fileIV); } if (ok) { if (haveHeader) { IORequest tmpReq = req; tmpReq.offset += HEADER_SIZE; ok = base->write(tmpReq); } else ok = base->write(req); } else { VLOG(1) << "encodeBlock failed for block " << blockNum << ", size " << req.dataLen; ok = false; } return ok; }
static u32int rootInit(Entry *e) { ulong addr; u32int tag; tag = tagGen(); addr = blockAlloc(BtDir, tag); memset(buf, 0, bsize); /* root meta data is in the third entry */ entryPack(e, buf, 2); entryInit(e); e->flags |= VtEntryDir; entryPack(e, buf, 0); entryInit(e); entryPack(e, buf, 1); blockWrite(PartData, addr); entryInit(e); e->flags |= VtEntryLocal|VtEntryDir; e->size = VtEntrySize*3; e->tag = tag; localToGlobal(addr, e->score); addr = blockAlloc(BtDir, RootTag); memset(buf, 0, bsize); entryPack(e, buf, 0); blockWrite(PartData, addr); return addr; }
static void rootMetaInit(Entry *e) { u32int addr; u32int tag; DirEntry de; MetaBlock mb; MetaEntry me; memset(&de, 0, sizeof(de)); de.elem = vtStrDup("root"); de.entry = 0; de.gen = 0; de.mentry = 1; de.mgen = 0; de.size = 0; de.qid = qid++; de.uid = vtStrDup("adm"); de.gid = vtStrDup("adm"); de.mid = vtStrDup("adm"); de.mtime = time(0); de.mcount = 0; de.ctime = time(0); de.atime = time(0); de.mode = ModeDir | 0555; tag = tagGen(); addr = blockAlloc(BtData, tag); /* build up meta block */ memset(buf, 0, bsize); mbInit(&mb, buf, bsize, bsize/100); me.size = deSize(&de); me.p = mbAlloc(&mb, me.size); assert(me.p != nil); dePack(&de, &me); mbInsert(&mb, 0, &me); mbPack(&mb); blockWrite(PartData, addr); deCleanup(&de); /* build up entry for meta block */ entryInit(e); e->flags |= VtEntryLocal; e->size = bsize; e->tag = tag; localToGlobal(addr, e->score); }
static void superInit(char *label, u32int root, uchar score[VtScoreSize]) { Super s; memset(buf, 0, bsize); memset(&s, 0, sizeof(s)); s.version = SuperVersion; s.epochLow = 1; s.epochHigh = 1; s.qid = qid; s.active = root; s.next = NilBlock; s.current = NilBlock; strecpy(s.name, s.name+sizeof(s.name), label); memmove(s.last, score, VtScoreSize); superPack(&s, buf); blockWrite(PartSuper, 0); }
static u32int blockAlloc(int type, u32int tag) { static u32int addr; Label l; int lpb; lpb = bsize/LabelSize; blockRead(PartLabel, addr/lpb); if(!labelUnpack(&l, buf, addr % lpb)) vtFatal("bad label: %r"); if(l.state != BsFree) vtFatal("want to allocate block already in use"); l.epoch = 1; l.epochClose = ~(u32int)0; l.type = type; l.state = BsAlloc; l.tag = tag; labelPack(&l, buf, addr % lpb); blockWrite(PartLabel, addr/lpb); return addr++; }
void superWrite(Block* b, Super* super, int forceWrite) { superPack(super, b->data); blockDirty(b); if(forceWrite){ while(!blockWrite(b, Waitlock)){ /* this should no longer happen */ fprint(2, "%s: could not write super block; " "waiting 10 seconds\n", argv0); sleep(10*1000); } while(b->iostate != BioClean && b->iostate != BioDirty){ assert(b->iostate == BioWriting); vtSleep(b->ioready); } /* * it's okay that b might still be dirty. * that means it got written out but with an old root pointer, * but the other fields went out, and those are the ones * we really care about. (specifically, epochHigh; see fsSnapshot). */ } }
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); }
static u32int ventiRoot(char *host, char *s) { int i, n; uchar score[VtScoreSize]; u32int addr, tag; DirEntry de; MetaBlock mb; MetaEntry me; Entry e; VtRoot root; if(!parseScore(score, s)) vtFatal("bad score '%s'", s); if((z = vtDial(host, 0)) == nil || !vtConnect(z, nil)) vtFatal("connect to venti: %R"); tag = tagGen(); addr = blockAlloc(BtDir, tag); ventiRead(score, VtRootType); if(!vtRootUnpack(&root, buf)) vtFatal("corrupted root: vtRootUnpack"); n = ventiRead(root.score, VtDirType); /* * Fossil's vac archives start with an extra layer of source, * but vac's don't. */ if(n <= 2*VtEntrySize){ if(!entryUnpack(&e, buf, 0)) vtFatal("bad root: top entry"); n = ventiRead(e.score, VtDirType); } /* * There should be three root sources (and nothing else) here. */ for(i=0; i<3; i++){ if(!entryUnpack(&e, buf, i) || !(e.flags&VtEntryActive) || e.psize < 256 || e.dsize < 256) vtFatal("bad root: entry %d", i); fprint(2, "%V\n", e.score); } if(n > 3*VtEntrySize) vtFatal("bad root: entry count"); blockWrite(PartData, addr); /* * Maximum qid is recorded in root's msource, entry #2 (conveniently in e). */ ventiRead(e.score, VtDataType); if(!mbUnpack(&mb, buf, bsize)) vtFatal("bad root: mbUnpack"); meUnpack(&me, &mb, 0); if(!deUnpack(&de, &me)) vtFatal("bad root: dirUnpack"); if(!de.qidSpace) vtFatal("bad root: no qidSpace"); qid = de.qidMax; /* * Recreate the top layer of source. */ entryInit(&e); e.flags |= VtEntryLocal|VtEntryDir; e.size = VtEntrySize*3; e.tag = tag; localToGlobal(addr, e.score); addr = blockAlloc(BtDir, RootTag); memset(buf, 0, bsize); entryPack(&e, buf, 0); blockWrite(PartData, addr); return addr; }