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

📄 dosfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
//ZZZ set type for excl, append?	if(req->perm & DMDIR){		f->qid.type = QTDIR;		xp = getsect(f->xf, clust2sect(bp, start));		if(xp == nil){			errno = Eio;			goto badio;		}		xd = (Dosdir *)&xp->iobuf[0];		memmove(xd, ndp->d, DOSDIRSIZE);		memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext);		xd->name[0] = '.';		xd = (Dosdir *)&xp->iobuf[DOSDIRSIZE];		if(pd)			memmove(xd, pd, DOSDIRSIZE);		else{			memset(xd, 0, DOSDIRSIZE);			puttime(xd, 0);			xd->attr = DDIR;		}		memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext);		xd->name[0] = '.';		xd->name[1] = '.';		xp->flags |= BMOD;		putsect(xp);	}	f->flags |= omode;	rep->qid = f->qid;	rep->iounit = 0;badio:	putfile(f);	putsect(pdp->p);	free(pdp);}voidrread(void){	Xfile *f;	int r;	if (!(f=xfile(req->fid, Asis)) || !(f->flags&Oread))		goto error;	if(req->count > sizeof repdata)		req->count = sizeof repdata;	if(f->qid.type & QTDIR){		if(getfile(f) < 0)			goto error;		r = readdir(f, repdata, req->offset, req->count);	}else{		if(getfile(f) < 0)			goto error;		r = readfile(f, repdata, req->offset, req->count);	}	putfile(f);	if(r < 0){error:		errno = Eio;	}else{		rep->count = r;		rep->data = (char*)repdata;	}}voidrwrite(void){	Xfile *f;	int r;	if (!(f=xfile(req->fid, Asis)) || !(f->flags&Owrite))		goto error;	if(getfile(f) < 0)		goto error;	r = writefile(f, req->data, req->offset, req->count);	putfile(f);	if(r < 0){error:		errno = Eio;	}else{		rep->count = r;	}}voidrclunk(void){	xfile(req->fid, Clunk);	sync();}/* * wipe out a dos directory entry */static voiddoremove(Xfs *xf, Dosptr *dp){	Iosect *p;	int prevdo;	dp->p->iobuf[dp->offset] = DOSEMPTY;	dp->p->flags |= BMOD;	for(prevdo = dp->offset-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){		if(dp->p->iobuf[prevdo+11] != 0xf)			break;		dp->p->iobuf[prevdo] = DOSEMPTY;	}	if(prevdo < 0 && dp->prevaddr != -1){		p = getsect(xf, dp->prevaddr);		for(prevdo = ((Dosbpb*)xf->ptr)->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){			if(p->iobuf[prevdo+11] != 0xf)				break;			p->iobuf[prevdo] = DOSEMPTY;			p->flags |= BMOD;		}		putsect(p);	}		}voidrremove(void){	Xfile *f;	Dosptr *dp;	Iosect *parp;	Dosdir *pard;	f = xfile(req->fid, Asis);	parp = nil;	if(f == nil){		errno = Eio;		goto out;	}	dp = f->ptr;	if(isroot(dp->addr)){		errno = Eperm;		goto out;	}	/*	 * can't remove if parent is read only,	 * it's a non-empty directory,	 * or it's a read only file in the root directory	 */	parp = getsect(f->xf, dp->paddr);	if(parp == nil	|| getfile(f) < 0){		errno = Eio;		goto out;	}	pard = (Dosdir *)&parp->iobuf[dp->poffset];	if(!isroot(dp->paddr) && (pard->attr & DRONLY)	|| (dp->d->attr & DDIR) && emptydir(f) < 0	|| isroot(dp->paddr) && (dp->d->attr&DRONLY)){		errno = Eperm;		goto out;	}	if(truncfile(f, 0) < 0){		errno = Eio;		goto out;	}	doremove(f->xf, f->ptr);	if(!isroot(dp->paddr)){		puttime(pard, 0);		parp->flags |= BMOD;	}out:	if(parp != nil)		putsect(parp);	if(f != nil)		putfile(f);	xfile(req->fid, Clunk);	sync();}static voiddostat(Xfile *f, Dir *d){	Dosptr *dp;	Iosect *p;	char *name, namebuf[DOSNAMELEN];	int islong, sum, prevdo;	dp = f->ptr;	if(isroot(dp->addr)){		memset(d, 0, sizeof(Dir));		d->name = "/";		d->qid.type = QTDIR;		d->qid.path = f->xf->rootqid.path;		d->mode = DMDIR|0777;		d->uid = "bill";		d->muid = "bill";		d->gid = "trog";	}else{		/*		 * assemble any long file name		 */		sum = aliassum(dp->d);		islong = 0;		name = namebuf;		for(prevdo = dp->offset-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){			if(dp->p->iobuf[prevdo+11] != 0xf)				break;			name = getnamesect(namebuf, name, &dp->p->iobuf[prevdo], &islong, &sum, -1);		}		if(prevdo < 0 && dp->prevaddr != -1){			p = getsect(f->xf, dp->prevaddr);			for(prevdo = ((Dosbpb*)f->xf->ptr)->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){				if(p->iobuf[prevdo+11] != 0xf)					break;				name = getnamesect(namebuf, name, &p->iobuf[prevdo], &islong, &sum, -1);			}			putsect(p);		}		getdir(f->xf, d, dp->d, dp->addr, dp->offset);		if(islong && sum == -1 && nameok(namebuf))			strcpy(d->name, namebuf);	}}voidrstat(void){	Dir dir;	Xfile *f;	f = xfile(req->fid, Asis);	if(!f || getfile(f) < 0){		errno = Eio;		return;	}	dir.name = repdata;	dostat(f, &dir);	rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);	rep->stat = statbuf;	putfile(f);}voidrwstat(void){	Dir dir, wdir;	Xfile *f, pf;	Dosptr *dp, ndp, pdp;	Iosect *parp;	Dosdir *pard, *d, od;	char sname[13];	ulong oaddr, ooffset;	long start, length;	int i, longtype, changes, attr;	f = xfile(req->fid, Asis);	if(!f || getfile(f) < 0){		errno = Eio;		return;	}	dp = f->ptr;	if(isroot(dp->addr)){		errno = Eperm;		goto out;	}	changes = 0;	dir.name = repdata;	dostat(f, &dir);	if(convM2D(req->stat, req->nstat, &wdir, (char*)statbuf) != req->nstat){		errno = Ebadstat;		goto out;	}	/*	 * To change length, must have write permission on file.	 * we only allow truncates for now.	 */	if(wdir.length!=~0 && wdir.length!=dir.length){		if(wdir.length > dir.length || !dir.mode & 0222){			errno = Eperm;			goto out;		}	}	/*	 * no chown or chgrp	 */	if(wdir.uid[0] != '\0' && strcmp(dir.uid, wdir.uid) != 0	|| wdir.gid[0] != '\0' && strcmp(dir.gid, wdir.gid) != 0){		errno = Eperm;		goto out;	}	/*	 * mode/mtime allowed	 */	if(wdir.mtime != ~0 && dir.mtime != wdir.mtime)		changes = 1;	/*	 * Setting DMAPPEND (make system file contiguous)	 * requires setting DMEXCL (system file).	 */	if(wdir.mode != ~0){		if((wdir.mode & 7) != ((wdir.mode >> 3) & 7)		|| (wdir.mode & 7) != ((wdir.mode >> 6) & 7)){			errno = Eperm;			goto out;		}		if((dir.mode^wdir.mode) & (DMEXCL|DMAPPEND|0777))			changes = 1;		if((dir.mode^wdir.mode) & DMAPPEND) {			if((wdir.mode & (DMEXCL|DMAPPEND)) == DMAPPEND) {				errno = Eperm;				goto out;			}			if((wdir.mode & DMAPPEND) && makecontig(f, 0) < 0) {				errno = Econtig;				goto out;			}		}	}	/*	 * to rename:	 *	1) make up a fake clone	 *	2) walk to parent	 *	3) remove the old entry	 *	4) create entry with new name	 *	5) write correct mode/mtime info	 * we need to remove the old entry before creating the new one	 * to avoid a lock loop.	 */	if(wdir.name[0] != '\0' && strcmp(dir.name, wdir.name) != 0){		if(utflen(wdir.name) >= DOSNAMELEN){			errno = Etoolong;			goto out;		}		/*		 * grab parent directory of file to be changed and check for write perm		 * rename also disallowed for read-only files in root directory		 */		parp = getsect(f->xf, dp->paddr);		if(parp == nil){			errno = Eio;			goto out;		}		pard = (Dosdir *)&parp->iobuf[dp->poffset];		if(!isroot(dp->paddr) && (pard->attr & DRONLY)		|| isroot(dp->paddr) && (dp->d->attr&DRONLY)){			putsect(parp);			errno = Eperm;			goto out;		}		/*		 * retrieve info from old entry		 */		oaddr = dp->addr;		ooffset = dp->offset;		d = dp->d;		od = *d;		start = getstart(f->xf, d);		length = GLONG(d->length);		attr = d->attr;		/*		 * temporarily release file to allow other directory ops:		 * walk to parent, validate new name		 * then remove old entry		 */		putfile(f);		pf = *f;		memset(&pdp, 0, sizeof(Dosptr));		pdp.prevaddr = -1;		pdp.naddr = -1;		pdp.addr = dp->paddr;		pdp.offset = dp->poffset;		pdp.p = parp;		if(!isroot(pdp.addr))			pdp.d = (Dosdir *)&parp->iobuf[pdp.offset];		pf.ptr = &pdp;		longtype = mk8dot3name(&pf, &ndp, wdir.name, sname);		if(longtype==Invalid){			putsect(parp);			errno = Eperm;			return;		}		if(getfile(f) < 0){			putsect(parp);			errno = Eio;			return;		}		doremove(f->xf, dp);		putfile(f);		/*		 * search for dir entry again, since we may be able to use the old slot,		 * and we need to set up the naddr field if a long name spans the block.		 * create new entry.		 */		if(searchdir(&pf, wdir.name, dp, 1, longtype) < 0		|| mkdentry(pf.xf, dp, wdir.name, sname, longtype, attr, start, length) < 0){			putsect(parp);			errno = Eio;			goto out;		}		/*		 * copy invisible fields		 */		d = dp->d;		for(i = 0; i < 2; i++)			d->ctime[i] = od.ctime[i];		for(i = 0; i < nelem(od.cdate); i++)			d->cdate[i] = od.cdate[i];		for(i = 0; i < nelem(od.adate); i++)			d->adate[i] = od.adate[i];		putsect(parp);		/*		 * relocate up other fids to the same file, if it moved		 */		f->qid.path = QIDPATH(dp);		if(oaddr != dp->addr || ooffset != dp->offset)			dosptrreloc(f, dp, oaddr, ooffset);		/*		 * copy fields that are not supposed to change		 */		if(wdir.mtime == ~0)			wdir.mtime = dir.mtime;		if(wdir.mode == ~0)			wdir.mode = dir.mode;		changes = 1;	}	/*	 * do the actual truncate	 */	if(wdir.length != ~0 && wdir.length != dir.length && truncfile(f, wdir.length) < 0)		errno = Eio;	if(changes){		putdir(dp->d, &wdir);		dp->p->flags |= BMOD;	}out:	putfile(f);	sync();}

⌨️ 快捷键说明

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