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

📄 vac.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
			ln = smprint("%s/%s", lname, name);			sn = smprint("%s/%s", sname, name);			if (ln == nil || sn == nil)				sysfatal("out of memory");			if(vf != nil)				vvf = vfWalk(vf, name);			else				vvf = nil;			vacFile(ds, ln, sn, vvf);			if(vvf != nil)				vfDecRef(vvf);			free(ln);			free(sn);		}		free(dirs);	}	dirSinkClose(ds);	dirSinkWriteSink(dsink, ds->sink);	dirSinkWriteSink(dsink, ds->msink->sink);	dirSinkFree(ds);}static intvacMergeFile(DirSink *dsink, VacFile *vf, VacDir *dir, uvlong offset, uvlong *max){	uchar buf[VtEntrySize];	VtEntry dd, md;	int e;	if(vfRead(vf, buf, VtEntrySize, (uvlong)dir->entry*VtEntrySize) != VtEntrySize) {		warn("could not read venti dir entry: %s\n", dir->elem);		return 0;	}	vtEntryUnpack(&dd, buf, 0);	if(dir->mode & ModeDir)	{		e = dir->mentry;		if(e == 0)			e = dir->entry + 1;		if(vfRead(vf, buf, VtEntrySize, e*VtEntrySize) != VtEntrySize) {			warn("could not read venti dir entry: %s\n", dir->elem);			return 0;		}		vtEntryUnpack(&md, buf, 0);	}	/* max might be incorrect in some old dumps */	if(dir->qid >= *max) {		warn("qid out of range: %s", dir->elem);		*max = dir->qid;	}	dir->qid += offset;	dir->entry = dsink->nentry;	if(dir->qidSpace) {		dir->qidOffset += offset;	} else {		dir->qidSpace = 1;		dir->qidOffset = offset;		dir->qidMax = *max;	}	dirSinkWrite(dsink, &dd);	if(dir->mode & ModeDir)		dirSinkWrite(dsink, &md);	metaSinkWriteDir(dsink->msink, dir);	return 1;}static intvacMerge(DirSink *dsink, char *lname, char *sname){	char *p;	VacFS *fs;	VacFile *vf;	VacDirEnum *d;	VacDir dir;	uvlong max;	p = strrchr(sname, '.');	if(p == 0 || strcmp(p, ".vac"))		return 0;	d = nil;	fs = vfsOpen(dsink->sink->z, sname, 1, 100);	if(fs == nil)		return 0;	vf = vfOpen(fs, "/");	if(vf == nil)		goto Done;	max = vfGetId(vf);	d = vdeOpen(fs, "/");	if(d == nil)		goto Done;	if(verbose)		fprint(2, "%s: merging: %s\n", argv0, lname);	if(maxbsize < vfsGetBlockSize(fs))		maxbsize = vfsGetBlockSize(fs);	for(;;) {		if(vdeRead(d, &dir, 1) < 1)			break;		vacMergeFile(dsink, vf, &dir, fileid, &max);		vdCleanup(&dir);	}	fileid += max;Done:	if(d != nil)		vdeFree(d);	if(vf != nil)		vfDecRef(vf);	vfsClose(fs);	return 1;}Sink *sinkAlloc(VtSession *z, int psize, int dsize){	Sink *k;	int i;	if(psize < 512 || psize > VtMaxLumpSize)		vtFatal("sinkAlloc: bad psize");	if(dsize < 512 || dsize > VtMaxLumpSize)		vtFatal("sinkAlloc: bad psize");	psize = VtScoreSize*(psize/VtScoreSize);	k = vtMemAllocZ(sizeof(Sink));	k->z = z;	k->dir.flags = VtEntryActive;	k->dir.psize = psize;	k->dir.dsize = dsize;	k->buf = vtMemAllocZ(VtPointerDepth*k->dir.psize + VtScoreSize);	for(i=0; i<=VtPointerDepth; i++)		k->pbuf[i] = k->buf + i*k->dir.psize;	return k;}voidsinkWriteScore(Sink *k, uchar score[VtScoreSize], int n){	int i;	uchar *p;	VtEntry *d;	memmove(k->pbuf[0], score, VtScoreSize);	d = &k->dir;	for(i=0; i<VtPointerDepth; i++) {		k->pbuf[i] += VtScoreSize;		if(k->pbuf[i] < k->buf + d->psize*(i+1))			break;		if(i == VtPointerDepth-1)			vtFatal("file too big");		p = k->buf+i*d->psize;		stats.meta++;		if(!vacWrite(k->z, k->pbuf[i+1], VtPointerType0+i, p, d->psize))			vtFatal("vacWrite failed: %s", vtGetError());		k->pbuf[i] = p;	}	/* round size up to multiple of dsize */	d->size = d->dsize * ((d->size + d->dsize-1)/d->dsize);	d->size += n;}voidsinkWrite(Sink *k, uchar *p, int n){	int type;	uchar score[VtScoreSize];	if(n > k->dir.dsize)		vtFatal("sinkWrite: size too big");	if(k->dir.flags & VtEntryDir) {		type = VtDirType;		stats.meta++;	} else {		type = VtDataType;		stats.data++;	}	if(!vacWrite(k->z, score, type, p, n))		vtFatal("vacWrite failed: %s", vtGetError());	sinkWriteScore(k, score, n);}static intsizeToDepth(uvlong s, int psize, int dsize){	int np;	int d;	/* determine pointer depth */	np = psize/VtScoreSize;	s = (s + dsize - 1)/dsize;	for(d = 0; s > 1; d++)		s = (s + np - 1)/np;	return d;}voidsinkClose(Sink *k){	int i, n;	uchar *p;	VtEntry *kd;	kd = &k->dir;	/* empty */	if(kd->size == 0) {		memmove(kd->score, vtZeroScore, VtScoreSize);		return;	}	for(n=VtPointerDepth-1; n>0; n--)		if(k->pbuf[n] > k->buf + kd->psize*n)			break;	kd->depth = sizeToDepth(kd->size, kd->psize, kd->dsize);	/* skip full part of tree */	for(i=0; i<n && k->pbuf[i] == k->buf + kd->psize*i; i++)		;	/* is the tree completely full */	if(i == n && k->pbuf[n] == k->buf + kd->psize*n + VtScoreSize) {		memmove(kd->score, k->pbuf[n] - VtScoreSize, VtScoreSize);		return;	}	n++;	/* clean up the edge */	for(; i<n; i++) {		p = k->buf+i*kd->psize;		stats.meta++;		if(!vacWrite(k->z, k->pbuf[i+1], VtPointerType0+i, p, k->pbuf[i]-p))			vtFatal("vacWrite failed: %s", vtGetError());		k->pbuf[i+1] += VtScoreSize;	}	memmove(kd->score, k->pbuf[i] - VtScoreSize, VtScoreSize);}voidsinkFree(Sink *k){	vtMemFree(k->buf);	vtMemFree(k);}DirSink *dirSinkAlloc(VtSession *z, int psize, int dsize){	DirSink *k;	int ds;	ds = VtEntrySize*(dsize/VtEntrySize);	k = vtMemAllocZ(sizeof(DirSink));	k->sink = sinkAlloc(z, psize, ds);	k->sink->dir.flags |= VtEntryDir;	k->msink = metaSinkAlloc(z, psize, dsize);	k->buf = vtMemAlloc(ds);	k->p = k->buf;	k->ep = k->buf + ds;	return k;}voiddirSinkWrite(DirSink *k, VtEntry *dir){	if(k->p + VtEntrySize > k->ep) {		sinkWrite(k->sink, k->buf, k->p - k->buf);		k->p = k->buf;	}	vtEntryPack(dir, k->p, 0);	k->nentry++;	k->p += VtEntrySize;}voiddirSinkWriteSink(DirSink *k, Sink *sink){	dirSinkWrite(k, &sink->dir);}intdirSinkWriteFile(DirSink *k, VacFile *vf){	VtEntry dir;	if(!vfGetVtEntry(vf, &dir))		return 0;	dirSinkWrite(k, &dir);	return 1;}voiddirSinkClose(DirSink *k){	metaSinkClose(k->msink);	if(k->p != k->buf)		sinkWrite(k->sink, k->buf, k->p - k->buf);	sinkClose(k->sink);}voiddirSinkFree(DirSink *k){	sinkFree(k->sink);	metaSinkFree(k->msink);	vtMemFree(k->buf);	vtMemFree(k);}MetaSink *metaSinkAlloc(VtSession *z, int psize, int dsize){	MetaSink *k;	k = vtMemAllocZ(sizeof(MetaSink));	k->sink = sinkAlloc(z, psize, dsize);	k->buf = vtMemAlloc(dsize);	k->maxindex = dsize/100;	/* 100 byte entries seems reasonable */	if(k->maxindex < 1)		k->maxindex = 1;	k->rp = k->p = k->buf + MetaHeaderSize + k->maxindex*MetaIndexSize;	k->ep = k->buf + dsize;	return k;}/* hack to get base to compare routine - not reentrant */uchar *blockBase;intdirCmp(void *p0, void *p1){	uchar *q0, *q1;	int n0, n1, r;	/* name is first element of entry */	q0 = p0;	q0 = blockBase + (q0[0]<<8) + q0[1];	n0 = (q0[6]<<8) + q0[7];	q0 += 8;	q1 = p1;	q1 = blockBase + (q1[0]<<8) + q1[1];	n1 = (q1[6]<<8) + q1[7];	q1 += 8;	if(n0 == n1)		return memcmp(q0, q1, n0);	else if (n0 < n1) {		r = memcmp(q0, q1, n0);		return (r==0)?1:r;	} else  {		r = memcmp(q0, q1, n1);		return (r==0)?-1:r;	}}voidmetaSinkFlush(MetaSink *k){	uchar *p;	int n;	MetaBlock mb;	if(k->nindex == 0)		return;	assert(k->nindex <= k->maxindex);	p = k->buf;	n = k->rp - p;	mb.size = n;	mb.free = 0;	mb.nindex = k->nindex;	mb.maxindex = k->maxindex;	mb.buf = p;	mbPack(&mb);	p += MetaHeaderSize;	/* XXX this is not reentrant! */	blockBase = k->buf;	qsort(p, k->nindex, MetaIndexSize, dirCmp);	p += k->nindex*MetaIndexSize;	memset(p, 0, (k->maxindex-k->nindex)*MetaIndexSize);	p += (k->maxindex-k->nindex)*MetaIndexSize;	sinkWrite(k->sink, k->buf, n);	/* move down partial entry */	n = k->p - k->rp;	memmove(p, k->rp, n);	k->rp = p;	k->p = p + n;	k->nindex = 0;}voidmetaSinkPutc(MetaSink *k, int c){	if(k->p+1 > k->ep)		metaSinkFlush(k);	if(k->p+1 > k->ep)		vtFatal("directory entry too large");	k->p[0] = c;	k->p++;}voidmetaSinkPutString(MetaSink *k, char *s){	int n = strlen(s);	metaSinkPutc(k, n>>8);	metaSinkPutc(k, n);	metaSinkWrite(k, (uchar*)s, n);}voidmetaSinkPutUint32(MetaSink *k, ulong x){	metaSinkPutc(k, x>>24);	metaSinkPutc(k, x>>16);	metaSinkPutc(k, x>>8);	metaSinkPutc(k, x);}voidmetaSinkPutUint64(MetaSink *k, uvlong x){	metaSinkPutUint32(k, x>>32);	metaSinkPutUint32(k, x);}voidmetaSinkWrite(MetaSink *k, uchar *data, int n){	if(k->p + n > k->ep)		metaSinkFlush(k);	if(k->p + n > k->ep)		vtFatal("directory entry too large");	memmove(k->p, data, n);	k->p += n;}voidmetaSinkWriteDir(MetaSink *ms, VacDir *dir){	metaSinkPutUint32(ms, DirMagic);	metaSinkPutc(ms, Version>>8);	metaSinkPutc(ms, Version);	metaSinkPutString(ms, dir->elem);	metaSinkPutUint32(ms, dir->entry);	metaSinkPutUint64(ms, dir->qid);	metaSinkPutString(ms, dir->uid);	metaSinkPutString(ms, dir->gid);	metaSinkPutString(ms, dir->mid);	metaSinkPutUint32(ms, dir->mtime);	metaSinkPutUint32(ms, dir->mcount);	metaSinkPutUint32(ms, dir->ctime);	metaSinkPutUint32(ms, dir->atime);	metaSinkPutUint32(ms, dir->mode);	if(dir->plan9) {		metaSinkPutc(ms, DirPlan9Entry);	/* plan9 extra info */		metaSinkPutc(ms, 0);			/* plan9 extra size */		metaSinkPutc(ms, 12);			/* plan9 extra size */		metaSinkPutUint64(ms, dir->p9path);		metaSinkPutUint32(ms, dir->p9version);	}	if(dir->qidSpace != 0) {		metaSinkPutc(ms, DirQidSpaceEntry);		metaSinkPutc(ms, 0);		metaSinkPutc(ms, 16);		metaSinkPutUint64(ms, dir->qidOffset);		metaSinkPutUint64(ms, dir->qidMax);	}	if(dir->gen != 0) {		metaSinkPutc(ms, DirGenEntry);		metaSinkPutc(ms, 0);		metaSinkPutc(ms, 4);		metaSinkPutUint32(ms, dir->gen);	}	metaSinkEOR(ms);}voidplan9ToVacDir(VacDir *vd, Dir *dir, ulong entry, uvlong qid){	memset(vd, 0, sizeof(VacDir));	vd->elem = vtStrDup(dir->name);	vd->entry = entry;	vd->qid = qid;	vd->uid = vtStrDup(dir->uid);	vd->gid = vtStrDup(dir->gid);	vd->mid = vtStrDup(dir->muid);	vd->mtime = dir->mtime;	vd->mcount = 0;	vd->ctime = dir->mtime;		/* ctime: not available on plan 9 */	vd->atime = dir->atime;	vd->mode = dir->mode & 0777;	if(dir->mode & DMDIR)		vd->mode |= ModeDir;	if(dir->mode & DMAPPEND)		vd->mode |= ModeAppend;	if(dir->mode & DMEXCL)		vd->mode |= ModeExclusive;	vd->plan9 = 1;	vd->p9path = dir->qid.path;	vd->p9version = dir->qid.vers;}voidmetaSinkEOR(MetaSink *k){	uchar *p;	int o, n;	p = k->buf + MetaHeaderSize;	p += k->nindex * MetaIndexSize;	o = k->rp-k->buf; 	/* offset from start of block */	n = k->p-k->rp;		/* size of entry */	p[0] = o >> 8;	p[1] = o;	p[2] = n >> 8;	p[3] = n;	k->rp = k->p;	k->nindex++;	if(k->nindex == k->maxindex)		metaSinkFlush(k);}voidmetaSinkClose(MetaSink *k){	metaSinkFlush(k);	sinkClose(k->sink);}voidmetaSinkFree(MetaSink *k){	sinkFree(k->sink);	vtMemFree(k->buf);	vtMemFree(k);}static voidwarn(char *fmt, ...){	va_list arg;	va_start(arg, fmt);	fprint(2, "%s: ", argv0);	vfprint(2, fmt, arg);	fprint(2, "\n");	va_end(arg);}static voidcleanup(void){	if(oname != nil)		remove(oname);}#define TWID64	((u64int)~(u64int)0)static u64intunittoull(char *s){	char *es;	u64int n;	if(s == nil)		return TWID64;	n = strtoul(s, &es, 0);	if(*es == 'k' || *es == 'K'){		n *= 1024;		es++;	}else if(*es == 'm' || *es == 'M'){		n *= 1024*1024;		es++;	}else if(*es == 'g' || *es == 'G'){		n *= 1024*1024*1024;		es++;	}	if(*es != '\0')		return TWID64;	return n;}

⌨️ 快捷键说明

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