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

📄 dosfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include "iotrack.h"#include "dat.h"#include "dosfs.h"#include "fns.h"voidrversion(void){	if(req->msize > Maxiosize)		rep->msize = Maxiosize;	else		rep->msize = req->msize;	rep->version = "9P2000";}voidrauth(void){	errno = Enoauth;}voidrflush(void){}voidrattach(void){	Xfs *xf;	Xfile *root;	Dosptr *dp;	root = xfile(req->fid, Clean);	if(!root){		errno = Enomem;		goto error;	}	root->xf = xf = getxfs(req->uname, req->aname);	if(!xf)		goto error;	if(xf->fmt == 0 && dosfs(xf) < 0){		errno = Eformat;		goto error;	}	root->qid.type = QTDIR;	root->qid.path = 0;	root->qid.vers = 0;	root->xf->rootqid = root->qid;	dp = malloc(sizeof(Dosptr));	if(dp == nil){		errno = Enomem;		goto error;	}	root->ptr = dp;	rootfile(root);	rep->qid = root->qid;	return;error:	if(root)		xfile(req->fid, Clunk);}Xfile*doclone(Xfile *of, int newfid){	Xfile *nf, *next;	Dosptr *dp;	nf = xfile(newfid, Clean);	if(!nf){		errno = Enomem;		return nil;	}	dp = malloc(sizeof(Dosptr));	if(dp == nil){		errno = Enomem;		return nil;	}	next = nf->next;	*nf = *of;	nf->next = next;	nf->fid = req->newfid;	nf->ptr = dp;	refxfs(nf->xf, 1);	memmove(dp, of->ptr, sizeof(Dosptr));	dp->p = nil;	dp->d = nil;	return nf;}voidrwalk(void){	Xfile *f, *nf;	Dosptr dp[1], savedp[1];	int r, longtype;	Qid saveqid;	rep->nwqid = 0;	nf = nil;	f = xfile(req->fid, Asis);	if(f == nil){		chat("\tno xfile\n");		goto error2;	}	if(req->fid != req->newfid){		nf = doclone(f, req->newfid);		if(nf == nil){			chat("\tclone failed\n");			goto error2;		}		f = nf;	}	saveqid = f->qid;	memmove(savedp, f->ptr, sizeof(Dosptr));	for(; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){		chat("\twalking %s\n", req->wname[rep->nwqid]);		if(!(f->qid.type & QTDIR)){			chat("\tnot dir: type=%#x\n", f->qid.type);			goto error;		}		if(strcmp(req->wname[rep->nwqid], ".") == 0){			;		}else if(strcmp(req->wname[rep->nwqid], "..") == 0){			if(f->qid.path != f->xf->rootqid.path){				r = walkup(f, dp);				if(r < 0)					goto error;				memmove(f->ptr, dp, sizeof(Dosptr));				if(isroot(dp->addr))					f->qid.path = f->xf->rootqid.path;				else					f->qid.path = QIDPATH(dp);			}		}else{			fixname(req->wname[rep->nwqid]);			longtype = classifyname(req->wname[rep->nwqid]);			if(longtype==Invalid || getfile(f) < 0)				goto error;			/*			 * always do a search for the long name,			 * because it could be filed as such			 */			r = searchdir(f, req->wname[rep->nwqid], dp, 0, longtype);			putfile(f);			if(r < 0)				goto error;			memmove(f->ptr, dp, sizeof(Dosptr));			f->qid.path = QIDPATH(dp);			f->qid.type = QTFILE;			if(isroot(dp->addr))				f->qid.path = f->xf->rootqid.path;			else if(dp->d->attr & DDIR)				f->qid.type = QTDIR;			else if(dp->d->attr & DSYSTEM){				f->qid.type |= QTEXCL;				if(iscontig(f->xf, dp->d))					f->qid.type |= QTAPPEND;			}//ZZZ maybe use other bits than qtexcl & qtapppend			putfile(f);		}		rep->wqid[rep->nwqid] = f->qid;	}	return;error:	f->qid = saveqid;	memmove(f->ptr, savedp, sizeof(Dosptr));	if(nf != nil)		xfile(req->newfid, Clunk);error2:	if(!errno && !rep->nwqid)		errno = Enonexist;}voidropen(void){	Xfile *f;	Iosect *p;	Dosptr *dp;	int attr, omode;	f = xfile(req->fid, Asis);	if(!f || (f->flags&Omodes)){		errno = Eio;		return;	}	dp = f->ptr;	omode = 0;	if(!isroot(dp->paddr) && (req->mode & ORCLOSE)){		/*		 * check on parent directory of file to be deleted		 */		p = getsect(f->xf, dp->paddr);		if(p == nil){			errno = Eio;			return;		}		attr = ((Dosdir *)&p->iobuf[dp->poffset])->attr;		putsect(p);		if(attr & DRONLY){			errno = Eperm;			return;		}		omode |= Orclose;	}else if(req->mode & ORCLOSE)		omode |= Orclose;	if(getfile(f) < 0){		errno = Enonexist;		return;	}	if(!isroot(dp->addr))		attr = dp->d->attr;	else		attr = DDIR;	switch(req->mode & 7){	case OREAD:	case OEXEC:		omode |= Oread;		break;	case ORDWR:		omode |= Oread;		/* fall through */	case OWRITE:		omode |= Owrite;		if(attr & DRONLY){			errno = Eperm;			goto out;		}		break;	default:		errno = Eio;		goto out;	}	if(req->mode & OTRUNC){		if(attr & DDIR || attr & DRONLY){			errno = Eperm;			goto out;		}		if(truncfile(f, 0) < 0){			errno = Eio;			goto out;		}	}	f->flags |= omode;	rep->qid = f->qid;	rep->iounit = 0;out:	putfile(f);}static intmk8dot3name(Xfile *f, Dosptr *ndp, char *name, char *sname){	Dosptr tmpdp;	int i, longtype;	if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)		return Invalid;	/*	 * always do a search for the long name,	 * because it could be filed as such	 */	fixname(name);	longtype = classifyname(name);	if(longtype==Invalid || searchdir(f, name, ndp, 1, longtype) < 0)		return Invalid;	if(longtype==Short)		return Short;	if(longtype==ShortLower){		/*		 * alias is the upper-case version, which we		 * already know does not exist.		 */		strcpy(sname, name);		for(i=0; sname[i]; i++)			if('a' <= sname[i] && sname[i] <= 'z')				sname[i] += 'A'-'a';		return ShortLower;	}	/*	 * find alias for the long name	 */	for(i=1;; i++){		mkalias(name, sname, i);		if(searchdir(f, sname, &tmpdp, 0, 0) < 0)			return Long;		putsect(tmpdp.p);	}}/* * fill in a directory entry for a new file */static intmkdentry(Xfs *xf, Dosptr *ndp, char *name, char *sname, int longtype, int nattr, long start, long length){	Dosdir *nd;	/*	 * fill in the entry	 */	ndp->p = getsect(xf, ndp->addr);	if(ndp->p == nil	|| longtype!=Short && putlongname(xf, ndp, name, sname) < 0){		errno = Eio;		return -1;	}	ndp->d = (Dosdir *)&ndp->p->iobuf[ndp->offset];	nd = ndp->d;	memset(nd, 0, DOSDIRSIZE);	if(longtype!=Short)		name = sname;	putname(name, nd);	nd->attr = nattr;	puttime(nd, 0);	putstart(xf, nd, start);	nd->length[0] = length;	nd->length[1] = length>>8;	nd->length[2] = length>>16;	nd->length[3] = length>>24;	ndp->p->flags |= BMOD;	return 0;}voidrcreate(void){	Dosbpb *bp;	Xfile *f;	Dosptr *pdp, *ndp;	Iosect *xp;	Dosdir *pd, *xd;	char sname[13];	long start;	int longtype, attr, omode, nattr;	f = xfile(req->fid, Asis);	if(!f || (f->flags&Omodes) || getfile(f)<0){		errno = Eio;		return;	}	pdp = f->ptr;	pd = pdp->d;	/*	 * perm check	 */	if(isroot(pdp->addr) && pd != nil)		panic("root pd != nil");	attr = pd ? pd->attr : DDIR;	if(!(attr & DDIR) || (attr & DRONLY)){badperm:		putfile(f);		errno = Eperm;		return;	}	omode = 0;	if(req->mode & ORCLOSE)		omode |= Orclose;	switch(req->mode & 7){	case OREAD:	case OEXEC:		omode |= Oread;		break;	case ORDWR:		omode |= Oread;		/* fall through */	case OWRITE:		omode |= Owrite;		if(req->perm & DMDIR)			goto badperm;		break;	default:		goto badperm;	}	/*	 * check the name, find the slot for the dentry,	 * and find a good alias for a long name	 */	ndp = malloc(sizeof(Dosptr));	if(ndp == nil){		putfile(f);		errno = Enomem;		return;	}	longtype = mk8dot3name(f, ndp, req->name, sname);	chat("rcreate %s longtype %d...\n", req->name, longtype);	if(longtype == Invalid){		free(ndp);		goto badperm;	}	/*	 * allocate first cluster, if making directory	 */	start = 0;	bp = nil;	if(req->perm & DMDIR){		bp = f->xf->ptr;		mlock(bp);		start = falloc(f->xf);		unmlock(bp);		if(start <= 0){			free(ndp);			putfile(f);			errno = Eio;			return;		}	}	/*	 * make the entry	 */	nattr = 0;	if((req->perm & 0222) == 0)		nattr |= DRONLY;	if(req->perm & DMDIR)		nattr |= DDIR;	if(mkdentry(f->xf, ndp, req->name, sname, longtype, nattr, start, 0) < 0){		if(ndp->p != nil)			putsect(ndp->p);		free(ndp);		if(start > 0)			ffree(f->xf, start);		putfile(f);		return;	}	if(pd != nil){		puttime(pd, 0);		pdp->p->flags |= BMOD;	}	/*	 * fix up the fid	 */	f->ptr = ndp;	f->qid.type = QTFILE;	f->qid.path = QIDPATH(ndp);

⌨️ 快捷键说明

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