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

📄 xfile.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include "iotrack.h"#include "dat.h"#include "fns.h"#define	FIDMOD	127	/* prime */static Xfs	*xhead;static Xfile	*xfiles[FIDMOD], *freelist;static MLock	xlock, xlocks[FIDMOD], freelock;static intokmode(int omode, int fmode){	if(omode == OREAD)		return fmode & 4;	/* else ORDWR */	return (fmode & 6) == 6;}Xfs *getxfs(char *user, char *name){	Xfs *xf, *fxf;	Dir *dir;	Qid dqid;	char *p, *q;	long offset;	int fd, omode;	USED(user);	if(name==nil || name[0]==0)		name = deffile;	if(name == nil){		errno = Enofilsys;		return 0;	}	/*	 * If the name passed is of the form 'name:offset' then	 * offset is used to prime xf->offset. This allows accessing	 * a FAT-based filesystem anywhere within a partition.	 * Typical use would be to mount a filesystem in the presence	 * of a boot manager programme at the beginning of the disc.	 */	offset = 0;	if(p = strrchr(name, ':')){		*p++ = 0;		offset = strtol(p, &q, 0);		chat("name %s, offset %ld\n", p, offset);		if(offset < 0 || p == q){			errno = Enofilsys;			return 0;		}		offset *= Sectorsize;	}	if(readonly)		omode = OREAD;	else		omode = ORDWR;	fd = open(name, omode);	if(fd < 0 && omode==ORDWR){		omode = OREAD;		fd = open(name, omode);	}	if(fd < 0){		chat("can't open %s: %r\n", name);		errno = Eerrstr;		return 0;	}	dir = dirfstat(fd);	if(dir == nil){		errno = Eio;		close(fd);		return 0;	}	dqid = dir->qid;	free(dir);	mlock(&xlock);	for(fxf=0,xf=xhead; xf; xf=xf->next){		if(xf->ref == 0){			if(fxf == 0)				fxf = xf;			continue;		}		if(!eqqid(xf->qid, dqid))			continue;		if(strcmp(xf->name, name) != 0 || xf->dev < 0)			continue;		if(devcheck(xf) < 0) /* look for media change */			continue;		if(offset && xf->offset != offset)			continue;		chat("incref \"%s\", dev=%d...", xf->name, xf->dev);		++xf->ref;		unmlock(&xlock);		close(fd);		return xf;	}	if(fxf == nil){		fxf = malloc(sizeof(Xfs));		if(fxf == nil){			unmlock(&xlock);			close(fd);			errno = Enomem;			return nil;		}		fxf->next = xhead;		xhead = fxf;	}	chat("alloc \"%s\", dev=%d...", name, fd);	fxf->name = strdup(name);	fxf->ref = 1;	fxf->qid = dqid;	fxf->dev = fd;	fxf->fmt = 0;	fxf->offset = offset;	fxf->ptr = nil;	fxf->isfat32 = 0;	fxf->omode = omode;	unmlock(&xlock);	return fxf;}voidrefxfs(Xfs *xf, int delta){	mlock(&xlock);	xf->ref += delta;	if(xf->ref == 0){		chat("free \"%s\", dev=%d...", xf->name, xf->dev);		free(xf->name);		free(xf->ptr);		purgebuf(xf);		if(xf->dev >= 0){			close(xf->dev);			xf->dev = -1;		}	}	unmlock(&xlock);}Xfile *xfile(int fid, int flag){	Xfile **hp, *f, *pf;	int k;	k = ((ulong)fid) % FIDMOD;	hp = &xfiles[k];	mlock(&xlocks[k]);	pf = nil;	for(f=*hp; f; f=f->next){		if(f->fid == fid)			break;		pf = f;	}	if(f && pf){		pf->next = f->next;		f->next = *hp;		*hp = f;	}	switch(flag){	default:		panic("xfile");	case Asis:		unmlock(&xlocks[k]);		return (f && f->xf && f->xf->dev < 0) ? nil : f;	case Clean:		break;	case Clunk:		if(f){			*hp = f->next;			unmlock(&xlocks[k]);			clean(f);			mlock(&freelock);			f->next = freelist;			freelist = f;			unmlock(&freelock);		} else			unmlock(&xlocks[k]);		return nil;	}	unmlock(&xlocks[k]);	if(f)		return clean(f);	mlock(&freelock);	if(f = freelist){	/* assign = */		freelist = f->next;		unmlock(&freelock);	} else {		unmlock(&freelock);		f = malloc(sizeof(Xfile));		if(f == nil){			errno = Enomem;			return nil;		}	}	mlock(&xlocks[k]);	f->next = *hp;	*hp = f;	unmlock(&xlocks[k]);	f->fid = fid;	f->flags = 0;	f->qid = (Qid){0,0,0};	f->xf = nil;	f->ptr = nil;	return f;}Xfile *clean(Xfile *f){	if(f->ptr){		free(f->ptr);		f->ptr = nil;	}	if(f->xf){		refxfs(f->xf, -1);		f->xf = nil;	}	f->flags = 0;	f->qid = (Qid){0,0,0};	return f;}/* * the file at <addr, offset> has moved * relocate the dos entries of all fids in the same file */voiddosptrreloc(Xfile *f, Dosptr *dp, ulong addr, ulong offset){	int i;	Xfile *p;	Dosptr *xdp;	for(i=0; i < FIDMOD; i++){		for(p = xfiles[i]; p != nil; p = p->next){			xdp = p->ptr;			if(p != f && p->xf == f->xf			&& xdp != nil && xdp->addr == addr && xdp->offset == offset){				memmove(xdp, dp, sizeof(Dosptr));				xdp->p = nil;				xdp->d = nil;				p->qid.path = QIDPATH(xdp);			}		}	}}

⌨️ 快捷键说明

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