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

📄 paqfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
paqDirFree(PaqDir *pd){	if(pd == nil)		return;	free(pd->name);	free(pd->uid);	free(pd->gid);	free(pd);}QidpaqDirQid(PaqDir *d){	Qid q;	q.path = d->qid;	q.vers = 0;	q.type = d->mode >> 24;	return q;}intpackDir(PaqDir *s, uchar *buf, int n){	Dir dir;	memset(&dir, 0, sizeof(dir));	dir.qid = paqDirQid(s);	dir.mode = s->mode;	dir.atime = s->mtime;	dir.mtime = s->mtime;	dir.length = s->length;	dir.name = s->name;	dir.uid = s->uid;	dir.gid = s->gid;	dir.muid = s->uid;	n = convD2M(&dir, buf, n);	if(n < STATFIXLEN)		return 0;	return n;}Block *blockLoad(ulong addr, int type){	ulong age;	int i, j;	Block *b;	if(addr == 0)		return nil;	cacheage++;	/* age has wraped */	if(cacheage == 0) {		for(i=0; i<cachesize; i++)			cache[i].age = 0;	}	j = -1;	age = ~0;	for(i=0; i<cachesize; i++) {		b = &cache[i];		if(b->age < age && b->ref == 0) {			age = b->age;			j = i;		}		if(b->addr != addr)			continue;		b->age = cacheage;		b->ref++;		return b;	}	if(j < 0)		sysfatal("no empty spots in cache!\n");	b = &cache[j];	assert(b->ref == 0);	if(!blockRead(b->data, addr, type)) {		b->addr = 0;		b->age = 0;		return nil;	}	b->age = cacheage;	b->addr = addr;	b->ref = 1;		return b;}voidblockFree(Block *b){	if(b == nil)		return;	if(--b->ref > 0)		return;	assert(b->ref == 0);}Paq*paqWalk(Paq *s, char *name){	Block *ptr, *b;	uchar *p, *ep;	PaqDir *pd;	int i, n;	Paq *ss;	if(strcmp(name, "..") == 0)		return paqCpy(s->up);	if(rootfile && s == root){		if(strcmp(name, rootfile->dir->name) == 0)			return paqCpy(rootfile);		return nil;	}	ptr = blockLoad(s->dir->offset, PointerBlock);	if(ptr == nil)		return nil;	for(i=0; i<blocksize/4; i++) {		b = blockLoad(getl(ptr->data+i*4), DirBlock);		if(b == nil)			break;		p = b->data;		ep = p + blocksize;		while(checkDirSize(p, ep)) {			n = gets(p);			pd = getDir(p);			if(strcmp(pd->name, name) == 0) {				ss = emallocz(sizeof(Paq));				ss->ref = 1;				ss->up = paqCpy(s);				ss->dir = pd;				ss->qid = paqDirQid(pd);				blockFree(b);				blockFree(ptr);				return ss;			}			paqDirFree(pd);			p += n;		}		blockFree(b);	}	blockFree(ptr);	return nil;}Fid *newfid(int fid){	Fid *f, *ff;	ff = 0;	for(f = fids; f; f = f->next)		if(f->fid == fid)			return f;		else if(!ff && !f->busy)			ff = f;	if(ff){		ff->fid = fid;		return ff;	}	f = emallocz(sizeof *f);	f->fid = fid;	f->next = fids;	fids = f;	return f;}voidio(int fd){	char *err;	int n, pid;	uchar *mdata;	mdata = emalloc(mesgsize);	pid = getpid();	for(;;){		n = read9pmsg(fd, mdata, mesgsize);		if(n < 0)			sysfatal("mount read");		if(n == 0)			break;		if(convM2S(mdata, n, &rhdr) == 0)			continue;		if(debug)			fprint(2, "paqfs %d:<-%F\n", pid, &rhdr);		thdr.data = (char*)mdata + IOHDRSZ;		if(!fcalls[rhdr.type])			err = "bad fcall type";		else			err = (*fcalls[rhdr.type])(newfid(rhdr.fid));		if(err){			thdr.type = Rerror;			thdr.ename = err;		}else{			thdr.type = rhdr.type + 1;			thdr.fid = rhdr.fid;		}		thdr.tag = rhdr.tag;		if(debug)			fprint(2, "paqfs %d:->%F\n", pid, &thdr);/**/		n = convS2M(&thdr, mdata, mesgsize);		if(n == 0)			sysfatal("convS2M sysfatal on write");		if(write(fd, mdata, n) != n)			sysfatal("mount write");	}}intperm(PaqDir *s, char *user, int p){	ulong perm = s->mode;	if((p*Pother) & perm)		return 1;	if((noauth || strcmp(user, s->gid)==0) && ((p*Pgroup) & perm))		return 1;	if((noauth || strcmp(user, s->uid)==0) && ((p*Powner) & perm))		return 1;	return 0;}voidinit(char *file, int verify){	PaqHeader hdr;	PaqTrailer tlr;	Dir *dir;	int i;	uchar *p;	DigestState *ds = nil;	PaqDir *r;	Block *b;	ulong offset;	inflateinit();	bin = Bopen(file, OREAD);	if(bin == nil)		sysfatal("could not open file: %s: %r", file);	if(verify)		ds = sha1(0, 0, 0, 0);		readHeader(&hdr, file, ds);	blocksize = hdr.blocksize;	if(verify) {		readBlocks(file, ds);	} else {		dir = dirstat(file);		if(dir == nil)			sysfatal("could not stat file: %s: %r", file);		offset = dir->length - TrailerSize;		free(dir);		if(Bseek(bin, offset, 0) != offset)			sysfatal("could not seek to trailer: %s", file);	}	readTrailer(&tlr, file, ds);	/* asctime includes a newline - yuk */	fprint(2, "%s: %s", hdr.label, asctime(gmtime(hdr.time)));	fprint(2, "fingerprint: ");	for(i=0; i<20; i++)		fprint(2, "%.2x", tlr.sha1[i]);	fprint(2, "\n");	cache = emallocz(cachesize*sizeof(Block));	p = emalloc(cachesize*blocksize);	for(i=0; i<cachesize; i++) {		cache[i].data = p;		p += blocksize;	}	/* hand craft root */	b = blockLoad(tlr.root, DirBlock);	if(b == nil || !checkDirSize(b->data, b->data+blocksize))		sysfatal("could not read root block: %s", file);	r = getDir(b->data);	blockFree(b);	root = emallocz(sizeof(Paq));	root->qid = paqDirQid(r);	root->ref = 1;	root->dir = r;	root->up = root;	/* parent of root is root */	/* craft root directory if root is a normal file */	if(!(root->qid.type&QTDIR)){		rootfile = root;		root = emallocz(sizeof(Paq));		root->qid = rootfile->qid;		root->qid.type |= QTDIR;		root->qid.path++;		root->ref = 1;		root->dir = emallocz(sizeof(PaqDir));		*root->dir = *r;		root->dir->mode |= DMDIR|0111;		root->up = root;	}}intblockRead(uchar *data, ulong addr, int type){	uchar buf[BlockSize];	PaqBlock b;	uchar *cdat;	if(Bseek(bin, addr, 0) != addr){		fprint(2, "paqfs: seek %lud: %r\n", addr);		return 0;	}	if(Bread(bin, buf, BlockSize) != BlockSize){		fprint(2, "paqfs: read %d at %lud: %r\n", BlockSize, addr);		return 0;	}	getBlock(buf, &b);	if(b.magic != BlockMagic || b.size > blocksize || b.type != type){		fprint(2, "paqfs: bad block: magic %.8lux (want %.8ux) size %lud (max %d) type %ud (want %ud)\n",			b.magic, BlockMagic, b.size, blocksize, b.type, type);		return 0;	}	switch(b.encoding) {	default:		return 0;	case NoEnc:		if(Bread(bin, data, blocksize) < blocksize)			return 0;		break;	case DeflateEnc:		cdat = emalloc(b.size);		if(Bread(bin, cdat, b.size) < b.size) {			free(cdat);			return 0;		}		if(inflateblock(data, blocksize, cdat, b.size) < 0) {			fprint(2, "inflate error: %r\n");			free(cdat);			return 0;		}		free(cdat);		break;	}	if(adler32(0, data, blocksize) != b.adler32)		return 0;	return 1;}voidreadHeader(PaqHeader *hdr, char *name, DigestState *ds){	uchar buf[HeaderSize];		if(Bread(bin, buf, HeaderSize) < HeaderSize)		sysfatal("could not read header: %s: %r", name);	if(ds)		sha1(buf, HeaderSize, 0, ds);	getHeader(buf, hdr);	if(hdr->magic != HeaderMagic)		sysfatal("bad header magic 0x%lux: %s", hdr->magic, name);	if(hdr->version != Version)		sysfatal("unknown file version: %s", name);}voidreadBlocks(char *name, DigestState *ds){	uchar *buf;	PaqBlock b;	buf = emalloc(BlockSize+blocksize);	for(;;) {		if(Bread(bin, buf, 4) < 4)			sysfatal("could not read block: %s: %r", name);		Bseek(bin, -4, 1);		/* check if it is a data block */		if(getl(buf) != BlockMagic)			break;		if(Bread(bin, buf, BlockSize) < BlockSize)			sysfatal("could not read block: %s: %r", name);		if(ds)			sha1(buf, BlockSize, 0, ds);		getBlock(buf, &b);		if(b.size > blocksize)			sysfatal("bad block size: %lud: %s", b.size, name);		if(ds) {			if(Bread(bin, buf, b.size) < b.size)				sysfatal("sysfatal reading block: %s: %r", name);			sha1(buf, b.size, 0, ds);		} else			Bseek(bin, b.size, 1);	}	free(buf);}voidreadTrailer(PaqTrailer *tlr, char *name, DigestState *ds){	uchar buf[TrailerSize];	uchar digest[20];	if(Bread(bin, buf, TrailerSize) < TrailerSize)		sysfatal("could not read trailer: %s: %r", name);	getTrailer(buf, tlr);	if(tlr->magic != TrailerMagic)		sysfatal("bad trailer magic: %s", name);	if(ds) {		sha1(buf, TrailerSize-20, digest, ds);		if(memcmp(digest, tlr->sha1, 20) != 0)			sysfatal("bad sha1 digest: %s", name);	}}void *emalloc(ulong n){	void *p;	p = malloc(n);	if(!p)		sysfatal("out of memory");	return p;}void *emallocz(ulong n){	void *p;	p = emalloc(n);	memset(p, 0, n);	return p;}void *erealloc(void *p, ulong n){	p = realloc(p, n);	if(!p)		sysfatal("out of memory");	return p;}char *estrdup(char *s){	s = strdup(s);	if(s == nil)		sysfatal("out of memory");	return s;}ulonggetl(uchar *p){	return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];}intgets(uchar *p){	return (p[0]<<8) | p[1];}intcheckDirSize(uchar *p, uchar *ep){	int n;		int i;	if(ep-p < 2)		return 0;	n = gets(p);	if(p+n > ep)		return 0;	ep = p+n;	p += 22;	for(i=0; i<3; i++) {		if(p+2 > ep)			return 0;		n = gets(p);		if(p+n > ep)			return 0;		p += n;	}	return 1;}voidgetHeader(uchar *p, PaqHeader *h){	h->magic = getl(p);	h->version = gets(p+4);	h->blocksize = gets(p+6);	if((h->magic>>16) == BigHeaderMagic){		h->magic = HeaderMagic;		h->version = gets(p+2);		h->blocksize = getl(p+4);	}	h->time = getl(p+8);	memmove(h->label, p+12, sizeof(h->label));	h->label[sizeof(h->label)-1] = 0;}voidgetTrailer(uchar *p, PaqTrailer *t){	t->magic = getl(p);	t->root = getl(p+4);	memmove(t->sha1, p+8, 20);}voidgetBlock(uchar *p, PaqBlock *b){	b->magic = getl(p);	b->size = gets(p+4);	if((b->magic>>16) == BigBlockMagic){		b->magic = BlockMagic;		b->size = getl(p+2);	}	b->type = p[6];	b->encoding = p[7];	b->adler32 = getl(p+8);}PaqDir *getDir(uchar *p){	PaqDir *pd;	pd = emallocz(sizeof(PaqDir));	pd->qid = getl(p+2);	pd->mode = getl(p+6);	pd->mtime = getl(p+10);	pd->length = getl(p+14);	pd->offset = getl(p+18);	p += 22;	pd->name = getstr(p);	p += gets(p);	pd->uid = getstr(p);	p += gets(p);	pd->gid = getstr(p);	return pd;}char *getstr(uchar *p){	char *s;	int n;	n = gets(p);	s = emalloc(n+1);	memmove(s, p+2, n);	s[n] = 0;	return s;}voidusage(void){	fprint(2, "usage: %s [-disv] [-c cachesize] [-m mountpoint] [-M mesgsize] paqfile\n", argv0);	exits("usage");}

⌨️ 快捷键说明

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