⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pack.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "stdinc.h"#include "vac.h"#include "dat.h"#include "fns.h"#include "error.h"typedef struct MetaChunk MetaChunk;struct MetaChunk {	ushort offset;	ushort size;	ushort index;};static int	stringUnpack(char **s, uchar **p, int *n);/* * integer conversion routines */#define	U8GET(p)	((p)[0])#define	U16GET(p)	(((p)[0]<<8)|(p)[1])#define	U32GET(p)	(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3])#define	U48GET(p)	(((uvlong)U16GET(p)<<32)|(uvlong)U32GET((p)+2))#define	U64GET(p)	(((uvlong)U32GET(p)<<32)|(uvlong)U32GET((p)+4))#define	U8PUT(p,v)	(p)[0]=(v)#define	U16PUT(p,v)	(p)[0]=(v)>>8;(p)[1]=(v)#define	U32PUT(p,v)	(p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)#define	U48PUT(p,v,t32)	t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)#define	U64PUT(p,v,t32)	t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)static intstringUnpack(char **s, uchar **p, int *n){	int nn;	if(*n < 2)		return 0;		nn = U16GET(*p);	*p += 2;	*n -= 2;	if(nn > *n)		return 0;	*s = vtMemAlloc(nn+1);	memmove(*s, *p, nn);	(*s)[nn] = 0;	*p += nn;	*n -= nn;	return 1;}static intstringPack(char *s, uchar *p){	int n;	n = strlen(s);	U16PUT(p, n);	memmove(p+2, s, n);	return n+2;}intmbUnpack(MetaBlock *mb, uchar *p, int n){	u32int magic;	mb->maxsize = n;	mb->buf = p;	if(n == 0) {		memset(mb, 0, sizeof(MetaBlock));		return 1;	}	magic = U32GET(p);	if(magic != MetaMagic && magic != MetaMagic+1) {		vtSetError("bad meta block magic");		return 0;	}	mb->size = U16GET(p+4);	mb->free = U16GET(p+6);	mb->maxindex = U16GET(p+8);	mb->nindex = U16GET(p+10);	mb->unbotch = (magic == MetaMagic+1);	if(mb->size > n) {		vtSetError("bad meta block size");		return 0;	}	p += MetaHeaderSize;	n -= MetaHeaderSize;	USED(p);	if(n < mb->maxindex*MetaIndexSize) { 		vtSetError("truncated meta block 2");		return 0;	}	return 1;}voidmbPack(MetaBlock *mb){	uchar *p;	p = mb->buf;	U32PUT(p, MetaMagic);	U16PUT(p+4, mb->size);	U16PUT(p+6, mb->free);	U16PUT(p+8, mb->maxindex);	U16PUT(p+10, mb->nindex);}voidmbDelete(MetaBlock *mb, int i, MetaEntry *me){	uchar *p;	int n;	assert(i < mb->nindex);	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--;}voidmbInsert(MetaBlock *mb, int i, MetaEntry *me){	uchar *p;	int o, n;	assert(mb->nindex < mb->maxindex);	o = me->p - mb->buf;	n = me->size;	if(o+n > mb->size) {		mb->free -= mb->size - o;		mb->size = o + n;	} else		mb->free -= n;	p = mb->buf + MetaHeaderSize + i*MetaIndexSize;	n = (mb->nindex-i)*MetaIndexSize;	memmove(p+MetaIndexSize, p, n);	U16PUT(p, me->p - mb->buf);	U16PUT(p+2, me->size);	mb->nindex++;}intmeUnpack(MetaEntry *me, MetaBlock *mb, int i){	uchar *p;	int eo, en;	if(i < 0 || i >= mb->nindex) {		vtSetError("bad meta entry index");		return 0;	}	p = mb->buf + MetaHeaderSize + i*MetaIndexSize;	eo = U16GET(p);	en = U16GET(p+2);if(0)print("eo = %d en = %d\n", eo, en);	if(eo < MetaHeaderSize + mb->maxindex*MetaIndexSize) {		vtSetError("corrupted entry in meta block");		return 0;	}	if(eo+en > mb->size) { 		vtSetError("truncated meta block");		return 0;	}	p = mb->buf + eo;		/* make sure entry looks ok and includes an elem name */	if(en < 8 || U32GET(p) != DirMagic || en < 8 + U16GET(p+6)) {		vtSetError("corrupted meta block entry");		return 0;	}	me->p = p;	me->size = en;	return 1;}/* assumes a small amount of checking has been done in mbEntry */intmeCmp(MetaEntry *me, char *s){	int n;	uchar *p;	p = me->p;	p += 6;	n = U16GET(p);	p += 2;	assert(n + 8 < me->size);	while(n > 0) {		if(*s == 0)			return -1;		if(*p < (uchar)*s)			return -1;		if(*p > (uchar)*s)			return 1;		p++;		s++;		n--;	}	return *s != 0;}intmeCmpNew(MetaEntry *me, char *s){	int n;	uchar *p;	p = me->p;	p += 6;	n = U16GET(p);	p += 2;	assert(n + 8 < me->size);	while(n > 0) {		if(*s == 0)			return 1;		if(*p < (uchar)*s)			return -1;		if(*p > (uchar)*s)			return 1;		p++;		s++;		n--;	}	return -(*s != 0);}static intoffsetCmp(void *s0, void *s1){	MetaChunk *mc0, *mc1;	mc0 = s0;	mc1 = s1;	if(mc0->offset < mc1->offset)		return -1;	if(mc0->offset > mc1->offset)		return 1;	return 0;}static MetaChunk *metaChunks(MetaBlock *mb){	MetaChunk *mc;	int oo, o, n, i;	uchar *p;	mc = vtMemAlloc(mb->nindex*sizeof(MetaChunk));	p = mb->buf + MetaHeaderSize;	for(i = 0; i<mb->nindex; i++) {		mc[i].offset = U16GET(p);		mc[i].size = U16GET(p+2);		mc[i].index = i;		p += MetaIndexSize;	}	qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp);	/* check block looks ok */	oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;	o = oo;	n = 0;	for(i=0; i<mb->nindex; i++) {		o = mc[i].offset;		n = mc[i].size;		if(o < oo)			goto Err;		oo += n;	}	if(o+n <= mb->size)		goto Err;	if(mb->size - oo != mb->free)		goto Err;	return mc;Err:	vtMemFree(mc);	return nil;}static voidmbCompact(MetaBlock *mb, MetaChunk *mc){	int oo, o, n, i;	oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;		for(i=0; i<mb->nindex; i++) {		o = mc[i].offset;		n = mc[i].size;		if(o != oo) {			memmove(mb->buf + oo, mb->buf + o, n);			U16PUT(mb->buf + MetaHeaderSize + mc[i].index*MetaIndexSize, oo);		}		oo += n;	}	mb->size = oo;	mb->free = 0;}uchar *mbAlloc(MetaBlock *mb, int n){	int i, o;	MetaChunk *mc;	/* off the end */	if(mb->maxsize - mb->size >= n)		return mb->buf + mb->size;	/* check if possible */	if(mb->maxsize - mb->size + mb->free < n)		return nil;	mc = metaChunks(mb);	/* look for hole */	o = MetaHeaderSize + mb->maxindex*MetaIndexSize;	for(i=0; i<mb->nindex; i++) {		if(mc[i].offset - o >= n) {			vtMemFree(mc);			return mb->buf + o;		}		o = mc[i].offset + mc[i].size;	}	if(mb->maxsize - o >= n) {		vtMemFree(mc);		return mb->buf + o;	}	/* compact and return off the end */	mbCompact(mb, mc);	vtMemFree(mc);	assert(mb->maxsize - mb->size >= n);	return mb->buf + mb->size;}intvdSize(VacDir *dir){	int n;		/* constant part */	n = 	4 +	/* magic */		2 + 	/* version */		4 +	/* entry */		4 + 	/* guid */		4 + 	/* mentry */		4 + 	/* mgen */		8 +	/* qid */		4 + 	/* mtime */		4 + 	/* mcount */		4 + 	/* ctime */		4 + 	/* atime */		4 +	/* mode */		0;	/* strings */	n += 2 + strlen(dir->elem);	n += 2 + strlen(dir->uid);	n += 2 + strlen(dir->gid);	n += 2 + strlen(dir->mid);	/* optional sections */	if(dir->qidSpace) {		n += 	3 + 	/* option header */			8 + 	/* qidOffset */			8;	/* qid Max */	}	return n;}voidvdPack(VacDir *dir, MetaEntry *me){	uchar *p;	ulong t32;	p = me->p;		U32PUT(p, DirMagic);	U16PUT(p+4, 9);		/* version */	p += 6;	p += stringPack(dir->elem, p);	U32PUT(p, dir->entry);	U32PUT(p+4, dir->gen);	U32PUT(p+8, dir->mentry);	U32PUT(p+12, dir->mgen);	U64PUT(p+16, dir->qid, t32);	p += 24;	p += stringPack(dir->uid, p);	p += stringPack(dir->gid, p);	p += stringPack(dir->mid, p);		U32PUT(p, dir->mtime);	U32PUT(p+4, dir->mcount);	U32PUT(p+8, dir->ctime);	U32PUT(p+12, dir->atime);	U32PUT(p+16, dir->mode);	p += 5*4;	if(dir->qidSpace) {		U8PUT(p, DirQidSpaceEntry);		U16PUT(p+1, 2*8);		p += 3;		U64PUT(p, dir->qidOffset, t32);		U64PUT(p+8, dir->qidMax, t32);	}	assert(p == me->p + me->size);}intvdUnpack(VacDir *dir, MetaEntry *me){	int t, nn, n, version;	uchar *p;		p = me->p;	n = me->size;	memset(dir, 0, sizeof(VacDir));if(0)print("vdUnpack\n");	/* magic */	if(n < 4 || U32GET(p) != DirMagic)		goto Err;	p += 4;	n -= 4;if(0)print("vdUnpack: got magic\n");	/* version */	if(n < 2)		goto Err;	version = U16GET(p);	if(version < 7 || version > 9)		goto Err;	p += 2;	n -= 2;	if(0)print("vdUnpack: got version\n");	/* elem */	if(!stringUnpack(&dir->elem, &p, &n))		goto Err;if(0)print("vdUnpack: got elem\n");	/* entry  */	if(n < 4)		goto Err;	dir->entry = U32GET(p);	p += 4;	n -= 4;if(0)print("vdUnpack: got entry\n");	if(version < 9) {		dir->gen = 0;		dir->mentry = dir->entry+1;		dir->mgen = 0;	} else {		if(n < 3*4)			goto Err;		dir->gen = U32GET(p);		dir->mentry = U32GET(p+4);		dir->mgen = U32GET(p+8);		p += 3*4;		n -= 3*4;	}if(0)print("vdUnpack: got gen etc\n");	/* size is gotten from DirEntry */	/* qid */	if(n < 8)		goto Err;	dir->qid = U64GET(p);	p += 8;	n -= 8;if(0)print("vdUnpack: got qid\n");	/* skip replacement */	if(version == 7) {		if(n < VtScoreSize)			goto Err;		p += VtScoreSize;		n -= VtScoreSize;	}		/* uid */	if(!stringUnpack(&dir->uid, &p, &n))		goto Err;	/* gid */	if(!stringUnpack(&dir->gid, &p, &n))		goto Err;	/* mid */	if(!stringUnpack(&dir->mid, &p, &n))		goto Err;if(0)print("vdUnpack: got ids\n");	if(n < 5*4)		goto Err;	dir->mtime = U32GET(p);	dir->mcount = U32GET(p+4);	dir->ctime = U32GET(p+8);	dir->atime = U32GET(p+12);	dir->mode = U32GET(p+16);	p += 5*4;	n -= 5*4;if(0)print("vdUnpack: got times\n");	/* optional meta data */	while(n > 0) {		if(n < 3)			goto Err;		t = p[0];		nn = U16GET(p+1);		p += 3;		n -= 3;		if(n < nn)			goto Err;		switch(t) {		case DirPlan9Entry:			/* not valid in version >= 9 */			if(version >= 9)				break;			if(dir->plan9 || nn != 12)				goto Err;			dir->plan9 = 1;			dir->p9path = U64GET(p);			dir->p9version = U32GET(p+8);			if(dir->mcount == 0)				dir->mcount = dir->p9version;			break;		case DirGenEntry:			/* not valid in version >= 9 */			if(version >= 9)				break;			break;		case DirQidSpaceEntry:			if(dir->qidSpace || nn != 16)				goto Err;			dir->qidSpace = 1;			dir->qidOffset = U64GET(p);			dir->qidMax = U64GET(p+8);			break;		}		p += nn;		n -= nn;	}if(0)print("vdUnpack: got options\n");	if(p != me->p + me->size)		goto Err;if(0)print("vdUnpack: correct size\n");	return 1;Err:if(0)print("vdUnpack: XXXXXXXXXXXX EbadMeta\n");	vtSetError(EBadMeta);	vdCleanup(dir);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -