plan 9 kernel history: overview | file list | diff list

1997/0327/port/sysfile.c (diff list | history)

port/sysfile.c on 1990/0227
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
 
/* 
 * The sys*() routines needn't poperror() as they return directly to syscall(). 
 */ 
 
int 
1991/0705    
newfd(Chan *c) 
1990/0227    
{ 
	int i; 
1997/0327    
	Fgrp *f = up->fgrp; 
1990/0227    
 
1991/0705    
	lock(f); 
1990/0227    
	for(i=0; i<NFD; i++) 
1991/0705    
		if(f->fd[i] == 0){ 
			if(i > f->maxfd) 
				f->maxfd = i; 
			f->fd[i] = c; 
			unlock(f); 
1990/0227    
			return i; 
		} 
1991/0705    
	unlock(f); 
1992/0114    
	exhausted("file descriptors"); 
1992/0720    
	return 0; 
1990/0227    
} 
 
Chan* 
1992/0825    
fdtochan(int fd, int mode, int chkmnt, int iref) 
1990/0227    
{ 
	Chan *c; 
1992/0825    
	Fgrp *f; 
1990/0227    
 
1991/0904    
	c = 0; 
1993/0501    
	f = up->fgrp; 
1992/0825    
 
	lock(f); 
	if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) { 
		unlock(f); 
1990/11211    
		error(Ebadfd); 
1992/0825    
	} 
	if(iref) 
		incref(c); 
	unlock(f); 
 
	if(chkmnt && (c->flag&CMSG)) { 
		if(iref) 
1997/0327    
			cclose(c); 
1992/0114    
		error(Ebadusefd); 
1992/0825    
	} 
 
1990/1009    
	if(mode<0 || c->mode==ORDWR) 
1990/0227    
		return c; 
1992/0825    
 
	if((mode&OTRUNC) && c->mode==OREAD) { 
		if(iref) 
1997/0327    
			cclose(c); 
1990/11211    
		error(Ebadusefd); 
1992/0825    
	} 
 
	if((mode&~OTRUNC) != c->mode) { 
		if(iref) 
1997/0327    
			cclose(c); 
1991/1011    
		error(Ebadusefd); 
1992/0825    
	} 
 
1990/0227    
	return c; 
} 
 
int 
openmode(ulong o) 
{ 
1990/08141    
	if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC)) 
1990/11211    
		error(Ebadarg); 
1990/08141    
	o &= ~(OTRUNC|OCEXEC|ORCLOSE); 
1990/0227    
	if(o > OEXEC) 
1991/1018    
		error(Ebadarg); 
1990/0227    
	if(o == OEXEC) 
		return OREAD; 
	return o; 
} 
 
long 
1994/0321    
sysfd2path(ulong *arg) 
1993/1004    
{ 
	Chan *c; 
 
	validaddr(arg[1], 1, 0); 
	if(vmemchr((char*)arg[1], '\0', arg[2]) == 0) 
		error(Ebadarg); 
 
	c = fdtochan(arg[0], -1, 0, 0); 
1994/0611    
	/* If we used open the chan will be at the first element 
	 * of a union rather than the mhead of the union. undomount 
	 * will make it look like we used Atodir rather than Aopen. 
	 */ 
	if(c->qid.path & CHDIR) 
		c = undomount(c); 
1993/1004    
	ptpath(c->path, (char*)arg[1], arg[2]); 
	return 0; 
} 
 
long 
1990/1009    
syspipe(ulong *arg) 
{ 
	int fd[2]; 
	Chan *c[2]; 
	Dev *d; 
1993/0501    
	Fgrp *f = up->fgrp; 
1990/1009    
 
	validaddr(arg[0], 2*BY2WD, 1); 
	evenaddr(arg[0]); 
1997/0327    
	d = devtab[devno('|', 0)]; 
1993/0501    
	c[0] = namec("#|", Atodir, 0, 0); 
1990/1009    
	c[1] = 0; 
	fd[0] = -1; 
	fd[1] = -1; 
	if(waserror()){ 
1997/0327    
		cclose(c[0]); 
1990/1009    
		if(c[1]) 
1997/0327    
			cclose(c[1]); 
1990/1009    
		if(fd[0] >= 0) 
1991/0705    
			f->fd[fd[0]]=0; 
1990/1009    
		if(fd[1] >= 0) 
1991/0705    
			f->fd[fd[1]]=0; 
1990/1009    
		nexterror(); 
	} 
1997/0327    
	c[1] = cclone(c[0], 0); 
1993/0501    
	walk(c[0], "data", 1); 
	walk(c[1], "data1", 1); 
1997/0327    
	c[0] = d->open(c[0], ORDWR); 
	c[1] = d->open(c[1], ORDWR); 
1991/0705    
	fd[0] = newfd(c[0]); 
	fd[1] = newfd(c[1]); 
1990/1009    
	((long*)arg[0])[0] = fd[0]; 
	((long*)arg[0])[1] = fd[1]; 
	poperror(); 
	return 0; 
} 
 
long 
1990/0227    
sysdup(ulong *arg) 
{ 
	int fd; 
	Chan *c, *oc; 
1993/0501    
	Fgrp *f = up->fgrp; 
1990/0227    
 
	/* 
	 * Close after dup'ing, so date > #d/1 works 
	 */ 
1992/0825    
	c = fdtochan(arg[0], -1, 0, 1); 
1990/0227    
	fd = arg[1]; 
1991/0221    
	if(fd != -1){ 
1992/0825    
		if(fd<0 || NFD<=fd) { 
1997/0327    
			cclose(c); 
1991/0221    
			error(Ebadfd); 
1992/0825    
		} 
1991/0705    
		lock(f); 
		if(fd > f->maxfd) 
			f->maxfd = fd; 
1992/0825    
 
1991/0705    
		oc = f->fd[fd]; 
		f->fd[fd] = c; 
		unlock(f); 
		if(oc) 
1997/0327    
			cclose(oc); 
1991/0706    
	}else{ 
1991/0705    
		if(waserror()) { 
1997/0327    
			cclose(c); 
1991/0705    
			nexterror(); 
		} 
		fd = newfd(c); 
		poperror(); 
1990/0227    
	} 
1991/0705    
 
1990/0227    
	return fd; 
} 
 
long 
sysopen(ulong *arg) 
{ 
	int fd; 
1991/0705    
	Chan *c = 0; 
1990/0227    
 
	openmode(arg[1]);	/* error check only */ 
1991/0706    
	if(waserror()){ 
1991/0705    
		if(c) 
1997/0327    
			cclose(c); 
1991/0705    
		nexterror(); 
	} 
1990/0227    
	validaddr(arg[0], 1, 0); 
	c = namec((char*)arg[0], Aopen, arg[1], 0); 
1991/0705    
	fd = newfd(c); 
	poperror(); 
1990/0227    
	return fd; 
} 
 
void 
1991/0705    
fdclose(int fd, int flag) 
1990/0227    
{ 
	int i; 
1991/0705    
	Chan *c; 
1993/0501    
	Fgrp *f = up->fgrp; 
1990/0227    
 
1991/0705    
	lock(f); 
	c = f->fd[fd]; 
1992/0817    
	if(c == 0){ 
		/* can happen for users with shared fd tables */ 
		unlock(f); 
		return; 
	} 
1991/0705    
	if(flag){ 
		if(c==0 || !(c->flag&flag)){ 
			unlock(f); 
			return; 
		} 
	} 
	f->fd[fd] = 0; 
	if(fd == f->maxfd) 
		for(i=fd; --i>=0 && f->fd[i]==0; ) 
			f->maxfd = i; 
 
	unlock(f); 
1997/0327    
	cclose(c); 
1990/0227    
} 
 
long 
sysclose(ulong *arg) 
{ 
1992/0825    
	fdtochan(arg[0], -1, 0, 0); 
1991/0705    
	fdclose(arg[0], 0); 
 
1990/0227    
	return 0; 
} 
 
long 
unionread(Chan *c, void *va, long n) 
{ 
	long nr; 
1992/0720    
	Chan *nc; 
	Pgrp *pg; 
1990/0227    
 
1993/0501    
	pg = up->pgrp; 
1993/0318    
	rlock(&pg->ns); 
1991/1011    
 
	for(;;) { 
		if(waserror()) { 
1993/0318    
			runlock(&pg->ns); 
1991/1011    
			nexterror(); 
		} 
1997/0327    
		nc = cclone(c->mnt->to, 0); 
1991/1011    
		poperror(); 
 
1992/0720    
		if(c->mountid != c->mnt->mountid) { 
1993/0318    
			pprint("unionread: changed underfoot?\n"); 
			runlock(&pg->ns); 
1997/0327    
			cclose(nc); 
1991/1011    
			return 0; 
		} 
 
1993/0318    
		/* Error causes component of union to be skipped */ 
1992/0720    
		if(waserror()) {	 
1997/0327    
			cclose(nc); 
1992/0720    
			goto next; 
1991/1011    
		} 
 
1997/0327    
		nc = devtab[nc->type]->open(nc, OREAD); 
1991/1011    
		nc->offset = c->offset; 
1997/0327    
		nr = devtab[nc->type]->read(nc, va, n, nc->offset); 
1993/0318    
		/* devdirread e.g. changes it */ 
1991/1011    
		c->offset = nc->offset;	 
		poperror(); 
 
1997/0327    
		cclose(nc); 
1991/1011    
		if(nr > 0) { 
1993/0318    
			runlock(&pg->ns); 
1991/1011    
			return nr; 
		} 
1992/0720    
		/* Advance to next element */ 
	next: 
1993/0318    
		c->mnt = c->mnt->next; 
1991/1011    
		if(c->mnt == 0) 
			break; 
		c->mountid = c->mnt->mountid; 
		c->offset = 0; 
1990/0227    
	} 
1993/0318    
	runlock(&pg->ns); 
1991/1011    
	return 0; 
1990/0227    
} 
 
long 
1994/0405    
sysread9p(ulong *arg) 
{ 
	int dir; 
	long n; 
	Chan *c; 
 
	validaddr(arg[1], arg[2], 1); 
	c = fdtochan(arg[0], OREAD, 1, 1); 
	if(waserror()) { 
1997/0327    
		cclose(c); 
1994/0405    
		nexterror(); 
	} 
 
	n = arg[2]; 
	dir = c->qid.path&CHDIR; 
 
	if(dir) { 
		n -= n%DIRLEN; 
		if(c->offset%DIRLEN || n==0) 
			error(Etoosmall); 
	} 
 
	if(dir && c->mnt) 
		n = unionread(c, (void*)arg[1], n); 
	else if(devchar[c->type] != L'M') 
1997/0327    
		n = devtab[c->type]->read(c, (void*)arg[1], n, c->offset); 
1994/0405    
	else 
		n = mntread9p(c, (void*)arg[1], n, c->offset); 
 
	lock(c); 
	c->offset += n; 
	unlock(c); 
 
	poperror(); 
1997/0327    
	cclose(c); 
1994/0405    
 
	return n; 
} 
 
long 
1990/0227    
sysread(ulong *arg) 
{ 
1992/0825    
	int dir; 
1990/0227    
	long n; 
1992/0825    
	Chan *c; 
1990/0227    
 
1990/1004    
	validaddr(arg[1], arg[2], 1); 
1992/0825    
	c = fdtochan(arg[0], OREAD, 1, 1); 
	if(waserror()) { 
1997/0327    
		cclose(c); 
1990/0227    
		nexterror(); 
	} 
1992/0825    
 
1990/0227    
	n = arg[2]; 
1992/0825    
	dir = c->qid.path&CHDIR; 
 
	if(dir) { 
1990/0227    
		n -= n%DIRLEN; 
		if(c->offset%DIRLEN || n==0) 
1992/0114    
			error(Etoosmall); 
1990/0227    
	} 
1992/0825    
 
	if(dir && c->mnt) 
1990/0227    
		n = unionread(c, (void*)arg[1], n); 
	else 
1997/0327    
		n = devtab[c->type]->read(c, (void*)arg[1], n, c->offset); 
1992/0825    
 
	lock(c); 
1991/1101    
	c->offset += n; 
1992/0825    
	unlock(c); 
 
	poperror(); 
1997/0327    
	cclose(c); 
1992/0825    
 
1990/0227    
	return n; 
} 
 
long 
1994/0402    
syswrite9p(ulong *arg) 
{ 
	Chan *c; 
	long n; 
 
	validaddr(arg[1], arg[2], 0); 
	c = fdtochan(arg[0], OWRITE, 1, 1); 
	if(waserror()) { 
1997/0327    
		cclose(c); 
1994/0402    
		nexterror(); 
	} 
 
	if(c->qid.path & CHDIR) 
		error(Eisdir); 
 
	if(devchar[c->type] != L'M') 
1997/0327    
		n = devtab[c->type]->write(c, (void*)arg[1], arg[2], c->offset); 
1994/0402    
	else 
		n = mntwrite9p(c, (void*)arg[1], arg[2], c->offset); 
	lock(c); 
	c->offset += n; 
	unlock(c); 
 
	poperror(); 
1997/0327    
	cclose(c); 
1994/0402    
 
	return n; 
} 
 
long 
1990/0227    
syswrite(ulong *arg) 
{ 
	Chan *c; 
	long n; 
 
	validaddr(arg[1], arg[2], 0); 
1992/0825    
	c = fdtochan(arg[0], OWRITE, 1, 1); 
	if(waserror()) { 
1997/0327    
		cclose(c); 
1990/0227    
		nexterror(); 
	} 
1992/0825    
 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eisdir); 
1992/0825    
 
1997/0327    
	n = devtab[c->type]->write(c, (void*)arg[1], arg[2], c->offset); 
1992/0825    
 
	lock(c); 
1991/1101    
	c->offset += n; 
1992/0825    
	unlock(c); 
 
	poperror(); 
1997/0327    
	cclose(c); 
1992/0825    
 
1990/0227    
	return n; 
} 
 
long 
sysseek(ulong *arg) 
{ 
	Chan *c; 
	char buf[DIRLEN]; 
	Dir dir; 
	long off; 
 
1992/0825    
	c = fdtochan(arg[0], -1, 1, 0); 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eisdir); 
1992/0825    
 
1991/0319    
	if(devchar[c->type] == '|') 
		error(Eisstream); 
1992/0825    
 
1991/1101    
	off = 0; 
1990/0227    
	switch(arg[2]){ 
	case 0: 
1991/1101    
		off = c->offset = arg[1]; 
1990/0227    
		break; 
 
	case 1: 
1992/0825    
		lock(c);	/* lock for read/write update */ 
1990/0227    
		c->offset += (long)arg[1]; 
1991/1101    
		off = c->offset; 
1992/0825    
		unlock(c); 
1990/0227    
		break; 
 
	case 2: 
1997/0327    
		devtab[c->type]->stat(c, buf); 
1990/0227    
		convM2D(buf, &dir); 
		c->offset = dir.length + (long)arg[1]; 
1991/1101    
		off = c->offset; 
1990/0227    
		break; 
	} 
	return off; 
} 
 
long 
sysfstat(ulong *arg) 
{ 
	Chan *c; 
 
	validaddr(arg[1], DIRLEN, 1); 
	evenaddr(arg[1]); 
1992/0825    
	c = fdtochan(arg[0], -1, 0, 1); 
	if(waserror()) { 
1997/0327    
		cclose(c); 
1992/0825    
		nexterror(); 
	} 
1997/0327    
	devtab[c->type]->stat(c, (char*)arg[1]); 
1992/0825    
	poperror(); 
1997/0327    
	cclose(c); 
1990/0227    
	return 0; 
} 
 
long 
sysstat(ulong *arg) 
{ 
	Chan *c; 
 
	validaddr(arg[1], DIRLEN, 1); 
	evenaddr(arg[1]); 
	validaddr(arg[0], 1, 0); 
	c = namec((char*)arg[0], Aaccess, 0, 0); 
	if(waserror()){ 
1997/0327    
		cclose(c); 
1990/0227    
		nexterror(); 
	} 
1997/0327    
	devtab[c->type]->stat(c, (char*)arg[1]); 
1990/0227    
	poperror(); 
1997/0327    
	cclose(c); 
1990/0227    
	return 0; 
} 
 
long 
syschdir(ulong *arg) 
{ 
	Chan *c; 
 
	validaddr(arg[0], 1, 0); 
1993/0501    
 
1990/0227    
	c = namec((char*)arg[0], Atodir, 0, 0); 
1997/0327    
	cclose(up->dot); 
1993/0501    
	up->dot = c; 
1990/0227    
	return 0; 
} 
 
long 
bindmount(ulong *arg, int ismount) 
{ 
	ulong flag; 
1993/0501    
	int fd, ret; 
	Chan *c0, *c1, *bc; 
1990/0227    
	struct{ 
		Chan	*chan; 
		char	*spec; 
1993/1014    
		int	flags; 
1990/0227    
	}bogus; 
 
	flag = arg[2]; 
1992/0607    
	fd = arg[0]; 
1990/0227    
	if(flag>MMASK || (flag&MORDER)==(MBEFORE|MAFTER)) 
1990/11211    
		error(Ebadarg); 
1993/0501    
 
1993/1014    
	bogus.flags = flag & (MRECOV|MCACHE); 
1993/0501    
 
1990/0227    
	if(ismount){ 
1993/0501    
		bc = fdtochan(fd, ORDWR, 0, 1); 
1992/0825    
		if(waserror()) { 
1997/0327    
			cclose(bc); 
1992/0825    
			nexterror(); 
		} 
		bogus.chan = bc; 
 
1990/11211    
		validaddr(arg[3], 1, 0); 
1991/0615    
		if(vmemchr((char*)arg[3], '\0', NAMELEN) == 0) 
			error(Ebadarg); 
1992/0825    
 
1990/0227    
		bogus.spec = (char*)arg[3]; 
1994/0622    
		if(strchr(bogus.spec, ' ')) 
			error(Ebadspec); 
1992/0825    
 
1990/0227    
		ret = devno('M', 0); 
1997/0327    
		c0 = devtab[ret]->attach((char*)&bogus); 
1992/0825    
 
		poperror(); 
1997/0327    
		cclose(bc); 
1992/0825    
	} 
	else { 
1993/0501    
		bogus.spec = 0; 
1990/0227    
		validaddr(arg[0], 1, 0); 
		c0 = namec((char*)arg[0], Aaccess, 0, 0); 
	} 
1993/0501    
 
1990/0227    
	if(waserror()){ 
1997/0327    
		cclose(c0); 
1990/0227    
		nexterror(); 
	} 
1993/0501    
 
1990/0227    
	validaddr(arg[1], 1, 0); 
	c1 = namec((char*)arg[1], Amount, 0, 0); 
	if(waserror()){ 
1997/0327    
		cclose(c1); 
1990/0227    
		nexterror(); 
	} 
1993/0501    
 
1997/0327    
	ret = cmount(c0, c1, flag, bogus.spec); 
1993/0501    
 
1991/0614    
	poperror(); 
1997/0327    
	cclose(c1); 
1991/0614    
	poperror(); 
1997/0327    
	cclose(c0); 
1991/0705    
	if(ismount) 
1992/0607    
		fdclose(fd, 0); 
1990/0227    
	return ret; 
} 
 
long 
sysbind(ulong *arg) 
{ 
	return bindmount(arg, 0); 
} 
 
long 
sysmount(ulong *arg) 
{ 
	return bindmount(arg, 1); 
} 
 
long 
1991/1011    
sysunmount(ulong *arg) 
{ 
	Chan *cmount, *cmounted; 
 
	cmounted = 0; 
 
	validaddr(arg[1], 1, 0); 
	cmount = namec((char *)arg[1], Amount, 0, 0); 
 
	if(arg[0]) { 
		if(waserror()) { 
1997/0327    
			cclose(cmount); 
1991/1011    
			nexterror(); 
		} 
		validaddr(arg[0], 1, 0); 
1993/1111    
		cmounted = namec((char*)arg[0], Aopen, OREAD, 0); 
1991/1011    
		poperror(); 
	} 
 
	if(waserror()) { 
1997/0327    
		cclose(cmount); 
1991/1011    
		if(cmounted) 
1997/0327    
			cclose(cmounted); 
1991/1011    
		nexterror(); 
	} 
1997/0327    
 
	cunmount(cmount, cmounted); 
	cclose(cmount); 
1991/1011    
	if(cmounted) 
1997/0327    
		cclose(cmounted); 
1991/1011    
	poperror();	 
	return 0; 
} 
 
long 
1990/0227    
syscreate(ulong *arg) 
{ 
	int fd; 
1991/0705    
	Chan *c = 0; 
1990/0227    
 
	openmode(arg[1]);	/* error check only */ 
1991/0705    
	if(waserror()) { 
		if(c) 
1997/0327    
			cclose(c); 
1991/0705    
		nexterror(); 
	} 
1990/0227    
	validaddr(arg[0], 1, 0); 
	c = namec((char*)arg[0], Acreate, arg[1], arg[2]); 
1991/0705    
	fd = newfd(c); 
	poperror(); 
1990/0227    
	return fd; 
} 
 
long 
sysremove(ulong *arg) 
{ 
	Chan *c; 
 
	validaddr(arg[0], 1, 0); 
	c = namec((char*)arg[0], Aaccess, 0, 0); 
	if(waserror()){ 
1990/0703    
		c->type = 0;	/* see below */ 
1997/0327    
		cclose(c); 
1990/0227    
		nexterror(); 
	} 
1997/0327    
	devtab[c->type]->remove(c); 
1990/0227    
	/* 
	 * 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; 
1991/0614    
	poperror(); 
1997/0327    
	cclose(c); 
1990/0227    
	return 0; 
} 
 
long 
syswstat(ulong *arg) 
{ 
	Chan *c; 
 
	validaddr(arg[1], DIRLEN, 0); 
1991/1107    
	nameok((char*)arg[1]); 
1990/0227    
	validaddr(arg[0], 1, 0); 
	c = namec((char*)arg[0], Aaccess, 0, 0); 
	if(waserror()){ 
1997/0327    
		cclose(c); 
1990/0227    
		nexterror(); 
	} 
1997/0327    
	devtab[c->type]->wstat(c, (char*)arg[1]); 
1990/0227    
	poperror(); 
1997/0327    
	cclose(c); 
1990/0227    
	return 0; 
} 
 
long 
sysfwstat(ulong *arg) 
{ 
	Chan *c; 
 
	validaddr(arg[1], DIRLEN, 0); 
1991/1107    
	nameok((char*)arg[1]); 
1992/0825    
	c = fdtochan(arg[0], -1, 1, 1); 
	if(waserror()) { 
1997/0327    
		cclose(c); 
1992/0825    
		nexterror(); 
	} 
1997/0327    
	devtab[c->type]->wstat(c, (char*)arg[1]); 
1992/0825    
	poperror(); 
1997/0327    
	cclose(c); 
1990/0227    
	return 0; 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)