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

1999/0709/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; 
1997/0603    
	Chan **newfd, **oldfd; 
1990/0227    
 
1991/0705    
	lock(f); 
1997/0603    
	for(i=0; i<f->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; 
		} 
1997/0603    
	/* 
	 * Unbounded allocation is unwise; besides, there are only 16 bits 
	 * of fid in 9P 
	 */ 
	if(f->nfd >= 5000){ 
1997/0606    
   Exhausted: 
1997/0603    
		unlock(f); 
		exhausted("file descriptors"); 
		return -1; 
	} 
1997/0606    
	newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*)); 
	if(newfd == 0) 
		goto Exhausted; 
1997/0603    
	oldfd = f->fd; 
	memmove(newfd, oldfd, f->nfd*sizeof(Chan*)); 
	f->fd = newfd; 
	f->nfd += DELTAFD; 
	f->maxfd = i; 
	f->fd[i] = c; 
1991/0705    
	unlock(f); 
1997/0603    
	free(oldfd); 
	if(i%100 == 0) 
		pprint("warning: process exceeds %d file descriptors\n", i); 
	return i; 
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); 
1997/0603    
	if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) { 
1992/0825    
		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    
	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    
{ 
1999/0629    
	Chan *c; 
1993/1004    
 
1999/0528    
	validaddr(arg[1], arg[2], 1); 
1993/1004    
 
1997/1205    
	c = fdtochan(arg[0], -1, 0, 1); 
 
1999/0629    
	if(c->name == nil) 
		snprint((char*)arg[1], arg[2], "<null>"); 
	else 
		snprint((char*)arg[1], arg[2], "%s", c->name->s); 
1999/0709    
	cclose(c); 
1993/1004    
	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); 
1999/0629    
	if(walkname(&c[0], "data", 1) < 0) 
1998/0224    
		error(Egreg); 
1999/0629    
	if(walkname(&c[1], "data1", 1) < 0) 
1998/0224    
		error(Egreg); 
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){ 
1997/1203    
		lock(f); 
1997/0603    
		if(fd<0 || f->nfd<=fd) { 
1997/1203    
			unlock(f); 
1997/0327    
			cclose(c); 
1991/0221    
			error(Ebadfd); 
1992/0825    
		} 
1991/0705    
		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) 
{ 
1998/0829    
	int i; 
1990/0227    
	long nr; 
1992/0720    
	Chan *nc; 
1998/0829    
	Mhead *m; 
	Mount *mount; 
1990/0227    
 
1998/0829    
	m = c->mh; 
	rlock(&m->lock); 
	mount = m->mount; 
	for(i = 0; mount != nil && i < c->uri; i++) 
		mount = mount->next; 
1991/1011    
 
1998/0901    
	while(mount != nil) { 
1991/1011    
		if(waserror()) { 
1998/0829    
			runlock(&m->lock); 
1991/1011    
			nexterror(); 
		} 
1998/0901    
		if(mount->to == nil) 
			goto next; 
1998/0829    
		nc = cclone(mount->to, 0); 
1991/1011    
		poperror(); 
 
1993/0318    
		/* Error causes component of union to be skipped */ 
1998/0512    
		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 */ 
1998/0512    
		c->offset = nc->offset; 
1991/1011    
		poperror(); 
 
1997/0327    
		cclose(nc); 
1991/1011    
		if(nr > 0) { 
1998/0829    
			runlock(&m->lock); 
1991/1011    
			return nr; 
		} 
1992/0720    
		/* Advance to next element */ 
	next: 
1998/0829    
		c->uri++; 
		mount = mount->next; 
		if(mount == nil) 
1991/1011    
			break; 
		c->offset = 0; 
1990/0227    
	} 
1998/0829    
	runlock(&m->lock); 
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); 
	} 
 
1998/0829    
	if(dir && c->mh) 
1994/0405    
		n = unionread(c, (void*)arg[1], n); 
1997/0408    
	else if(devtab[c->type]->dc != 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    
 
1998/0922    
	n = arg[2]; 
	validaddr(arg[1], n, 1); 
1992/0825    
	c = fdtochan(arg[0], OREAD, 1, 1); 
1998/0922    
 
1992/0825    
	if(waserror()) { 
1997/0327    
		cclose(c); 
1990/0227    
		nexterror(); 
	} 
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    
 
1998/0829    
	if(dir && c->mh) 
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); 
 
1997/0408    
	if(devtab[c->type]->dc != 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; 
1998/0922    
	long m, n; 
	uvlong oo; 
1990/0227    
 
	validaddr(arg[1], arg[2], 0); 
1998/0922    
	n = arg[2]; 
1992/0825    
	c = fdtochan(arg[0], OWRITE, 1, 1); 
	if(waserror()) { 
1997/0327    
		cclose(c); 
1998/0922    
		lock(c); 
		c->offset -= n; 
		unlock(c); 
1990/0227    
		nexterror(); 
	} 
1992/0825    
 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eisdir); 
1992/0825    
 
	lock(c); 
1998/0922    
	oo = c->offset; 
1991/1101    
	c->offset += n; 
1992/0825    
	unlock(c); 
1998/0922    
 
	m = devtab[c->type]->write(c, (void*)arg[1], n, oo); 
 
	if(m < n){ 
		lock(c); 
1998/0923    
		c->offset -= n - m; 
1998/0922    
		unlock(c); 
	} 
1992/0825    
 
	poperror(); 
1997/0327    
	cclose(c); 
1992/0825    
 
1990/0227    
	return n; 
} 
 
1998/0326    
static void 
sseek(ulong *arg) 
1990/0227    
{ 
	Chan *c; 
	char buf[DIRLEN]; 
	Dir dir; 
1998/0319    
	vlong off; 
	union { 
		vlong v; 
		ulong u[2]; 
	} o; 
1990/0227    
 
1998/0403    
	c = fdtochan(arg[1], -1, 1, 1); 
	if(waserror()){ 
		cclose(c); 
		nexterror(); 
	} 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eisdir); 
1992/0825    
 
1997/0408    
	if(devtab[c->type]->dc == '|') 
1991/0319    
		error(Eisstream); 
1992/0825    
 
1991/1101    
	off = 0; 
1998/0326    
	o.u[0] = arg[2]; 
	o.u[1] = arg[3]; 
	switch(arg[4]){ 
1990/0227    
	case 0: 
1998/0319    
		off = o.v; 
		c->offset = off; 
1990/0227    
		break; 
 
	case 1: 
1992/0825    
		lock(c);	/* lock for read/write update */ 
1998/0319    
		off = o.v + c->offset; 
		c->offset = off; 
1992/0825    
		unlock(c); 
1990/0227    
		break; 
 
	case 2: 
1997/0327    
		devtab[c->type]->stat(c, buf); 
1990/0227    
		convM2D(buf, &dir); 
1998/0326    
		off = dir.length + o.v; 
1998/0319    
		c->offset = off; 
1990/0227    
		break; 
	} 
1998/0326    
	*(vlong*)arg[0] = off; 
1998/0829    
	c->uri = 0; 
1998/0403    
	cclose(c); 
	poperror(); 
1998/0319    
} 
 
long 
1998/0915    
sysseek(ulong *arg) 
1998/0326    
{ 
	validaddr(arg[0], BY2V, 1); 
	sseek(arg); 
	return 0; 
} 
 
long 
1998/0915    
sysoseek(ulong *arg) 
1998/0319    
{ 
	union { 
		vlong v; 
		ulong u[2]; 
	} o; 
1998/0326    
	ulong a[5]; 
1998/0319    
 
	o.v = arg[1]; 
1998/0326    
	a[0] = (ulong)&o.v; 
	a[1] = arg[0]; 
	a[2] = o.u[0]; 
	a[3] = o.u[1]; 
	a[4] = arg[2]; 
	sseek(a); 
	return o.v; 
1990/0227    
} 
 
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); 
1998/0512    
	poperror(); 
1991/1011    
	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)