Charles.Forsyth2008010978a844018 years agoHistory
1125 lines · 16.2 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h" static intgrowfd(Fgrp *f, int fd){	int n;	Chan **nfd, **ofd; 	if(fd < f->nfd)		return 0;	n = f->nfd+DELTAFD;	if(n > MAXNFD)		n = MAXNFD;	if(fd >= n)		return -1;	nfd = malloc(n*sizeof(Chan*));	if(nfd == nil)		return -1;	ofd = f->fd;	memmove(nfd, ofd, f->nfd*sizeof(Chan *));	f->fd = nfd;	f->nfd = n;	free(ofd);	return 0;} intnewfd(Chan *c){	int i;	Fgrp *f = up->env->fgrp; 	lock(f);	for(i=f->minfd; i<f->nfd; i++)		if(f->fd[i] == 0)			break;	if(i >= f->nfd && growfd(f, i) < 0){		unlock(f);		exhausted("file descriptors");		return -1;	}	f->minfd = i + 1;	if(i > f->maxfd)		f->maxfd = i;	f->fd[i] = c;	unlock(f);	return i;} Chan*fdtochan(Fgrp *f, int fd, int mode, int chkmnt, int iref){	Chan *c; 	c = 0; 	lock(f);	if(fd<0 || f->maxfd<fd || (c = f->fd[fd])==0) {		unlock(f);		error(Ebadfd);	}	if(iref)		incref(c);	unlock(f); 	if(chkmnt && (c->flag&CMSG)) {		if(iref)			cclose(c);		error(Ebadusefd);	} 	if(mode<0 || c->mode==ORDWR)		return c; 	if((mode&OTRUNC) && c->mode==OREAD) {		if(iref)			cclose(c);		error(Ebadusefd);	} 	if((mode&~OTRUNC) != c->mode) {		if(iref)			cclose(c);		error(Ebadusefd);	} 	return c;} longkchanio(void *vc, void *buf, int n, int mode){	int r;	Chan *c; 	c = vc;	if(waserror())		return -1; 	if(mode == OREAD)		r = devtab[c->type]->read(c, buf, n, c->offset);	else		r = devtab[c->type]->write(c, buf, n, c->offset); 	lock(c);	c->offset += r;	unlock(c);	poperror();	return r;} intopenmode(ulong o){	if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC))		error(Ebadarg);	o &= ~(OTRUNC|OCEXEC|ORCLOSE);	if(o > OEXEC)		error(Ebadarg);	if(o == OEXEC)		return OREAD;	return o;} voidfdclose(Fgrp *f, int fd){	int i;	Chan *c; 	lock(f);	c = f->fd[fd];	if(c == 0){		/* can happen for users with shared fd tables */		unlock(f);		return;	}	f->fd[fd] = 0;	if(fd == f->maxfd)		for(i=fd; --i>=0 && f->fd[i]==0; )			f->maxfd = i;	if(fd < f->minfd)		f->minfd = fd;	unlock(f);	cclose(c);} intkchdir(char *path){	Chan *c;	Pgrp *pg; 	if(waserror())		return -1; 	c = namec(path, Atodir, 0, 0);	pg = up->env->pgrp;	cclose(pg->dot);	pg->dot = c;	poperror();	return 0;} intkfgrpclose(Fgrp *f, int fd){	if(waserror())		return -1; 	/*	 * Take no reference on the chan because we don't really need the	 * data structure, and are calling fdtochan only for error checks.	 * fdclose takes care of processes racing through here.	 */	fdtochan(f, fd, -1, 0, 0);	fdclose(f, fd);	poperror();	return 0;} intkclose(int fd){	return kfgrpclose(up->env->fgrp, fd);} intkcreate(char *path, int mode, ulong perm){	int fd;	Chan *c; 	if(waserror())		return -1; 	openmode(mode&~OEXCL);	/* error check only; OEXCL okay here */	c = namec(path, Acreate, mode, perm);	if(waserror()) {		cclose(c);		nexterror();	}	fd = newfd(c);	if(fd < 0)		error(Enofd);	poperror(); 	poperror();	return fd;} intkdup(int old, int new){	int fd;	Chan *c, *oc;	Fgrp *f = up->env->fgrp; 	if(waserror())		return -1; 	c = fdtochan(up->env->fgrp, old, -1, 0, 1);	if(c->qid.type & QTAUTH)		error(Eperm);	fd = new;	if(fd != -1){		lock(f);		if(fd<0 || growfd(f, fd) < 0) {			unlock(f);			cclose(c);			error(Ebadfd);		}		if(fd > f->maxfd)			f->maxfd = fd;		oc = f->fd[fd];		f->fd[fd] = c;		unlock(f);		if(oc)			cclose(oc);	}else{		if(waserror()) {			cclose(c);			nexterror();		}		fd = newfd(c);		if(fd < 0)			error(Enofd);		poperror();	}	poperror();	return fd;} intkfstat(int fd, uchar *buf, int n){	Chan *c; 	if(waserror())		return -1; 	c = fdtochan(up->env->fgrp, fd, -1, 0, 1);	if(waserror()) {		cclose(c);		nexterror();	}	devtab[c->type]->stat(c, buf, n); 	poperror();	cclose(c); 	poperror();	return n;} char*kfd2path(int fd){	Chan *c;	char *s; 	if(waserror())		return nil;	c = fdtochan(up->env->fgrp, fd, -1, 0, 1);	s = nil;	if(c->name != nil){		s = malloc(c->name->len+1);		if(s == nil){			cclose(c);			error(Enomem);		}		memmove(s, c->name->s, c->name->len+1);		cclose(c);	}	poperror();	return s;} intkfauth(int fd, char *aname){	Chan *c, *ac; 	if(waserror())		return -1; 	validname(aname, 0);	c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);	if(waserror()){		cclose(c);		nexterror();	} 	ac = mntauth(c, aname); 	/* at this point ac is responsible for keeping c alive */	poperror();	/* c */	cclose(c); 	if(waserror()){		cclose(ac);		nexterror();	} 	fd = newfd(ac);	if(fd < 0)		error(Enofd);	poperror();	/* ac */ 	poperror(); 	return fd;} intkfversion(int fd, uint msize, char *vers, uint arglen){	int m;	Chan *c; 	if(waserror())		return -1; 	/* check there's a NUL in the version string */	if(arglen==0 || memchr(vers, 0, arglen)==0)		error(Ebadarg); 	c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);	if(waserror()){		cclose(c);		nexterror();	} 	m = mntversion(c, vers, msize, arglen); 	poperror();	cclose(c); 	poperror();	return m;} intkpipe(int fd[2]){	Dev *d;	Fgrp *f;	Chan *c[2];	static char *names[] = {"data", "data1"}; 	f = up->env->fgrp; 	d = devtab[devno('|', 0)];	c[0] = namec("#|", Atodir, 0, 0);	c[1] = 0;	fd[0] = -1;	fd[1] = -1;	if(waserror()) {		if(c[0] != 0)			cclose(c[0]);		if(c[1] != 0)			cclose(c[1]);		if(fd[0] >= 0)			f->fd[fd[0]]=0;		if(fd[1] >= 0)			f->fd[fd[1]]=0;		return -1;	}	c[1] = cclone(c[0]);	if(walk(&c[0], &names[0], 1, 1, nil) < 0)		error(Egreg);	if(walk(&c[1], &names[1], 1, 1, nil) < 0)		error(Egreg);	c[0] = d->open(c[0], ORDWR);	c[1] = d->open(c[1], ORDWR);	fd[0] = newfd(c[0]);	if(fd[0] < 0)		error(Enofd);	fd[1] = newfd(c[1]);	if(fd[1] < 0)		error(Enofd);	poperror();	return 0;} intkfwstat(int fd, uchar *buf, int n){	Chan *c; 	if(waserror())		return -1; 	validstat(buf, n);	c = fdtochan(up->env->fgrp, fd, -1, 1, 1);	if(waserror()) {		cclose(c);		nexterror();	}	n = devtab[c->type]->wstat(c, buf, n);	poperror();	cclose(c); 	poperror();	return n;} longbindmount(Chan *c, char *old, int flag, char *spec){	int ret;	Chan *c1; 	if(flag>MMASK || (flag&MORDER) == (MBEFORE|MAFTER))		error(Ebadarg); 	c1 = namec(old, Amount, 0, 0);	if(waserror()){		cclose(c1);		nexterror();	}	ret = cmount(c, c1, flag, spec); 	poperror();	cclose(c1);	return ret;} intkbind(char *new, char *old, int flags){	long r;	Chan *c0; 	if(waserror())		return -1; 	c0 = namec(new, Abind, 0, 0);	if(waserror()) {		cclose(c0);		nexterror();	}	r = bindmount(c0, old, flags, "");	poperror();	cclose(c0); 	poperror();	return r;} intkmount(int fd, int afd, char *old, int flags, char *spec){	long r;	volatile struct { Chan *c; } c0;	volatile struct { Chan *c; } bc;	volatile struct { Chan *c; } ac;	Mntparam mntparam; 	ac.c = nil;	bc.c = nil;	c0.c = nil;	if(waserror()) {		cclose(ac.c);		cclose(bc.c);		cclose(c0.c);		return -1;	}	bc.c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);	if(afd >= 0)		ac.c = fdtochan(up->env->fgrp, afd, ORDWR, 0, 1);	mntparam.chan = bc.c;	mntparam.authchan = ac.c;	mntparam.spec = spec;	mntparam.flags = flags;

Lines 1–500 of 1125.