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

📄 9p2.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * if remove on close, check access here	 */	ro = isro(file->fs->dev) || (writegroup && !ingroup(file->uid, writegroup));	if(f->mode & ORCLOSE){		if(ro){			error = Eronly;			goto out;		}		/*		 * check on parent directory of file to be deleted		 */		if(file->wpath == 0 || file->wpath->addr == file->addr){			error = Ephase;			goto out;		}		p = getbuf(file->fs->dev, file->wpath->addr, Bread);		if(p == nil || checktag(p, Tdir, QPNONE)){			error = Ephase;			goto out;		}		if((d = getdir(p, file->wpath->slot)) == nil || !(d->mode & DALLOC)){			error = Ephase;			goto out;		}		if(iaccess(file, d, DWRITE)){			error = Eaccess;			goto out;		}		putbuf(p);	}	p = getbuf(file->fs->dev, file->addr, Bread);	if(p == nil || checktag(p, Tdir, QPNONE)){		error = Ealloc;		goto out;	}	if((d = getdir(p, file->slot)) == nil || !(d->mode & DALLOC)){		error = Ealloc;		goto out;	}	if(error = mkqidcmp(&file->qid, d))		goto out;	mkqid(&qid, d, 1);	switch(f->mode & 7){	case OREAD:		if(iaccess(file, d, DREAD) && !wok)			goto badaccess;		fmod = FREAD;		break;	case OWRITE:		if((d->mode & DDIR) || (iaccess(file, d, DWRITE) && !wok))			goto badaccess;		if(ro){			error = Eronly;			goto out;		}		fmod = FWRITE;		break;	case ORDWR:		if((d->mode & DDIR)		|| (iaccess(file, d, DREAD) && !wok)		|| (iaccess(file, d, DWRITE) && !wok))			goto badaccess;		if(ro){			error = Eronly;			goto out;		}		fmod = FREAD+FWRITE;		break;	case OEXEC:		if((d->mode & DDIR) || (iaccess(file, d, DEXEC) && !wok))			goto badaccess;		fmod = FREAD;		break;	default:		error = Emode;		goto out;	}	if(f->mode & OTRUNC){		if((d->mode & DDIR) || (iaccess(file, d, DWRITE) && !wok))			goto badaccess;		if(ro){			error = Eronly;			goto out;		}	}	t = 0;	if(d->mode & DLOCK){		if((t = tlocked(p, d)) == nil){			error = Elocked;			goto out;		}	}	if(f->mode & ORCLOSE)		fmod |= FREMOV;	file->open = fmod;	if((f->mode & OTRUNC) && !(d->mode & DAPND)){		dtrunc(p, d);		qid.vers = d->qid.version;	}	r->qid = qid;	file->tlock = t;	if(t != nil)		t->file = file;	file->lastra = 1;	goto out;badaccess:	error = Eaccess;	file->open = 0;out:	if(p != nil)		putbuf(p);	if(file != nil)		qunlock(file);	r->iounit = chan->msize-IOHDRSZ;	return error;}static intdir9p2(Dir* dir, Dentry* dentry, void* strs){	char *op, *p;	memset(dir, 0, sizeof(Dir));	mkqid(&dir->qid, dentry, 1);	dir->mode = (dir->qid.type<<24)|(dentry->mode & 0777);	dir->atime = dentry->atime;	dir->mtime = dentry->mtime;	dir->length = dentry->size;	op = p = strs;	dir->name = p;	p += sprint(p, "%s", dentry->name)+1;	dir->uid = p;	uidtostr(p, dentry->uid);	p += strlen(p)+1;	dir->gid = p;	uidtostr(p, dentry->gid);	p += strlen(p)+1;	dir->muid = p;	strcpy(p, "");	p += strlen(p)+1;	return p-op;}static intcheckname9p2(char* name){	char *p;	/*	 * Return length of string if valid, 0 if not.	 */	if(name == nil)		return 0;	for(p = name; *p != 0; p++){		if((*p & 0xFF) <= 040)			return 0;	}	return p-name;}static intfscreate(Chan* chan, Fcall* f, Fcall* r){	Iobuf *p, *p1;	Dentry *d, *d1;	File *file;	int error, slot, slot1, fmod, wok, l;	long addr, addr1, path;	Tlock *t;	Wpath *w;	wok = 0;	p = nil;	if(chan == cons.chan || writeallow)		wok = 1;	if((file = filep(chan, f->fid, 0)) == nil){		error = Efid;		goto out;	}	if(isro(file->fs->dev) || (writegroup && !ingroup(file->uid, writegroup))){		error = Eronly;		goto out;	}	p = getbuf(file->fs->dev, file->addr, Bread);	if(p == nil || checktag(p, Tdir, QPNONE)){		error = Ealloc;		goto out;	}	if((d = getdir(p, file->slot)) == nil || !(d->mode & DALLOC)){		error = Ealloc;		goto out;	}	if(error = mkqidcmp(&file->qid, d))		goto out;	if(!(d->mode & DDIR)){		error = Edir2;		goto out;	}	if(iaccess(file, d, DWRITE) && !wok) {		error = Eaccess;		goto out;	}	accessdir(p, d, FREAD);	/*	 * Check the name is valid and will fit in an old	 * directory entry.	 */	if((l = checkname9p2(f->name)) == 0){		error = Ename;		goto out;	}	if(l+1 > NAMELEN){		error = Etoolong;		goto out;	}	if(strcmp(f->name, ".") == 0 || strcmp(f->name, "..") == 0){		error = Edot;		goto out;	}	addr1 = 0;	slot1 = 0;	/* set */	for(addr = 0; ; addr++){		if((p1 = dnodebuf(p, d, addr, 0)) == nil){			if(addr1 != 0)				break;			p1 = dnodebuf(p, d, addr, Tdir);		}		if(p1 == nil){			error = Efull;			goto out;		}		if(checktag(p1, Tdir, d->qid.path)){			putbuf(p1);			goto phase;		}		for(slot = 0; slot < DIRPERBUF; slot++){			d1 = getdir(p1, slot);			if(!(d1->mode & DALLOC)){				if(addr1 == 0){					addr1 = p1->addr;					slot1 = slot + addr*DIRPERBUF;				}				continue;			}			if(strncmp(f->name, d1->name, sizeof(d1->name)) == 0){				putbuf(p1);				error = Eexist;				goto out;			}		}		putbuf(p1);	}	switch(f->mode & 7){	case OEXEC:	case OREAD:		/* seems only useful to make directories */		fmod = FREAD;		break;	case OWRITE:		fmod = FWRITE;		break;	case ORDWR:		fmod = FREAD+FWRITE;		break;	default:		error = Emode;		goto out;	}	if(f->perm & PDIR)		if((f->mode & OTRUNC) || (f->perm & PAPND) || (fmod & FWRITE))			goto badaccess;	/*	 * do it	 */	path = qidpathgen(&file->fs->dev);	if((p1 = getbuf(file->fs->dev, addr1, Bread|Bimm|Bmod)) == nil)		goto phase;	d1 = getdir(p1, slot1);	if(d1 == nil || checktag(p1, Tdir, d->qid.path)) {		putbuf(p1);		goto phase;	}	if(d1->mode & DALLOC){		putbuf(p1);		goto phase;	}	strncpy(d1->name, f->name, sizeof(d1->name));	if(chan == cons.chan){		d1->uid = cons.uid;		d1->gid = cons.gid;	}	else{		d1->uid = file->uid;		d1->gid = d->gid;		f->perm &= d->mode | ~0666;		if(f->perm & PDIR)			f->perm &= d->mode | ~0777;	}	d1->qid.path = path;	d1->qid.version = 0;	d1->mode = DALLOC | (f->perm & 0777);	if(f->perm & PDIR) {		d1->mode |= DDIR;		d1->qid.path |= QPDIR;	}	if(f->perm & PAPND)		d1->mode |= DAPND;	t = nil;	if(f->perm & PLOCK){		d1->mode |= DLOCK;		t = tlocked(p1, d1);		/* if nil, out of tlock structures */	}	accessdir(p1, d1, FWRITE);	mkqid(&r->qid, d1, 0);	putbuf(p1);	accessdir(p, d, FWRITE);	/*	 * do a walk to new directory entry	 */	if((w = newwp()) == nil){		error = Ewalk;		goto out;	}	w->addr = file->addr;	w->slot = file->slot;	w->up = file->wpath;	file->wpath = w;	file->qid = r->qid;	file->tlock = t;	if(t != nil)		t->file = file;	file->lastra = 1;	if(f->mode & ORCLOSE)		fmod |= FREMOV;	file->open = fmod;	file->addr = addr1;	file->slot = slot1;	goto out;badaccess:	error = Eaccess;	goto out;phase:	error = Ephase;out:	if(p != nil)		putbuf(p);	if(file != nil)		qunlock(file);	r->iounit = chan->msize-IOHDRSZ;	return error;}static intfsread(Chan* chan, Fcall* f, Fcall* r){	uchar *data;	Iobuf *p, *p1;	File *file;	Dentry *d, *d1;	Tlock *t;	long addr, offset, start, tim;	int error, iounit, nread, count, n, o, slot;	Dir dir;	char strdata[28*10];	p = nil;	data = (uchar*)r->data;	count = f->count;	offset = f->offset;	nread = 0;	if((file = filep(chan, f->fid, 0)) == nil){		error = Efid;		goto out;	}	if(file->qid.type & QTAUTH){		nread = authread(file, data, count);		if(nread < 0)			error = Esystem;		else			error = 0;		goto out;	}	if(!(file->open & FREAD)){		error = Eopen;		goto out;	}	iounit = chan->msize-IOHDRSZ;	if(count < 0 || count > iounit){		error = Ecount;		goto out;	}	if(offset < 0){		error = Eoffset;		goto out;	}	p = getbuf(file->fs->dev, file->addr, Bread);	if(p == nil || checktag(p, Tdir, QPNONE)){		error = Ealloc;		goto out;	}	if((d = getdir(p, file->slot)) == nil || !(d->mode & DALLOC)){		error = Ealloc;		goto out;	}	if(error = mkqidcmp(&file->qid, d))		goto out;	if(t = file->tlock){		tim = time(0);		if(t->time < tim || t->file != file){			error = Ebroken;			goto out;		}		/* renew the lock */		t->time = tim + TLOCK;	}	accessdir(p, d, FREAD);	if(d->mode & DDIR)		goto dread;	if(offset+count > d->size)		count = d->size - offset;	while(count > 0){		if(p == nil){			p = getbuf(file->fs->dev, file->addr, Bread);			if(p == nil || checktag(p, Tdir, QPNONE)){				error = Ealloc;				goto out;			}			if((d = getdir(p, file->slot)) == nil || !(d->mode & DALLOC)){				error = Ealloc;				goto out;			}		}		addr = offset / BUFSIZE;		o = offset % BUFSIZE;		n = BUFSIZE - o;		if(n > count)			n = count;		p1 = dnodebuf1(p, d, addr, 0);		p = nil;		if(p1 != nil){			if(checktag(p1, Tfile, QPNONE)){				error = Ephase;				putbuf(p1);				goto out;			}			memmove(data+nread, p1->iobuf+o, n);			putbuf(p1);		}		else			memset(data+nread, 0, n);		count -= n;		nread += n;		offset += n;	}	goto out;dread:	/*	 * Pick up where we left off last time if nothing has changed,	 * otherwise must scan from the beginning.	 */	if(offset == file->doffset /*&& file->qid.vers == file->dvers*/){		addr = file->dslot/DIRPERBUF;		slot = file->dslot%DIRPERBUF;		start = offset;	}	else{		addr = 0;		slot = 0;		start = 0;	}dread1:	if(p == nil){		/*		 * This is just a check to ensure the entry hasn't		 * gone away during the read of each directory block.		 */		p = getbuf(file->fs->dev, file->addr, Bread);		if(p == nil || checktag(p, Tdir, QPNONE)){			error = Ealloc;			goto out1;		}		if((d = getdir(p, file->slot)) == nil || !(d->mode & DALLOC)){			error = Ealloc;			goto out1;		}	}	p1 = dnodebuf1(p, d, addr, 0);	p = nil;	if(p1 == nil)		goto out1;	if(checktag(p1, Tdir, QPNONE)){		error = Ephase;		putbuf(p1);		goto out1;	}	for(; slot < DIRPERBUF; slot++){		d1 = getdir(p1, slot);		if(!(d1->mode & DALLOC))			continue;		dir9p2(&dir, d1, strdata);		if((n = convD2M(&dir, data+nread, iounit - nread)) <= BIT16SZ){			putbuf(p1);			goto out1;		}		start += n;		if(start < offset)			continue;		if(count < n){			putbuf(p1);			goto out1;		}		count -= n;		nread += n;		offset += n;	}	putbuf(p1);	slot = 0;	addr++;	goto dread1;out1:	if(error == 0){		file->doffset = offset;		file->dvers = file->qid.vers;		file->dslot = slot+DIRPERBUF*addr;	}out:	/*	 * Do we need this any more?	count = f->count - nread;	if(count > 0)		memset(data+nread, 0, count);	 */	if(p != nil)		putbuf(p);	if(file != nil)		qunlock(file);	r->count = nread;	r->data = (char*)data;	return error;}static intfswrite(Chan* chan, Fcall* f, Fcall* r){	Iobuf *p, *p1;	Dentry *d;	File *file;	Tlock *t;	long offset, addr, tim, qpath;	int count, error, nwrite, o, n;	offset = f->offset;	count = f->count;	nwrite = 0;	p = nil;	if((file = filep(chan, f->fid, 0)) == nil){		error = Efid;		goto out;	}	if(file->qid.type & QTAUTH){		nwrite = authwrite(file, (uchar*)f->data, count);		if(nwrite < 0)			error = Esystem;		else			error = 0;		goto out;	}	if(!(file->open & FWRITE)){		error = Eopen;		goto out;	}	if(isro(file->fs->dev) || (writegroup && !ingroup(file->uid, writegroup))){		error = Eronly;		goto out;	}	if(count < 0 || count > chan->msize-IOHDRSZ){		error = Ecount;		goto out;	}	if(offset < 0) {		error = Eoffset;

⌨️ 快捷键说明

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