133 lines · 2.5 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <venti.h>#include "cvt.h" static intchecksize(int n){	if(n < 256) {		werrstr("bad block size %#ux", n);		return -1;	}	return 0;} // _VtEntryBig integer format is floating-point:// (n>>5) << (n&31).// Convert this number; must be exact or return -1.intvttobig(ulong n){	int shift;	ulong n0;		n0 = n;	shift = 0;	while(n >= (1<<(16 - 5))) {		if(n & 1)			return -1;		shift++;		n >>= 1;	}		n = (n<<5) | shift;	if(((n>>5)<<(n&31)) != n0)		sysfatal("vttobig %#lux => %#lux failed", n0, n);	return n;} voidvtentrypack(VtEntry *e, uchar *p, int index){	ulong t32;	int flags;	uchar *op;	int depth;	int psize, dsize; 	p += index * VtEntrySize;	op = p; 	depth = e->type&VtTypeDepthMask;	flags = (e->flags&~(_VtEntryDir|_VtEntryDepthMask));	flags |= depth << _VtEntryDepthShift;	if(e->type - depth == VtDirType)		flags |= _VtEntryDir;	U32PUT(p, e->gen);	p += 4;	psize = e->psize;	dsize = e->dsize;	if(psize >= (1<<16) || dsize >= (1<<16)) {		flags |= _VtEntryBig;		psize = vttobig(psize);		dsize = vttobig(dsize);		if(psize < 0 || dsize < 0)			sysfatal("invalid entry psize/dsize: %d/%d", e->psize, e->dsize);	}	U16PUT(p, psize);	p += 2;	U16PUT(p, dsize);	p += 2;	U8PUT(p, flags);	p++;	memset(p, 0, 5);	p += 5;	U48PUT(p, e->size, t32);	p += 6;	memmove(p, e->score, VtScoreSize);	p += VtScoreSize; 	assert(p-op == VtEntrySize);} intvtentryunpack(VtEntry *e, uchar *p, int index){	uchar *op; 	p += index * VtEntrySize;	op = p; 	e->gen = U32GET(p);	p += 4;	e->psize = U16GET(p);	p += 2;	e->dsize = U16GET(p);	p += 2;	e->flags = U8GET(p);	p++;	if(e->flags & _VtEntryBig) {		e->psize = (e->psize>>5)<<(e->psize & 31);		e->dsize = (e->dsize>>5)<<(e->dsize & 31);	}	e->type = (e->flags&_VtEntryDir) ? VtDirType : VtDataType;	e->type += (e->flags & _VtEntryDepthMask) >> _VtEntryDepthShift;	e->flags &= ~(_VtEntryDir|_VtEntryDepthMask|_VtEntryBig);	p += 5;	e->size = U48GET(p);	p += 6;	memmove(e->score, p, VtScoreSize);	p += VtScoreSize; 	assert(p-op == VtEntrySize);		if(!(e->flags & VtEntryActive))		return 0; 	/* 	 * Some old vac files use psize==0 and dsize==0 when the	 * file itself has size 0 or is zeros.  Just to make programs not	 * have to figure out what block sizes of 0 means, rewrite them.	 */	if(e->psize == 0 && e->dsize == 0	&& memcmp(e->score, vtzeroscore, VtScoreSize) == 0){		e->psize = 4096;		e->dsize = 4096;	}	if(checksize(e->psize) < 0 || checksize(e->dsize) < 0)		return -1; 	return 0;}