Exemplo n.º 1
0
static int
deeFill(DirEntryEnum *dee)
{
	int i, n;
	Source *meta, *source;
	MetaBlock mb;
	MetaEntry me;
	File *f;
	Block *b;
	DirEntry *de;

	/* clean up first */
	for(i=dee->i; i<dee->n; i++)
		deCleanup(dee->buf+i);
	vtMemFree(dee->buf);
	dee->buf = nil;
	dee->i = 0;
	dee->n = 0;

	f = dee->file;

	source = f->source;
	meta = f->msource;

	b = sourceBlock(meta, dee->boff, OReadOnly);
	if(b == nil)
		goto Err;
	if(!mbUnpack(&mb, b->data, meta->dsize))
		goto Err;

	n = mb.nindex;
	dee->buf = vtMemAlloc(n * sizeof(DirEntry));

	for(i=0; i<n; i++){
		de = dee->buf + i;
		meUnpack(&me, &mb, i);
		if(!deUnpack(de, &me))
			goto Err;
		dee->n++;
		if(!(de->mode & ModeDir))
		if(!dirEntrySize(source, de->entry, de->gen, &de->size))
			goto Err;
	}
	dee->boff++;
	blockPut(b);
	return 1;
Err:
	blockPut(b);
	return 0;
}
Exemplo n.º 2
0
int
metaentrygen(void *v, Block *b, int o, Tnode **tp)
{
    Tnode *t;
    MetaBlock *mb;
    MetaEntry me;

    mb = v;
    if(o >= mb->nindex)
        return -1;
    meUnpack(&me, mb, o);

    t = stringnode("MetaEntry %d bytes", mb->size);
    t->kid = mallocz(sizeof(t->kid[0])*1, 1);
    t->kid[0] = initxdirentry(&me);
    t->nkid = 1;
    *tp = t;
    return 1;
}
Exemplo n.º 3
0
void
mbDelete(MetaBlock *mb, int i)
{
	uchar *p;
	int n;
	MetaEntry me;

	assert(i < mb->nindex);
	meUnpack(&me, mb, i);
	memset(me.p, 0, me.size);

	if(me.p - mb->buf + me.size == mb->size)
		mb->size -= me.size;
	else
		mb->free += me.size;

	p = mb->buf + MetaHeaderSize + i*MetaIndexSize;
	n = (mb->nindex-i-1)*MetaIndexSize;
	memmove(p, p+MetaIndexSize, n);
	memset(p+n, 0, MetaIndexSize);
	mb->nindex--;
}
Exemplo n.º 4
0
int
mbSearch(MetaBlock *mb, char *elem, int *ri, MetaEntry *me)
{
	int i;
	int b, t, x;
if(0)fprint(2, "mbSearch %s\n", elem);

	/* binary search within block */
	b = 0;
	t = mb->nindex;
	while(b < t){
		i = (b+t)>>1;
		meUnpack(me, mb, i);

		if(mb->botch)
			x = meCmpOld(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));

	vtSetError(ENoFile);
	return 0;
}
Exemplo n.º 5
0
File *
fileRoot(Source *r)
{
	Block *b;
	Source *r0, *r1, *r2;
	MetaBlock mb;
	MetaEntry me;
	File *root, *mr;
	Fs *fs;

	b = nil;
	root = nil;
	mr = nil;
	r1 = nil;
	r2 = nil;

	fs = r->fs;
	if(!sourceLock(r, -1))
		return nil;
	r0 = sourceOpen(r, 0, fs->mode, 0);
	if(r0 == nil)
		goto Err;
	r1 = sourceOpen(r, 1, fs->mode, 0);
	if(r1 == nil)
		goto Err;
	r2 = sourceOpen(r, 2, fs->mode, 0);
	if(r2 == nil)
		goto Err;

	mr = fileAlloc(fs);
	mr->msource = r2;
	r2 = nil;

	root = fileAlloc(fs);
	root->boff = 0;
	root->up = mr;
	root->source = r0;
	r0->file = root;			/* point back to source */
	r0 = nil;
	root->msource = r1;
	r1 = nil;

	mr->down = root;

	if(!sourceLock(mr->msource, -1))
		goto Err;
	b = sourceBlock(mr->msource, 0, OReadOnly);
	sourceUnlock(mr->msource);
	if(b == nil)
		goto Err;

	if(!mbUnpack(&mb, b->data, mr->msource->dsize))
		goto Err;

	meUnpack(&me, &mb, 0);
	if(!deUnpack(&root->dir, &me))
		goto Err;
	blockPut(b);
	sourceUnlock(r);
	fileRAccess(root);

	return root;
Err:
	blockPut(b);
	if(r0)
		sourceClose(r0);
	if(r1)
		sourceClose(r1);
	if(r2)
		sourceClose(r2);
	if(mr)
		fileFree(mr);
	if(root)
		fileFree(root);
	sourceUnlock(r);

	return nil;
}
Exemplo n.º 6
0
/*
 * Walk the source tree making sure that the BtData
 * sources containing directory entries are okay.
 */
static void
chkDir(Fsck *chk, char *name, Source *source, Source *meta)
{
	int i;
	u32int a1, a2, nb, o;
	char *s, *nn;
	uchar *bm;
	Block *b, *bb;
	DirEntry de;
	Entry e1, e2;
	MetaBlock mb;
	MetaEntry me;
	Source *r, *mr;

	if(!chk->useventi && globalToLocal(source->score)==NilBlock &&
	    globalToLocal(meta->score)==NilBlock)
		return;

	if(!sourceLock2(source, meta, OReadOnly)){
		warn(chk, "could not lock sources for %s: %R", name);
		return;
	}
	if(!sourceGetEntry(source, &e1) || !sourceGetEntry(meta, &e2)){
		warn(chk, "could not load entries for %s: %R", name);
		return;
	}
	a1 = globalToLocal(e1.score);
	a2 = globalToLocal(e2.score);
	if((!chk->useventi && a1==NilBlock && a2==NilBlock)
	|| (getBit(chk->smap, a1) && getBit(chk->smap, a2))){
		sourceUnlock(source);
		sourceUnlock(meta);
		return;
	}
	setBit(chk->smap, a1);
	setBit(chk->smap, a2);

	bm = vtMemAllocZ(sourceGetDirSize(source)/8 + 1);

	nb = (sourceGetSize(meta) + meta->dsize - 1)/meta->dsize;
	for(o = 0; o < nb; o++){
		b = sourceBlock(meta, o, OReadOnly);
		if(b == nil){
			error(chk, "could not read block in meta file: %s[%ud]: %R",
				name, o);
			continue;
		}
if(0)		fprint(2, "source %V:%d block %d addr %d\n", source->score,
			source->offset, o, b->addr);
		if(b->addr != NilBlock && getBit(chk->errmap, b->addr))
			warn(chk, "previously reported error in block %ux is in %s",
				b->addr, name);

		if(!mbUnpack(&mb, b->data, meta->dsize)){
			error(chk, "could not unpack meta block: %s[%ud]: %R",
				name, o);
			blockPut(b);
			continue;
		}
		if(!chkMetaBlock(&mb)){
			error(chk, "bad meta block: %s[%ud]: %R", name, o);
			blockPut(b);
			continue;
		}
		s = nil;
		for(i=mb.nindex-1; i>=0; i--){
			meUnpack(&me, &mb, i);
			if(!deUnpack(&de, &me)){
				error(chk,
				  "could not unpack dir entry: %s[%ud][%d]: %R",
					name, o, i);
				continue;
			}
			if(s && strcmp(s, de.elem) <= 0)
				error(chk,
			   "dir entry out of order: %s[%ud][%d] = %s last = %s",
					name, o, i, de.elem, s);
			vtMemFree(s);
			s = vtStrDup(de.elem);
			nn = smprint("%s/%s", name, de.elem);
			if(nn == nil){
				error(chk, "out of memory");
				continue;
			}
			if(chk->printdirs)
				if(de.mode&ModeDir)
					chk->print("%s/\n", nn);
			if(chk->printfiles)
				if(!(de.mode&ModeDir))
					chk->print("%s\n", nn);
			if(!(de.mode & ModeDir)){
				r = openSource(chk, source, nn, bm, de.entry,
					de.gen, 0, &mb, i, b);
				if(r != nil){
					if(sourceLock(r, OReadOnly)){
						scanSource(chk, nn, r);
						sourceUnlock(r);
					}
					sourceClose(r);
				}
				deCleanup(&de);
				free(nn);
				continue;
			}

			r = openSource(chk, source, nn, bm, de.entry,
				de.gen, 1, &mb, i, b);
			if(r == nil){
				deCleanup(&de);
				free(nn);
				continue;
			}

			mr = openSource(chk, source, nn, bm, de.mentry,
				de.mgen, 0, &mb, i, b);
			if(mr == nil){
				sourceClose(r);
				deCleanup(&de);
				free(nn);
				continue;
			}

			if(!(de.mode&ModeSnapshot) || chk->walksnapshots)
				chkDir(chk, nn, r, mr);

			sourceClose(mr);
			sourceClose(r);
			deCleanup(&de);
			free(nn);
			deCleanup(&de);

		}
		vtMemFree(s);
		blockPut(b);
	}

	nb = sourceGetDirSize(source);
	for(o=0; o<nb; o++){
		if(getBit(bm, o))
			continue;
		r = sourceOpen(source, o, OReadOnly, 0);
		if(r == nil)
			continue;
		warn(chk, "non referenced entry in source %s[%d]", name, o);
		if((bb = sourceBlock(source, o/(source->dsize/VtEntrySize),
		    OReadOnly)) != nil){
			if(bb->addr != NilBlock){
				setBit(chk->errmap, bb->addr);
				chk->clre(chk, bb, o%(source->dsize/VtEntrySize));
				chk->nclre++;
			}
			blockPut(bb);
		}
		sourceClose(r);
	}

	sourceUnlock(source);
	sourceUnlock(meta);
	vtMemFree(bm);
}
Exemplo n.º 7
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;
}