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

📄 file.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* link in and up parent ref count */	nvf->next = vf->down;	vf->down = nvf;	nvf->up = vf;	vfIncRef(vf);	vfWAccess(vf, user);	vfUnlock(vf);	return nvf;Err:	lumpDecRef(u, 1);	if(r)		sourceRemove(r);	if(mr)		sourceRemove(mr);	if(nvf)		vfFree(nvf);	vfUnlock(vf);	return 0;}intvfRead(VacFile *vf, void *buf, int cnt, vlong offset){	Source *s;	uvlong size;	ulong bn;	int off, dsize, n, nn;	Lump *u;	uchar *b;if(0)fprint(2, "vfRead: %s %d, %lld\n", vf->dir.elem, cnt, offset);	if(!vfRLock(vf))		return -1;	s = vf->source;	dsize = s->dsize;	size = sourceGetSize(s);	if(offset < 0) {		vtSetError(EBadOffset);		goto Err;	}	vfRAccess(vf);	if(offset >= size)		offset = size;	if(cnt > size-offset)		cnt = size-offset;	bn = offset/dsize;	off = offset%dsize;	b = buf;	while(cnt > 0) {		u = sourceGetLump(s, bn, 1, 0);		if(u == nil)			goto Err;		if(u->asize <= off) {			lumpDecRef(u, 0);			goto Err;		}		n = cnt;		if(n > dsize-off)			n = dsize-off;		nn = u->asize-off;		if(nn > n)			nn = n;		memmove(b, u->data+off, nn);		memset(b+nn, 0, n-nn);		off = 0;		bn++;		cnt -= n;		b += n;		lumpDecRef(u, 0);	}	vfRUnlock(vf);	return b-(uchar*)buf;Err:	vfRUnlock(vf);	return -1;}intvfWrite(VacFile *vf, void *buf, int cnt, vlong offset, char *user){	Source *s;	ulong bn;	int off, dsize, n;	Lump *u;	uchar *b;	USED(user);	if(!vfLock(vf))		return -1;	if(vf->fs->readOnly) {		vtSetError(EReadOnly);		goto Err;	}	if(vf->dir.mode & ModeDir) {		vtSetError(ENotFile);		goto Err;	}if(0)fprint(2, "vfWrite: %s %d, %lld\n", vf->dir.elem, cnt, offset);	s = vf->source;	dsize = s->dsize;	if(offset < 0) {		vtSetError(EBadOffset);		goto Err;	}	vfWAccess(vf, user);	bn = offset/dsize;	off = offset%dsize;	b = buf;	while(cnt > 0) {		n = cnt;		if(n > dsize-off)			n = dsize-off;		if(!sourceSetDepth(s, offset+n))			goto Err;		u = sourceGetLump(s, bn, 0, 0);		if(u == nil)			goto Err;		if(u->asize < dsize) {			vtSetError("runt block");			lumpDecRef(u, 0);			goto Err;		}		memmove(u->data+off, b, n);		off = 0;		cnt -= n;		b += n;		offset += n;		bn++;		lumpDecRef(u, 0);		if(!sourceSetSize(s, offset))			goto Err;	}	vfLock(vf);	return b-(uchar*)buf;Err:	vfLock(vf);	return -1;}intvfGetDir(VacFile *vf, VacDir *dir){	if(!vfRLock(vf))		return 0;	vfMetaLock(vf);	vdCopy(dir, &vf->dir);	vfMetaUnlock(vf);	if(!vfIsDir(vf))		dir->size = sourceGetSize(vf->source);	vfRUnlock(vf);	return 1;}uvlongvfGetId(VacFile *vf){	/* immutable */	return vf->dir.qid;}ulongvfGetMcount(VacFile *vf){	ulong mcount;	vfMetaLock(vf);	mcount = vf->dir.mcount;	vfMetaUnlock(vf);	return mcount;}intvfIsDir(VacFile *vf){	/* immutable */	return (vf->dir.mode & ModeDir) != 0;}intvfIsRoot(VacFile *vf){	return vf == vf->fs->root;}intvfGetSize(VacFile *vf, uvlong *size){	if(!vfRLock(vf))		return 0;	*size = sourceGetSize(vf->source);	vfRUnlock(vf);	return 1;}static intvfMetaRemove(VacFile *vf, char *user){	Lump *u;	MetaBlock mb;	MetaEntry me;	int i;	VacFile *vfp;	vfp = vf->up;	vfWAccess(vfp, user);	vfMetaLock(vf);	u = sourceGetLump(vfp->msource, vf->block, 0, 1);	if(u == nil)		goto Err;	if(!mbUnpack(&mb, u->data, u->asize))		goto Err;	if(!mbSearch(&mb, vf->dir.elem, &i, &me) || me.p == nil)		goto Err;print("deleting %d entry\n", i);	mbDelete(&mb, i, &me);	memset(me.p, 0, me.size);	mbPack(&mb);	lumpDecRef(u, 1);	vf->removed = 1;	vf->block = NilBlock;	vfMetaUnlock(vf);	return 1;Err:	lumpDecRef(u, 1);	vfMetaUnlock(vf);	return 0;}static intvfCheckEmpty(VacFile *vf){	int i, n;	Lump *u;	MetaBlock mb;	Source *r;	r = vf->msource;	n = sourceGetNumBlocks(r);	for(i=0; i<n; i++) {		u = sourceGetLump(r, i, 1, 1);		if(u == nil)			goto Err;		if(!mbUnpack(&mb, u->data, u->asize))			goto Err;		if(mb.nindex > 0) {			vtSetError(ENotEmpty);			goto Err;		}		lumpDecRef(u, 1);	}	return 1;Err:	lumpDecRef(u, 1);	return 0;}intvfRemove(VacFile *vf, char *user){	/* can not remove the root */	if(vfIsRoot(vf)) {		vtSetError(ERoot);		return 0;	}	if(!vfLock(vf))		return 0;	if(vfIsDir(vf) && !vfCheckEmpty(vf))		goto Err;	assert(vf->down == nil);	sourceRemove(vf->source);	vf->source = nil;	if(vf->msource) {		sourceRemove(vf->msource);		vf->msource = nil;	}	vfUnlock(vf);	if(!vfMetaRemove(vf, user))		return 0;	return 1;Err:	vfUnlock(vf);	return 0;}VacFile *vfIncRef(VacFile *vf){	vfMetaLock(vf);	assert(vf->ref > 0);	vf->ref++;	vfMetaUnlock(vf);	return vf;}voidvfDecRef(VacFile *vf){	VacFile *p, *q, **qq;	if(vf->up == nil) {		vfFree(vf);		return;	}	vfMetaLock(vf);	vf->ref--;	if(vf->ref > 0) {		vfMetaUnlock(vf);		return;	}	assert(vf->ref == 0);	assert(vf->down == nil);	p = vf->up;	qq = &p->down;	for(q = *qq; q; qq=&q->next,q=*qq)		if(q == vf)			break;	assert(q != nil);	*qq = vf->next;	vfMetaUnlock(vf);	vfFree(vf);	vfDecRef(p);}intvfGetVtEntry(VacFile *vf, VtEntry *e){	int res;	if(!vfRLock(vf))		return 0;	res = sourceGetVtEntry(vf->source, e);	vfRUnlock(vf);	return res;}#ifdef notdefintvfGetBlockScore(VacFile *vf, ulong bn, uchar score[VtScoreSize]){	Lump *u;	int ret, off;	Source *r;	if(!vfRLock(vf))		return 0;	r = vf->source;	u = sourceWalk(r, bn, 1, &off);	if(u == nil){		vfRUnlock(vf);		return 0;	}	ret = lumpGetScore(u, off, score);	lumpDecRef(u, 0);	vfRUnlock(vf);	return ret;}#endifVacFile *vfGetParent(VacFile *vf){	if(vfIsRoot(vf))		return vfIncRef(vf);	return vfIncRef(vf->up);}static VacDirEnum *vdeAlloc(VacFile *vf){	VacDirEnum *ds;	if(!(vf->dir.mode & ModeDir)) {		vtSetError(ENotDir);		vfDecRef(vf);		return nil;	}	ds = vtMemAllocZ(sizeof(VacDirEnum));	ds->file = vf;	return ds;}VacDirEnum *vdeOpen(VacFS *fs, char *path){	VacFile *vf;	vf = vfOpen(fs, path);	if(vf == nil)		return nil;	return vdeAlloc(vf);}VacDirEnum *vfDirEnum(VacFile *vf){	return vdeAlloc(vfIncRef(vf));}static intdirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size){	Lump *u;	ulong bn;	VtEntry e;	bn = elem/s->epb;	elem -= bn*s->epb;	u = sourceGetLump(s, bn, 1, 1);	if(u == nil)		goto Err;	if(u->asize < (elem+1)*VtEntrySize) {		vtSetError(ENoDir);		goto Err;	}	vtEntryUnpack(&e, u->data, elem);	if(!(e.flags & VtEntryActive) || e.gen != gen) {fprint(2, "gen mismatch\n");		vtSetError(ENoDir);		goto Err;	}	*size = e.size;	lumpDecRef(u, 1);	return 1;Err:	lumpDecRef(u, 1);	return 0;}intvdeRead(VacDirEnum *ds, VacDir *dir, int n){	ulong nb;	int i;	Source *meta, *source;	MetaBlock mb;	MetaEntry me;	Lump *u;	vfRAccess(ds->file);	if(!vfRLock(ds->file))		return -1;	i = 0;	u = nil;	source = ds->file->source;	meta = ds->file->msource;	nb = (sourceGetSize(meta) + meta->dsize - 1)/meta->dsize;	if(ds->block >= nb)		goto Exit;	u = sourceGetLump(meta, ds->block, 1, 1);	if(u == nil)		goto Err;	if(!mbUnpack(&mb, u->data, u->asize))		goto Err;	for(i=0; i<n; i++) {		while(ds->index >= mb.nindex) {			lumpDecRef(u, 1);			u = nil;			ds->index = 0;			ds->block++;			if(ds->block >= nb)				goto Exit;			u = sourceGetLump(meta, ds->block, 1, 1);			if(u == nil)				goto Err;			if(!mbUnpack(&mb, u->data, u->asize))				goto Err;		}		if(!meUnpack(&me, &mb, ds->index))			goto Err;		if(dir != nil) {			if(!vdUnpack(&dir[i], &me))				goto Err;			if(!(dir[i].mode & ModeDir))			if(!dirEntrySize(source, dir[i].entry, dir[i].gen, &dir[i].size))				goto Err;		}		ds->index++;	}Exit:	lumpDecRef(u, 1);	vfRUnlock(ds->file);	return i;Err:	lumpDecRef(u, 1);	vfRUnlock(ds->file);	n = i;	for(i=0; i<n ; i++)		vdCleanup(&dir[i]);	return -1;}voidvdeFree(VacDirEnum *ds){	if(ds == nil)		return;	vfDecRef(ds->file);	vtMemFree(ds);}static ulongmsAlloc(Source *ms, ulong start, int n){	ulong nb, i;	Lump *u;	MetaBlock mb;	nb = sourceGetNumBlocks(ms);	u = nil;	if(start > nb)		start = nb;	for(i=start; i<nb; i++) {		u = sourceGetLump(ms, i, 1, 1);		if(u == nil)			goto Err;		if(!mbUnpack(&mb, u->data, ms->dsize))			goto Err;		if(mb.maxsize - mb.size + mb.free >= n && mb.nindex < mb.maxindex)			break;		lumpDecRef(u, 1);		u = nil;	}	/* add block to meta file */	if(i == nb) {		if(!sourceSetDepth(ms, (i+1)*ms->dsize))			goto Err;		u = sourceGetLump(ms, i, 0, 1);		if(u == nil)			goto Err;		sourceSetSize(ms, (nb+1)*ms->dsize);		mbInit(&mb, u->data, u->asize);		mbPack(&mb);	}	lumpDecRef(u, 1);	return i;Err:	lumpDecRef(u, 1);	return NilBlock;}VacFS *vacfs(VacFile *vf){	if (vf == nil)		return nil;	return vf->fs;}/* * path may be nil; it's the right-hand part of the path so far. * result is malloced, path must be malloced or nil. */char *vfName(VacFile *vf, char *path){	char *nname, *rname, *elem;	if (vf == nil || vf == vf->up) {		/* at the root? */		if (path == nil)			return strdup("/");		return path;	}	elem = vf->dir.elem;	if (elem != nil && path != nil)		rname = smprint("%s/%s", elem, path);	else if (elem != nil)		rname = strdup(elem);	else		return vfName(vf->up, path);	nname = vfName(vf->up, rname);	if (nname != rname)		free(rname);	return nname;}

⌨️ 快捷键说明

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