Echo Lineinitial commit9fd65008 years agoHistory
837 lines · 12.6 KB · C
RawDownload
#include	"u.h"#include	"lib.h"#include	"dat.h"#include	"fns.h"#include	"error.h" Chan*fdtochan(int fd, int mode, int chkmnt, int iref){	Fgrp *f;	Chan *c; 	c = 0;	f = up->fgrp; 	lock(&f->ref.lk);	if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) {		unlock(&f->ref.lk);		error(Ebadfd);	}	if(iref)		refinc(&c->ref);	unlock(&f->ref.lk); 	if(chkmnt && (c->flag&CMSG))		goto bad;	if(mode<0 || c->mode==ORDWR)		return c;	if((mode&OTRUNC) && c->mode==OREAD)		goto bad;	if((mode&~OTRUNC) != c->mode)		goto bad;	return c;bad:	if(iref)		cclose(c);	error(Ebadusefd);	return nil; /* shut up compiler */} static voidfdclose(int fd, int flag){	int i;	Chan *c;	Fgrp *f; 	f = up->fgrp; 	lock(&f->ref.lk);	c = f->fd[fd];	if(c == 0) {		unlock(&f->ref.lk);		return;	}	if(flag) {		if(c==0 || !(c->flag&flag)) {			unlock(&f->ref.lk);			return;		}	}	f->fd[fd] = 0;	if(fd == f->maxfd)		for(i=fd; --i>=0 && f->fd[i]==0; )			f->maxfd = i; 	unlock(&f->ref.lk);	cclose(c);} static intnewfd(Chan *c){	int i;	Fgrp *f; 	f = up->fgrp;	lock(&f->ref.lk);	for(i=0; i<NFD; i++)		if(f->fd[i] == 0){			if(i > f->maxfd)				f->maxfd = i;			f->fd[i] = c;			unlock(&f->ref.lk);			return i;		}	unlock(&f->ref.lk);	error("no file descriptors");	return 0;} intsysclose(int fd){	if(waserror())		return -1; 	fdtochan(fd, -1, 0, 0);	fdclose(fd, 0);	poperror();	return 0;} intsyscreate(char *path, int mode, ulong perm){	int fd;	Chan *c = 0; 	if(waserror()) {		cclose(c);		return -1;	} 	openmode(mode);			/* error check only */	c = namec(path, Acreate, mode, perm);	fd = newfd((Chan*)c);	poperror();	return fd;} intsysdup(int old, int new){	Chan *oc;	Fgrp *f = up->fgrp;	Chan *c = 0; 	if(waserror())		return -1; 	c = fdtochan(old, -1, 0, 1);	if(new != -1) {		if(new < 0 || NFD <= new) {			cclose(c);			error(Ebadfd);		}		lock(&f->ref.lk);		if(new > f->maxfd)			f->maxfd = new;		oc = f->fd[new];		f->fd[new] = (Chan*)c;		unlock(&f->ref.lk);		if(oc != 0)			cclose(oc);	}	else {		if(waserror()) {			cclose(c);			nexterror();		}		new = newfd((Chan*)c);		poperror();	}	poperror();	return new;} intsysfstat(int fd, char *buf){	Chan *c = 0; 	if(waserror()) {		cclose(c);		return -1;	}	c = fdtochan(fd, -1, 0, 1);	devtab[c->type]->stat((Chan*)c, buf);	poperror();	cclose(c);	return 0;} intsysfwstat(int fd, char *buf){	Chan *c = 0; 	if(waserror()) {		cclose(c);		return -1;	}	nameok(buf);	c = fdtochan(fd, -1, 1, 1);	devtab[c->type]->wstat((Chan*)c, buf);	poperror();	cclose(c);	return 0;} intsyschdir(char *dir){	return 0;} longbindmount(Chan *c0, char *old, int flag, char *spec){	int ret;	Chan *c1 = 0; 	if(flag>MMASK || (flag&MORDER) == (MBEFORE|MAFTER))		error(Ebadarg); 	c1 = namec(old, Amount, 0, 0);	if(waserror()){		cclose(c1);		nexterror();	} 	ret = cmount(c0, c1, flag, spec); 	poperror();	cclose(c1);	return ret;} intsysbind(char *new, char *old, int flags){	long r;	Chan *c0 = 0; 	if(waserror()) {		cclose(c0);		return -1;	}	c0 = namec(new, Aaccess, 0, 0);	r = bindmount(c0, old, flags, "");	poperror();	cclose(c0);	return 0;} intsysmount(int fd, char *old, int flags, char *spec){	long r;	Chan *c0 = 0, *bc = 0;	struct {		Chan*	chan;		char*	spec;		int	flags;	} mntparam; 	if(waserror()) {		cclose(bc);		cclose(c0);		return -1;	}	bc = fdtochan(fd, ORDWR, 0, 1);	mntparam.chan = (Chan*)bc;	mntparam.spec = spec;	mntparam.flags = flags;	c0 = (*devtab[devno('M', 0)].attach)(&mntparam);	cclose(bc);	r = bindmount(c0, old, flags, spec);	poperror();	cclose(c0); 	return r;} intsysunmount(char *old, char *new){	Chan *cmount = 0, *cmounted = 0; 	if(waserror()) {		cclose(cmount);		cclose(cmounted);		return -1;	} 	cmount = namec(new, Amount, OREAD, 0);	if(old != 0)		cmounted = namec(old, Aopen, OREAD, 0); 	cunmount(cmount, cmounted);	poperror();		cclose(cmount);	cclose(cmounted);	return 0;} intsysopen(char *path, int mode){	int fd;	Chan *c = 0; 	if(waserror()){		cclose(c);		return -1;	}	openmode(mode);				/* error check only */	c = namec(path, Aopen, mode, 0);	fd = newfd((Chan*)c);	poperror();	return fd;} longunionread(Chan *c, void *va, long n){	long nr;	Chan *nc = 0;	Pgrp *pg = 0; 	pg = up->pgrp;	rlock(&pg->ns); 	for(;;) {		if(waserror()) {			runlock(&pg->ns);			nexterror();		}		nc = clone(c->mnt->to, 0);		poperror(); 		if(c->mountid != c->mnt->mountid) {			runlock(&pg->ns);			cclose(nc);			return 0;		} 		/* Error causes component of union to be skipped */		if(waserror()) {				cclose(nc);			goto next;		} 		nc = (*devtab[nc->type].open)((Chan*)nc, OREAD);		nc->offset = c->offset;		nr = (*devtab[nc->type].read)((Chan*)nc, va, n, nc->offset);		/* devdirread e.g. changes it */		c->offset = nc->offset;			poperror(); 		cclose(nc);		if(nr > 0) {			runlock(&pg->ns);			return nr;		}		/* Advance to next element */	next:		c->mnt = c->mnt->next;		if(c->mnt == 0)			break;		c->mountid = c->mnt->mountid;		c->offset = 0;	}	runlock(&pg->ns);	return 0;} longsysread(int fd, void *va, long n){	int dir;	Lock *cl;	Chan *c = 0; 	if(waserror()) {		cclose(c);		return -1;	}	c = fdtochan(fd, OREAD, 1, 1); 	dir = c->qid.path&CHDIR;	if(dir) {		n -= n%DIRLEN;		if(c->offset%DIRLEN || n==0)			error(Etoosmall);	} 	if(dir && c->mnt)		n = unionread((Chan*)c, va, n);	else		n = (*devtab[c->type].read)((Chan*)c, va, n, c->offset); 	cl = (Lock*)&c->r.l;	lock(cl);	c->offset += n;	unlock(cl); 	poperror();	cclose(c); 	return n;} intsysremove(char *path){	Chan *c = 0; 	if(waserror()) {		if(c != 0)			c->type = 0;	/* see below */		cclose(c);		return -1;	}	c = namec(path, Aaccess, 0, 0);	(*devtab[c->type].remove)((Chan*)c);	/*	 * Remove clunks the fid, but we need to recover the Chan	 * so fake it up.  rootclose() is known to be a nop.	 */	c->type = 0;	poperror();	cclose(c);	return 0;} longsysseek(int fd, long off, int whence){	Dir dir;	Chan *c;	char buf[DIRLEN]; 	if(waserror())		return -1; 	c = fdtochan(fd, -1, 1, 0);	if(c->qid.path & CHDIR)		error(Eisdir); 	switch(whence) {	case 0:		c->offset = off;		break; 	case 1:		lock(&c->r.l);	/* lock for read/write update */		c->offset += off;		off = c->offset;		unlock(&c->r.l);		break; 	case 2:		(*devtab[c->type].stat)(c, buf);		convM2D(buf, &dir);		c->offset = dir.length + off;		off = c->offset;		break;	}	poperror();	return off;} intsysstat(char *path, char *buf){	Chan *c = 0; 	if(waserror()){		cclose(c);		return -1;	}	c = namec(path, Aaccess, 0, 0);	(*devtab[c->type].stat)((Chan*)c, buf);	poperror();	cclose(c);	return 0;} longsyswrite(int fd, void *va, long n){	Lock *cl;	Chan *c = 0; 	if(waserror()) {		cclose(c);		return -1;	}	c = fdtochan(fd, OWRITE, 1, 1);	if(c->qid.path & CHDIR)		error(Eisdir); 	n = (*devtab[c->type].write)((Chan*)c, va, n, c->offset); 	cl = (Lock*)&c->r.l;	lock(cl);	c->offset += n;	unlock(cl); 	poperror();	cclose(c); 	return n;} intsyswstat(char *path, char *buf){

Lines 1–500 of 837.