Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/sysfile.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/sysfile.c 1990/0227
## diff -e /dev/null /n/bootesdump/1990/0227/sys/src/9/mips/sysfile.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"
#include	"fcall.h"

/*
 * The sys*() routines needn't poperror() as they return directly to syscall().
 */

int
newfd(void)
{
	int i;

	for(i=0; i<NFD; i++)
		if(u->fd[i] == 0){
			if(i > u->maxfd)
				u->maxfd = i;
			return i;
		}
	error(0, Enofd);
}

Chan*
fdtochan(int fd, int mode)
{
	Chan *c;

	if(fd<0 || NFD<=fd || (c=u->fd[fd])==0)
		error(0, Ebadfd);
	if(mode<0 || c->mode == 2)
		return c;
	if((mode&16) && c->mode==0)
    err:
		error(0, Ebadusefd);
	if((mode&~16) != c->mode)
		goto err;
	return c;
}

int
openmode(ulong o)
{
	if(o >= (OTRUNC|OEXEC))
    Err:
		error(0, Ebadarg);
	o &= ~OTRUNC;
	if(o > OEXEC)
		goto Err;
	if(o == OEXEC)
		return OREAD;
	return o;
}

long
sysdup(ulong *arg)
{
	int fd;
	Chan *c, *oc;

	/*
	 * Close after dup'ing, so date > #d/1 works
	 */
	c = fdtochan(arg[0], -1);
	fd = arg[1];
	if(fd != -1)
		oc = u->fd[fd];
	else{
		oc = 0;
		fd = newfd();
	}
	u->fd[fd] = c;
	incref(c);
	if(oc)
		close(oc);
	return fd;
}

long
sysopen(ulong *arg)
{
	int fd;
	Chan *c;

	openmode(arg[1]);	/* error check only */
	fd = newfd();
	validaddr(arg[0], 1, 0);
	c = namec((char*)arg[0], Aopen, arg[1], 0);
	u->fd[fd] = c;
	return fd;
}

void
fdclose(int fd)
{
	int i;

	u->fd[fd] = 0;
	if(fd == u->maxfd)
		for(i=fd; --i>=0 && u->fd[i]==0; )
			u->maxfd = i;
}

long
sysclose(ulong *arg)
{
	Chan *c;

	c = fdtochan(arg[0], -1);
	close(c);
	fdclose(arg[0]);
	return 0;
}

long
unionread(Chan *c, void *va, long n)
{
	Mount *mnt;
	Chan *mc, *nc;
	Pgrp *pg = u->p->pgrp;
	long nr;

	mnt = c->mnt;
	lock(pg);
	if(c->mountid != mnt->mountid){
		print("unionread: changed underfoot?\n");
		unlock(pg);
		return 0;
	}
    Again:
	mc = mnt->c;
	incref(mc);
	unlock(pg);
	if(waserror()){
		close(mc);
		nexterror();
	}
	nc = clone(mc, 0);
	close(mc);
	poperror();
	if(waserror()){
		close(nc);
		nexterror();
	}
	nc = (*devtab[nc->type].open)(nc, OREAD);
	nc->offset = c->offset;
	nr = (*devtab[nc->type].read)(nc, va, n);
	close(nc);
	poperror();
	if(nr > 0)
		return nr;
	/*
	 * Advance to next element
	 */
	lock(pg);
	mnt = c->mnt;
	if(c->mountid != mnt->mountid){
		print("unionread: changed underfoot?\n");
		unlock(pg);
		return 0;
	}
	if(mnt->term){
		unlock(pg);
		return 0;
	}
	mnt = mnt->next;
	c->mnt = mnt;
	c->mountid = mnt->mountid;
	c->offset = 0;
	goto Again;
}

long
sysread(ulong *arg)
{
	Chan *c;
	long n;

	c = fdtochan(arg[0], 0);
	validaddr(arg[1], arg[2], 0);
	qlock(c);
	if(waserror()){
		qunlock(c);
		nexterror();
	}
	n = arg[2];
	if(c->qid&CHDIR){
		n -= n%DIRLEN;
		if(c->offset%DIRLEN || n==0)
			error(0, Ebaddirread);
	}
	if((c->qid&CHDIR) && c->flag&CMOUNT)
		n = unionread(c, (void*)arg[1], n);
	else
		n = (*devtab[c->type].read)(c, (void*)arg[1], n);
	c->offset += n;
	qunlock(c);
	return n;
}

long
syswrite(ulong *arg)
{
	Chan *c;
	long n;

	c = fdtochan(arg[0], 1);
	validaddr(arg[1], arg[2], 0);
	qlock(c);
	if(waserror()){
		qunlock(c);
		nexterror();
	}
	if(c->qid & CHDIR)
		error(0, Eisdir);
	n = (*devtab[c->type].write)(c, (void*)arg[1], arg[2]);
	c->offset += n;
	qunlock(c);
	return n;
}

long
sysseek(ulong *arg)
{
	Chan *c;
	char buf[DIRLEN];
	Dir dir;
	long off;

	c = fdtochan(arg[0], -1);
	if(c->qid & CHDIR)
		error(0, Eisdir);
	qlock(c);
	if(waserror()){
		qunlock(c);
		nexterror();
	}
	switch(arg[2]){
	case 0:
		c->offset = arg[1];
		break;

	case 1:
		c->offset += (long)arg[1];
		break;

	case 2:
		(*devtab[c->type].stat)(c, buf);
		convM2D(buf, &dir);
		c->offset = dir.length + (long)arg[1];
		break;
	}
	off = c->offset;
	qunlock(c);
	poperror();
	return off;
}

long
sysfstat(ulong *arg)
{
	Chan *c;
	long n;

	validaddr(arg[1], DIRLEN, 1);
	evenaddr(arg[1]);
	c = fdtochan(arg[0], -1);
	(*devtab[c->type].stat)(c, (char*)arg[1]);
	return 0;
}

long
sysstat(ulong *arg)
{
	Chan *c;
	long n;

	validaddr(arg[1], DIRLEN, 1);
	evenaddr(arg[1]);
	validaddr(arg[0], 1, 0);
	c = namec((char*)arg[0], Aaccess, 0, 0);
	if(waserror()){
		close(c);
		nexterror();
	}
	(*devtab[c->type].stat)(c, (char*)arg[1]);
	poperror();
	close(c);
	return 0;
}

long
sysaccess(ulong *arg)
{
	Chan *c;
	long mode;

	validaddr(arg[0], 1, 0);
	c = namec((char*)arg[0], Aaccess, 0, 0);
	mode = c->mode;
	close(c);
	/* BUG: check modes */
	return 0;
}

long
syschdir(ulong *arg)
{
	Chan *c;

	validaddr(arg[0], 1, 0);
	c = namec((char*)arg[0], Atodir, 0, 0);
	close(u->dot);
	u->dot = c;
	return 0;
}

long
bindmount(ulong *arg, int ismount)
{
	Chan *c0, *c1;
	ulong flag;
	long ret;
	struct{
		Chan	*chan;
		char	*spec;
	}bogus;

	flag = arg[2];
	if(flag>MMASK || (flag&MORDER)==(MBEFORE|MAFTER))
		error(0, Ebadarg);
	if(ismount){
		bogus.chan = fdtochan(arg[0], 2);
/*BUG: check validaddr for ALL of arg[3]!! */
		validaddr(arg[3], 1, 0);
		bogus.spec = (char*)arg[3];
		ret = devno('M', 0);
		c0 = (*devtab[ret].attach)((char*)&bogus);
	}else{
		validaddr(arg[0], 1, 0);
		c0 = namec((char*)arg[0], Aaccess, 0, 0);
	}
	if(waserror()){
		close(c0);
		nexterror();
	}
	validaddr(arg[1], 1, 0);
	c1 = namec((char*)arg[1], Amount, 0, 0);
	if(waserror()){
		close(c1);
		nexterror();
	}
	if((c0->qid^c1->qid) & CHDIR)
		error(0, Ebadmount);
	if(flag && !(c0->qid&CHDIR))
		error(0, Ebadmount);
	ret = mount(c0, c1, flag);
	close(c0);
	close(c1);
	if(ismount){
		close(bogus.chan);
		fdclose(arg[0]);
	}
	return ret;
}

long
sysbind(ulong *arg)
{
	return bindmount(arg, 0);
}

long
sysmount(ulong *arg)
{
	return bindmount(arg, 1);
}

long
syspipe(ulong *arg)
{
	int fd[2];
	Chan *c[2];
	Dev *d;

	validaddr(arg[0], 2*BY2WD, 1);
	evenaddr(arg[0]);
	d = &devtab[devno('|', 0)];
	c[0] = (*d->attach)(0);
	c[1] = 0;
	fd[0] = -1;
	fd[1] = -1;
	if(waserror()){
		close(c[0]);
		if(c[1])
			close(c[1]);
		if(fd[0] >= 0)
			u->fd[fd[0]]=0;
		if(fd[1] >= 0)
			u->fd[fd[1]]=0;
		nexterror();
	}
	c[1] = (*d->clone)(c[0], 0);
	c[0] = (*d->open)(c[0], ORDWR);
	c[1] = (*d->open)(c[1], ORDWR);
	c[0]->mode = 2;
	c[1]->mode = 2;
	c[0]->flag |= COPEN;
	c[1]->flag |= COPEN;
	fd[0] = newfd();
	u->fd[fd[0]] = c[0];
	fd[1] = newfd();
	u->fd[fd[1]] = c[1];
	((long*)arg[0])[0] = fd[0];
	((long*)arg[0])[1] = fd[1];
	poperror();
	return 0;
}

long
syscreate(ulong *arg)
{
	int fd;
	Chan *c;

	openmode(arg[1]);	/* error check only */
	fd = newfd();
	validaddr(arg[0], 1, 0);
	c = namec((char*)arg[0], Acreate, arg[1], arg[2]);
	u->fd[fd] = c;
	return fd;
}

long
sysuserstr(ulong *arg)
{
	Error err;
	char buf[NAMELEN];

	validaddr(arg[0], sizeof(Error), 0);
	validaddr(arg[1], NAMELEN, 1);
	err = *(Error*)arg[0];
	err.type = devno(err.type, 1);
	if(err.type == -1)
		strcpy((char*)arg[1], "*gok*");
	else{
		(*devtab[err.type].userstr)(&err, buf);
		memcpy((char*)arg[1], buf, sizeof buf);
	}
	return 0;
}

long
sysremove(ulong *arg)
{
	Chan *c;

	validaddr(arg[0], 1, 0);
	c = namec((char*)arg[0], Aaccess, 0, 0);
	if(waserror()){
		close(c);
		nexterror();
	}
	(*devtab[c->type].remove)(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;
	close(c);
	return 0;
}

long
syswstat(ulong *arg)
{
	Chan *c;
	long n;

	validaddr(arg[1], DIRLEN, 0);
	evenaddr(arg[1]);
	validaddr(arg[0], 1, 0);
	c = namec((char*)arg[0], Aaccess, 0, 0);
	if(waserror()){
		close(c);
		nexterror();
	}
	(*devtab[c->type].wstat)(c, (char*)arg[1]);
	poperror();
	close(c);
	return 0;
}

long
sysfwstat(ulong *arg)
{
	Chan *c;
	long n;

	validaddr(arg[1], DIRLEN, 0);
	evenaddr(arg[1]);
	c = fdtochan(arg[0], -1);
	(*devtab[c->type].wstat)(c, (char*)arg[1]);
	return 0;
}
.
## diffname port/sysfile.c 1990/0321
## diff -e /n/bootesdump/1990/0227/sys/src/9/mips/sysfile.c /n/bootesdump/1990/0321/sys/src/9/mips/sysfile.c
129c
		pprint("unionread: changed underfoot?\n");
.
## diffname port/sysfile.c 1990/03292
## diff -e /n/bootesdump/1990/0321/sys/src/9/mips/sysfile.c /n/bootesdump/1990/03292/sys/src/9/mips/sysfile.c
409,412d
## diffname port/sysfile.c 1990/0513
## diff -e /n/bootesdump/1990/03292/sys/src/9/mips/sysfile.c /n/bootesdump/1990/0513/sys/src/9/mips/sysfile.c
285a
print("stat error\n");
.
## diffname port/sysfile.c 1990/0617
## diff -e /n/bootesdump/1990/0513/sys/src/9/mips/sysfile.c /n/bootesdump/1990/0617/sys/src/9/mips/sysfile.c
286d
## diffname port/sysfile.c 1990/0703
## diff -e /n/bootesdump/1990/0617/sys/src/9/mips/sysfile.c /n/bootesdump/1990/0703/sys/src/9/mips/sysfile.c
459a
		c->type = 0;	/* see below */
.
## diffname port/sysfile.c 1990/08141
## diff -e /n/bootesdump/1990/0703/sys/src/9/mips/sysfile.c /n/bootesdump/1990/08141/sys/src/9/mips/sysfile.c
50c
	o &= ~(OTRUNC|OCEXEC|ORCLOSE);
.
47c
	if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC))
.
## diffname port/sysfile.c 1990/0821
## diff -e /n/bootesdump/1990/08141/sys/src/9/mips/sysfile.c /n/bootesdump/1990/0821/sys/src/9/mips/sysfile.c
195c
	if((c->qid&CHDIR) && (c->flag&CMOUNT))
.
150a
	c->offset = nc->offset;		/* devdirread e.g. changes it */
.
## diffname port/sysfile.c 1990/0822
## diff -e /n/bootesdump/1990/0821/sys/src/9/mips/sysfile.c /n/bootesdump/1990/0822/sys/src/9/mips/sysfile.c
302,306c
	postnote(u->p, 1, "access is deprecated", NDebug);
.
## diffname port/sysfile.c 1990/0918
## diff -e /n/bootesdump/1990/0822/sys/src/9/mips/sysfile.c /n/bootesdump/1990/0918/sys/src/9/mips/sysfile.c
334,335c
		p = (char*)arg[3];
		t = BY2PG-((ulong)p&(BY2PG-1));
		while(vmemchr(p, 0, t) == 0){
			p += t;
			t = BY2PG;
		}
.
323a
	char *p;
	int t;
.
## diffname port/sysfile.c 1990/1004
## diff -e /n/bootesdump/1990/0918/sys/src/9/mips/sysfile.c /n/bootesdump/1990/1004/sys/src/9/mips/sysfile.c
184c
	validaddr(arg[1], arg[2], 1);
.
## diffname port/sysfile.c 1990/1009
## diff -e /n/bootesdump/1990/1004/sys/src/9/mips/sysfile.c /n/bootesdump/1990/1009/sys/src/9/mips/sysfile.c
383,419d
211c
	c = fdtochan(arg[0], OWRITE);
.
183c
	c = fdtochan(arg[0], OREAD);
.
58a
syspipe(ulong *arg)
{
	int fd[2];
	Chan *c[2];
	Dev *d;

	validaddr(arg[0], 2*BY2WD, 1);
	evenaddr(arg[0]);
	d = &devtab[devno('|', 0)];
	c[0] = (*d->attach)(0);
	c[1] = 0;
	fd[0] = -1;
	fd[1] = -1;
	if(waserror()){
		close(c[0]);
		if(c[1])
			close(c[1]);
		if(fd[0] >= 0)
			u->fd[fd[0]]=0;
		if(fd[1] >= 0)
			u->fd[fd[1]]=0;
		nexterror();
	}
	c[1] = (*d->clone)(c[0], 0);
	(*d->walk)(c[0], "data");
	(*d->walk)(c[1], "data1");
	c[0] = (*d->open)(c[0], ORDWR);
	c[1] = (*d->open)(c[1], ORDWR);
	fd[0] = newfd();
	u->fd[fd[0]] = c[0];
	fd[1] = newfd();
	u->fd[fd[1]] = c[1];
	((long*)arg[0])[0] = fd[0];
	((long*)arg[0])[1] = fd[1];
	poperror();
	return 0;
}

long
.
39c
	if((mode&~OTRUNC) != c->mode)
.
36c
	if((mode&OTRUNC) && c->mode==OREAD)
.
34c
	if(mode<0 || c->mode==ORDWR)
.
## diffname port/sysfile.c 1990/11211
## diff -e /n/bootesdump/1990/1009/sys/src/9/mips/sysfile.c /n/bootesdump/1990/11211/sys/src/9/mips/sysfile.c
436,454d
398,401c
	if((c0->qid.path^c1->qid.path) & CHDIR)
		error(Ebadmount);
	if(flag && !(c0->qid.path&CHDIR))
		error(Ebadmount);
.
381a
		validaddr(arg[4], 1, 0);
		p = (char*)arg[4];
		t = BY2PG-((ulong)p&(BY2PG-1));
		while(vmemchr(p, 0, t) == 0){
			p += t;
			t = BY2PG;
		}
		bogus.auth = (char*)arg[4];
.
374a
		validaddr(arg[3], 1, 0);
.
372c
		error(Ebadarg);
.
367a
		char	*auth;
.
274,275c
	if(c->qid.path & CHDIR)
		error(Eisdir);
.
257,258c
	if(c->qid.path & CHDIR)
		error(Eisdir);
.
235c
	if((c->qid.path&CHDIR) && (c->flag&CMOUNT))
.
233c
			error(Ebaddirread);
.
230c
	if(c->qid.path & CHDIR){
.
49c
		error(Ebadarg);
.
38c
		error(Ebadusefd);
.
33c
		error(Ebadfd);
.
24c
	error(Enofd);
.
## diffname port/sysfile.c 1990/1126
## diff -e /n/bootesdump/1990/11211/sys/src/9/mips/sysfile.c /n/bootesdump/1990/1126/sys/src/9/mips/sysfile.c
332,341d
31a
	c = 0;	/* set */
.
## diffname port/sysfile.c 1990/1210
## diff -e /n/bootesdump/1990/1210/sys/src/9/mips/sysfile.c /n/bootesdump/1990/1210/sys/src/9/port/sysfile.c
492a

#ifdef asdf
long
sysfilsys(ulong *arg)
{
	Chan *cin, *cout;

	cin = fdtochan(arg[0], OREAD);
	cout = fdtochan(arg[1], OWRITE);
	validaddr(arg[2], 1, 0);
	if((cin->qid.path&CHDIR) || (cout->qid.path&CHDIR))
		error(Ebadarg);
	service((char *)arg[2], cin, cout, filsys);
	return 0;
}
#endif
.
32c
	c = 0;		/* set */
.
## diffname port/sysfile.c 1991/0221
## diff -e /n/bootesdump/1990/1210/sys/src/9/port/sysfile.c /n/bootesdump/1991/0221/sys/src/9/port/sysfile.c
111c
	}else{
.
109c
	if(fd != -1){
		if(fd<0 || NFD<=fd)
			error(Ebadfd);
		if(fd > u->maxfd)
			u->maxfd = fd;
.
## diffname port/sysfile.c 1991/0319
## diff -e /n/bootesdump/1991/0221/sys/src/9/port/sysfile.c /n/bootesdump/1991/0319/sys/src/9/port/sysfile.c
280a
	if(devchar[c->type] == '|')
		error(Eisstream);
.
## diffname port/sysfile.c 1991/0411
## diff -e /n/bootesdump/1991/0319/sys/src/9/port/sysfile.c /n/bootesdump/1991/0411/sys/src/9/port/sysfile.c
304c
	qunlock(&c->rdl);
	qunlock(&c->wrl);
.
285c
		qunlock(&c->rdl);
		qunlock(&c->wrl);
.
283c
	qlock(&c->rdl);
	qlock(&c->wrl);
.
266c
	qunlock(&c->wrl);
.
264c
	n = (*devtab[c->type].write)(c, (void*)arg[1], arg[2], c->offset);
.
259c
		qunlock(&c->wrl);
.
257c
	qlock(&c->wrl);
.
245c
	qunlock(&c->rdl);
.
243c
		n = (*devtab[c->type].read)(c, (void*)arg[1], n, c->offset);
.
231c
		qunlock(&c->rdl);
.
229c
	qlock(&c->rdl);
.
194c
	nr = (*devtab[nc->type].read)(nc, va, n, nc->offset);
.
## diffname port/sysfile.c 1991/0417
## diff -e /n/bootesdump/1991/0411/sys/src/9/port/sysfile.c /n/bootesdump/1991/0417/sys/src/9/port/sysfile.c
265a
	qunlock(&c->rdl);		/* BUG BUG BUG */
.
258a
		qunlock(&c->rdl);		/* BUG BUG BUG */
.
256a
	qlock(&c->rdl);		/* BUG BUG BUG */
.
245a
	qunlock(&c->wrl);		/* BUG BUG BUG */
.
231a
		qunlock(&c->wrl);		/* BUG BUG BUG */
.
229a
	qlock(&c->wrl);		/* BUG BUG BUG */
.
## diffname port/sysfile.c 1991/0419
## diff -e /n/bootesdump/1991/0417/sys/src/9/port/sysfile.c /n/bootesdump/1991/0419/sys/src/9/port/sysfile.c
271d
263d
260d
248d
233d
230d
## diffname port/sysfile.c 1991/0501
## diff -e /n/bootesdump/1991/0419/sys/src/9/port/sysfile.c /n/bootesdump/1991/0501/sys/src/9/port/sysfile.c
257a

.
229a

.
## diffname port/sysfile.c 1991/0614
## diff -e /n/bootesdump/1991/0501/sys/src/9/port/sysfile.c /n/bootesdump/1991/0614/sys/src/9/port/sysfile.c
467a
	poperror();
.
416a
	poperror();
	close(c0);
.
415c
	poperror();
.
310d
307a
	poperror();
.
267a
	poperror();
.
245a
	poperror();
.
## diffname port/sysfile.c 1991/0615
## diff -e /n/bootesdump/1991/0614/sys/src/9/port/sysfile.c /n/bootesdump/1991/0615/sys/src/9/port/sysfile.c
389,394c
		if(vmemchr((char*)arg[4], '\0', NAMELEN) == 0)
			error(Ebadarg);
.
381,386c
		if(vmemchr((char*)arg[3], '\0', NAMELEN) == 0)
			error(Ebadarg);
.
367,368d
## diffname port/sysfile.c 1991/0705
## diff -e /n/bootesdump/1991/0615/sys/src/9/port/sysfile.c /n/bootesdump/1991/0705/sys/src/9/port/sysfile.c
440c
	fd = newfd(c);
	poperror();
.
437c
	if(waserror()) {
		if(c)
			close(c);
		nexterror();
	}
.
434c
	Chan *c = 0;
.
411,414c
	if(ismount)
		fdclose(arg[0], 0);

.
366a
	char *p;
	int t;
.
197a
	close(nc);
.
196d
187a
	close(mc);
.
186d
157,158c
	fdclose(arg[0], 0);

.
145,148c
	lock(f);
	c = f->fd[fd];
	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);
	close(c);
.
143a
	Chan *c;
	Fgrp *f = u->p->fgrp;
.
141c
fdclose(int fd, int flag)
.
136c
	fd = newfd(c);
	poperror();
.
133c
	if(waserror()) {
		if(c)
			close(c);
		nexterror();
	}
.
130c
	Chan *c = 0;
.
119,122c

.
112,117c

		lock(f);
		if(fd > f->maxfd)
			f->maxfd = fd;
		incref(c);
		oc = f->fd[fd];
		f->fd[fd] = c;
		unlock(f);
		if(oc)
			close(oc);
	}else {
		if(waserror()) {
			close(c);
			nexterror();
		}
		incref(c);
		fd = newfd(c);
		poperror();
.
102a
	Fgrp *f = u->p->fgrp;
.
88,91c
	fd[0] = newfd(c[0]);
	fd[1] = newfd(c[1]);
.
80c
			f->fd[fd[1]]=0;
.
78c
			f->fd[fd[0]]=0;
.
64a
	Fgrp *f = u->p->fgrp;
.
32,33c
	USED(c);
	if(fd<0 || NFD<=fd || (c = u->p->fgrp->fd[fd])==0)
.
23a
	unlock(f);
.
19,21c
		if(f->fd[i] == 0){
			if(i > f->maxfd)
				f->maxfd = i;
			f->fd[i] = c;
			unlock(f);
.
17a
	lock(f);
.
15a
	Fgrp *f = u->p->fgrp;
.
14c
newfd(Chan *c)
.
## diffname port/sysfile.c 1991/0706
## diff -e /n/bootesdump/1991/0705/sys/src/9/port/sysfile.c /n/bootesdump/1991/0706/sys/src/9/port/sysfile.c
147c
	if(waserror()){
.
127c
	}else{
.
## diffname port/sysfile.c 1991/0904
## diff -e /n/bootesdump/1991/0706/sys/src/9/port/sysfile.c /n/bootesdump/1991/0904/sys/src/9/port/sysfile.c
186,188c
	fdtochan(arg[0], -1);
.
37c
	c = 0;
.
## diffname port/sysfile.c 1991/1011
## diff -e /n/bootesdump/1991/0904/sys/src/9/port/sysfile.c /n/bootesdump/1991/1011/sys/src/9/port/sysfile.c
535,550d
531c
	c = fdtochan(arg[0], -1, 1);
.
461a
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()) {
			close(cmount);
			nexterror();
		}
		validaddr(arg[0], 1, 0);
		cmounted = namec((char*)arg[0], Aaccess, 0, 0);
		poperror();
	}

	if(waserror()) {
		close(cmount);
		if(cmounted)
			close(cmounted);
		nexterror();
	}
	unmount(cmount, cmounted);
	close(cmount);
	if(cmounted)
		close(cmounted);
	poperror();	
	return 0;
}

long
.
409c
		bogus.chan = fdtochan(arg[0], 2, 0);
.
354c
	c = fdtochan(arg[0], -1, 0);
.
312c
	c = fdtochan(arg[0], -1, 1);
.
287c
	c = fdtochan(arg[0], OWRITE, 1);
.
271c
	if((c->qid.path&CHDIR) && c->mnt)
.
257c
	c = fdtochan(arg[0], OREAD, 1);
.
222,248c
	runlock(&pg->ns);
	return 0;
.
220c
		if(nr > 0) {
			runlock(&pg->ns);
			return nr;
		}
		/*
		 * Advance to next element
		 */
		c->mnt = c->mnt->next;
		if(c->mnt == 0)
			break;
		c->mountid = c->mnt->mountid;
		c->offset = 0;
.
200,218c
	rlock(&pg->ns);

	for(;;) {
		if(waserror()) {
			runlock(&pg->ns);
			nexterror();
		}
		nc = clone(c->mnt->to, 0);
		poperror();

		if(c->mountid != c->mnt->mountid){
			pprint("unionread: changed underfoot?\n");
			runlock(&pg->ns);
			close(nc);
			return 0;
		}

		if(waserror()){
			runlock(&pg->ns);
			close(nc);
			nexterror();
		}

		nc = (*devtab[nc->type].open)(nc, OREAD);
		nc->offset = c->offset;
		nr = (*devtab[nc->type].read)(nc, va, n, nc->offset);
		/* devdirread e.g. changes it */
		c->offset = nc->offset;	
		poperror();

.
195d
186c
	fdtochan(arg[0], -1, 0);
.
112c
	c = fdtochan(arg[0], -1, 0);
.
46c
		error(Ebadusefd);
.
43d
39a
	if(chkmnt && (c->flag&CMSG))
		errors("channel is mounted");
.
33c
fdtochan(int fd, int mode, int chkmnt)
.
## diffname port/sysfile.c 1991/1018
## diff -e /n/bootesdump/1991/1011/sys/src/9/port/sysfile.c /n/bootesdump/1991/1018/sys/src/9/port/sysfile.c
59c
		error(Ebadarg);
.
55d
## diffname port/sysfile.c 1991/1101
## diff -e /n/bootesdump/1991/1018/sys/src/9/port/sysfile.c /n/bootesdump/1991/1101/sys/src/9/port/sysfile.c
335,338d
332a
		off = c->offset;
.
326a
		off = c->offset;
		unlock(&c->offl);
.
325a
		lock(&c->offl);	/* lock for read/write update */
.
322c
		off = c->offset = arg[1];
.
313,319c
	off = 0;
.
296a
	poperror();
	lock(&c->offl);
	c->offset += n;
	unlock(&c->offl);
.
294,295d
273a
	poperror();
	lock(&c->offl);
	c->offset += n;
	unlock(&c->offl);
.
271,272d
## diffname port/sysfile.c 1991/1107
## diff -e /n/bootesdump/1991/1101/sys/src/9/port/sysfile.c /n/bootesdump/1991/1107/sys/src/9/port/sysfile.c
558c
	nameok((char*)arg[1]);
.
538c
	nameok((char*)arg[1]);
.
## diffname port/sysfile.c 1992/0111
## diff -e /n/bootesdump/1991/1107/sys/src/9/port/sysfile.c /n/bootesdump/1992/0111/sys/src/9/port/sysfile.c
6c
#include	"../port/error.h"
.
## diffname port/sysfile.c 1992/0114
## diff -e /n/bootesdump/1992/0111/sys/src/9/port/sysfile.c /n/bootesdump/1992/0114/sys/src/9/port/sysfile.c
431c
		error(Emount);
.
429c
		error(Emount);
.
265c
			error(Etoosmall);
.
41c
		error(Ebadusefd);
.
29c
	exhausted("file descriptors");
.
## diffname port/sysfile.c 1992/0312
## diff -e /n/bootesdump/1992/0114/sys/src/9/port/sysfile.c /n/bootesdump/1992/0312/sys/src/9/port/sysfile.c
411c
		bogus.serv = (char*)arg[4];
.
396c
		char	*serv;
.
## diffname port/sysfile.c 1992/0321
## diff -e /n/bootesdump/1992/0312/sys/src/9/port/sysfile.c /n/bootesdump/1992/0321/sys/src/9/port/sysfile.c
2c
#include	"../port/lib.h"
.
## diffname port/sysfile.c 1992/0520
## diff -e /n/bootesdump/1992/0321/sys/src/9/port/sysfile.c /n/bootesdump/1992/0520/sys/src/9/port/sysfile.c
29a
	return 0;		/* not reached */
.
## diffname port/sysfile.c 1992/0607
## diff -e /n/bootesdump/1992/0520/sys/src/9/port/sysfile.c /n/bootesdump/1992/0607/sys/src/9/port/sysfile.c
439,440c
		fdclose(fd, 0);
.
404c
		bogus.chan = fdtochan(fd, 2, 0);
.
400a
	fd = arg[0];
.
393c
	int t, fd;
.
180a
	if(c == 0)
		panic("fdclose");
.
## diffname port/sysfile.c 1992/0619
## diff -e /n/bootesdump/1992/0607/sys/src/9/port/sysfile.c /n/bootesdump/1992/0619/sys/src/9/port/sysfile.c
7d
## diffname port/sysfile.c 1992/0711
## diff -e /n/bootesdump/1992/0619/sys/src/9/port/sysfile.c /n/bootesdump/1992/0711/sys/src/9/port/sysfile.c
557d
537d
393,394c
	int fd;
.
359d
346d
197c
	Chan *nc;
.
## diffname port/sysfile.c 1992/0720
## diff -e /n/bootesdump/1992/0711/sys/src/9/port/sysfile.c /n/bootesdump/1992/0720/sys/src/9/port/sysfile.c
236,238c
		/* Advance to next element */
	next:
.
221c
			goto next;
.
218,219c
		/* Error causes component of union to be skipped */
		if(waserror()) {	
.
211c
		if(c->mountid != c->mnt->mountid) {
.
200a
	pg = u->p->pgrp;
.
199a
	Chan *nc;
	Pgrp *pg;
.
197,198d
29c
	return 0;
.
## diffname port/sysfile.c 1992/0817
## diff -e /n/bootesdump/1992/0720/sys/src/9/port/sysfile.c /n/bootesdump/1992/0817/sys/src/9/port/sysfile.c
180,181d
167a
	if(c == 0){
		/* can happen for users with shared fd tables */
		unlock(f);
		return;
	}
.
## diffname port/sysfile.c 1992/0825
## diff -e /n/bootesdump/1992/0817/sys/src/9/port/sysfile.c /n/bootesdump/1992/0825/sys/src/9/port/sysfile.c
560a
	poperror();
	close(c);
.
559c
	c = fdtochan(arg[0], -1, 1, 1);
	if(waserror()) {
		close(c);
		nexterror();
	}
.
417c

		poperror();
		close(bc);
	}
	else {
.
413a

.
409a

.
406c
		bc = fdtochan(fd, 2, 0, 1);
		if(waserror()) {
			close(bc);
			nexterror();
		}
		bogus.chan = bc;

.
391c
	Chan *c0, *c1, *bc;
.
353a
	poperror();
	close(c);
.
352c
	c = fdtochan(arg[0], -1, 0, 1);
	if(waserror()) {
		close(c);
		nexterror();
	}
.
332c
		unlock(c);
.
329c
		lock(c);	/* lock for read/write update */
.
321a

.
319a

.
317c
	c = fdtochan(arg[0], -1, 1, 0);
.
305c
	unlock(c);

	poperror();
	close(c);

.
301,303c

	lock(c);
.
299a

.
297a

.
292,295c
	c = fdtochan(arg[0], OWRITE, 1, 1);
	if(waserror()) {
		close(c);
.
290d
280c
	unlock(c);

	poperror();
	close(c);

.
276,278c

	lock(c);
.
272c

	if(dir && c->mnt)
.
267c
	dir = c->qid.path&CHDIR;

	if(dir) {
.
265a

.
260,263c
	c = fdtochan(arg[0], OREAD, 1, 1);
	if(waserror()) {
		close(c);
.
258d
256a
	Chan *c;
.
255c
	int dir;
.
191c
	fdtochan(arg[0], -1, 0, 0);
.
132d
121c

.
117c
		}
.
115c
		if(fd<0 || NFD<=fd) {
			close(c);
.
112c
	c = fdtochan(arg[0], -1, 0, 1);
.
47a
	}

.
46c
	}

	if((mode&~OTRUNC) != c->mode) {
		if(iref)
			close(c);
.
44c

	if((mode&OTRUNC) && c->mode==OREAD) {
		if(iref)
			close(c);
.
41a
	}

.
40c
	}
	if(iref)
		incref(c);
	unlock(f);

	if(chkmnt && (c->flag&CMSG)) {
		if(iref)
			close(c);
.
38c
	f = u->p->fgrp;

	lock(f);
	if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) {
		unlock(f);
.
35a
	Fgrp *f;
.
33c
fdtochan(int fd, int mode, int chkmnt, int iref)
.
## diffname port/sysfile.c 1993/0209
## diff -e /n/bootesdump/1992/0825/sys/src/9/port/sysfile.c /n/bootesdump/1993/0209/sys/src/9/port/sysfile.c
87a
sysfsession(ulong *arg)
{
	USED(arg);
	return 0;
}

long
.
## diffname port/sysfile.c 1993/0317
## diff -e /n/bootesdump/1993/0209/sys/src/9/port/sysfile.c /n/bootesdump/1993/0317/sys/src/9/port/sysfile.c
278c
	qunlock(&pg->nsh);
.
272c
		c->mnt = c->mnt->mount;
.
267c
			qunlock(&pg->nsh);
.
261c
		/*
		 * devdirread e.g. changes it
		 */
.
252c
		/*
		 * Error causes component of union to be skipped
		 */
.
246,247c
			pprint("unionread: changed underfoot\n");
			qunlock(&pg->nsh);
.
242c
		nc = clone(c->mnt->cmnt, 0);
.
239c
			qunlock(&pg->nsh);
.
235c
	qlock(&pg->nsh);
.
## diffname port/sysfile.c 1993/0318
## diff -e /n/bootesdump/1993/0317/sys/src/9/port/sysfile.c /n/bootesdump/1993/0318/sys/src/9/port/sysfile.c
282c
	runlock(&pg->ns);
.
276c
		c->mnt = c->mnt->next;
.
271c
			runlock(&pg->ns);
.
263,265c
		/* devdirread e.g. changes it */
.
252,254c
		/* Error causes component of union to be skipped */
.
246,247c
			pprint("unionread: changed underfoot?\n");
			runlock(&pg->ns);
.
242c
		nc = clone(c->mnt->to, 0);
.
239c
			runlock(&pg->ns);
.
235c
	rlock(&pg->ns);
.
## diffname port/sysfile.c 1993/0330
## diff -e /n/bootesdump/1993/0318/sys/src/9/port/sysfile.c /n/bootesdump/1993/0330/sys/src/9/port/sysfile.c
469d
465,467d
445d
88,94d
## diffname port/sysfile.c 1993/0501
## diff -e /n/bootesdump/1993/0330/sys/src/9/port/sysfile.c /n/fornaxdump/1993/0501/sys/src/brazil/port/sysfile.c
478,482c

	ret = mount(c0, c1, flag, bogus.spec);

.
471a

.
467a

.
464a
		bogus.spec = 0;
.
445c
		bc = fdtochan(fd, ORDWR, 0, 1);
.
443a

	bogus.recov = flag&MRECOV;

.
437a
		char	recov;
.
433,434c
	int fd, ret;
	Chan *c0, *c1, *bc;
.
431d
423,424c
	close(up->dot);
	up->dot = c;
.
421a

.
227c
	pg = up->pgrp;
.
187c
	Fgrp *f = up->fgrp;
.
130c
	Fgrp *f = up->fgrp;
.
112,114c
	c[1] = clone(c[0], 0);
	walk(c[0], "data", 1);
	walk(c[1], "data1", 1);
.
98c
	c[0] = namec("#|", Atodir, 0, 0);
.
93c
	Fgrp *f = up->fgrp;
.
39c
	f = up->fgrp;
.
15c
	Fgrp *f = up->fgrp;
.
## diffname port/sysfile.c 1993/1004
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/sysfile.c /n/fornaxdump/1993/1004/sys/src/brazil/port/sysfile.c
87a
syspath(ulong *arg)
{
	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);

	ptpath(c->path, (char*)arg[1], arg[2]);
	return 0;
}

long
.
## diffname port/sysfile.c 1993/1014
## diff -e /n/fornaxdump/1993/1004/sys/src/brazil/port/sysfile.c /n/fornaxdump/1993/1014/sys/src/brazil/port/sysfile.c
461c
	bogus.flags = flag & (MRECOV|MCACHE);
.
453c
		int	flags;
.
## diffname port/sysfile.c 1993/1111
## diff -e /n/fornaxdump/1993/1014/sys/src/brazil/port/sysfile.c /n/fornaxdump/1993/1111/sys/src/brazil/port/sysfile.c
540c
		cmounted = namec((char*)arg[0], Aopen, OREAD, 0);
.
## diffname port/sysfile.c 1994/0321
## diff -e /n/fornaxdump/1993/1111/sys/src/brazil/port/sysfile.c /n/fornaxdump/1994/0321/sys/src/brazil/port/sysfile.c
88c
sysfd2path(ulong *arg)
.
## diffname port/sysfile.c 1994/0402
## diff -e /n/fornaxdump/1994/0321/sys/src/brazil/port/sysfile.c /n/fornaxdump/1994/0402/sys/src/brazil/port/sysfile.c
328a
syswrite9p(ulong *arg)
{
	Chan *c;
	long n;

	validaddr(arg[1], arg[2], 0);
	c = fdtochan(arg[0], OWRITE, 1, 1);
	if(waserror()) {
		close(c);
		nexterror();
	}

	if(c->qid.path & CHDIR)
		error(Eisdir);

	if(devchar[c->type] != L'M')
		n = (*devtab[c->type].write)(c, (void*)arg[1], arg[2], c->offset);
	else
		n = mntwrite9p(c, (void*)arg[1], arg[2], c->offset);

	lock(c);
	c->offset += n;
	unlock(c);

	poperror();
	close(c);

	return n;
}

long
.
## diffname port/sysfile.c 1994/0405
## diff -e /n/fornaxdump/1994/0402/sys/src/brazil/port/sysfile.c /n/fornaxdump/1994/0405/sys/src/brazil/port/sysfile.c
348d
290a
sysread9p(ulong *arg)
{
	int dir;
	long n;
	Chan *c;

	validaddr(arg[1], arg[2], 1);
	c = fdtochan(arg[0], OREAD, 1, 1);
	if(waserror()) {
		close(c);
		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')
		n = (*devtab[c->type].read)(c, (void*)arg[1], n, c->offset);
	else
		n = mntread9p(c, (void*)arg[1], n, c->offset);


	lock(c);
	c->offset += n;
	unlock(c);

	poperror();
	close(c);

	return n;
}

long
.
## diffname port/sysfile.c 1994/0406
## diff -e /n/fornaxdump/1994/0405/sys/src/brazil/port/sysfile.c /n/fornaxdump/1994/0406/sys/src/brazil/port/sysfile.c
320d
## diffname port/sysfile.c 1994/0611
## diff -e /n/fornaxdump/1994/0406/sys/src/brazil/port/sysfile.c /n/fornaxdump/1994/0611/sys/src/brazil/port/sysfile.c
97c
	/* 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);
.
## diffname port/sysfile.c 1994/0616
## diff -e /n/fornaxdump/1994/0611/sys/src/brazil/port/sysfile.c /n/fornaxdump/1994/0616/sys/src/brazil/port/sysfile.c
550a
		nameok(bogus.spec);
.
## diffname port/sysfile.c 1994/0622
## diff -e /n/fornaxdump/1994/0616/sys/src/brazil/port/sysfile.c /n/fornaxdump/1994/0622/sys/src/brazil/port/sysfile.c
551c
		if(strchr(bogus.spec, ' '))
			error(Ebadspec);
.
## diffname port/sysfile.c 1997/0327
## diff -e /n/fornaxdump/1994/0622/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/0327/sys/src/brazil/port/sysfile.c
710c
	cclose(c);
.
708c
	devtab[c->type]->wstat(c, (char*)arg[1]);
.
705c
		cclose(c);
.
692c
	cclose(c);
.
690c
	devtab[c->type]->wstat(c, (char*)arg[1]);
.
687c
		cclose(c);
.
673c
	cclose(c);
.
666c
	devtab[c->type]->remove(c);
.
663c
		cclose(c);
.
644c
			cclose(c);
.
630c
		cclose(cmounted);
.
627,628c

	cunmount(cmount, cmounted);
	cclose(cmount);
.
624c
			cclose(cmounted);
.
622c
		cclose(cmount);
.
613c
			cclose(cmount);
.
583c
	cclose(c0);
.
581c
	cclose(c1);
.
578c
	ret = cmount(c0, c1, flag, bogus.spec);
.
574c
		cclose(c1);
.
567c
		cclose(c0);
.
558c
		cclose(bc);
.
555c
		c0 = devtab[ret]->attach((char*)&bogus);
.
541c
			cclose(bc);
.
514c
	cclose(up->dot);
.
502c
	cclose(c);
.
500c
	devtab[c->type]->stat(c, (char*)arg[1]);
.
497c
		cclose(c);
.
483c
	cclose(c);
.
481c
	devtab[c->type]->stat(c, (char*)arg[1]);
.
478c
		cclose(c);
.
460c
		devtab[c->type]->stat(c, buf);
.
426c
	cclose(c);
.
419c
	n = devtab[c->type]->write(c, (void*)arg[1], arg[2], c->offset);
.
412c
		cclose(c);
.
398c
	cclose(c);
.
390c
		n = devtab[c->type]->write(c, (void*)arg[1], arg[2], c->offset);
.
382c
		cclose(c);
.
368c
	cclose(c);
.
361c
		n = devtab[c->type]->read(c, (void*)arg[1], n, c->offset);
.
345c
		cclose(c);
.
330c
	cclose(c);
.
321c
		n = devtab[c->type]->read(c, (void*)arg[1], n, c->offset);
.
305c
		cclose(c);
.
278c
		cclose(nc);
.
273c
		nr = devtab[nc->type]->read(nc, va, n, nc->offset);
.
271c
		nc = devtab[nc->type]->open(nc, OREAD);
.
267c
			cclose(nc);
.
261c
			cclose(nc);
.
255c
		nc = cclone(c->mnt->to, 0);
.
228c
	cclose(c);
.
192c
			cclose(c);
.
173c
			cclose(c);
.
170c
			cclose(oc);
.
159c
			cclose(c);
.
135,136c
	c[0] = d->open(c[0], ORDWR);
	c[1] = d->open(c[1], ORDWR);
.
132c
	c[1] = cclone(c[0], 0);
.
125c
			cclose(c[1]);
.
123c
		cclose(c[0]);
.
117c
	d = devtab[devno('|', 0)];
.
67c
			cclose(c);
.
61c
			cclose(c);
.
52c
			cclose(c);
.
16a
	Fgrp *f = up->fgrp;
.
15d
## diffname port/sysfile.c 1997/0408
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/0408/sys/src/brazil/port/sysfile.c
443c
	if(devtab[c->type]->dc == '|')
.
389c
	if(devtab[c->type]->dc != L'M')
.
320c
	else if(devtab[c->type]->dc != L'M')
.
## diffname port/sysfile.c 1997/0529
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/0529/sys/src/brazil/port/sysfile.c
27a
print("process %d (%s) out of file descriptors\n", up->pid, up->text);
.
## diffname port/sysfile.c 1997/0603
## diff -e /n/emeliedump/1997/0529/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/0603/sys/src/brazil/port/sysfile.c
159c
		if(fd<0 || f->nfd<=fd) {
.
43c
	if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) {
.
28,30c
	free(oldfd);
	if(i%100 == 0)
		pprint("warning: process exceeds %d file descriptors\n", i);
	return i;
.
26a
	/*
	 * Unbounded allocation is unwise; besides, there are only 16 bits
	 * of fid in 9P
	 */
	if(f->nfd >= 5000){
		unlock(f);
		exhausted("file descriptors");
		return -1;
	}
	newfd = smalloc((f->nfd+DELTAFD)*sizeof(Chan*));
	oldfd = f->fd;
	memmove(newfd, oldfd, f->nfd*sizeof(Chan*));
	f->fd = newfd;
	f->nfd += DELTAFD;
	f->maxfd = i;
	f->fd[i] = c;
.
19c
	for(i=0; i<f->nfd; i++)
.
16a
	Chan **newfd, **oldfd;
.
## diffname port/sysfile.c 1997/0606
## diff -e /n/emeliedump/1997/0603/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/0606/sys/src/brazil/port/sysfile.c
37c
	newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*));
	if(newfd == 0)
		goto Exhausted;
.
32a
   Exhausted:
.
## diffname port/sysfile.c 1997/1104
## diff -e /n/emeliedump/1997/0606/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/1104/sys/src/brazil/port/sysfile.c
7a
void
poot(char *s, int d)
{
	if(up->slash->type<0||up->slash->type>50||(up->slash->flag&COPEN))
		panic("poot: %s %d=%lux\n", s, d, d);
}

.
## diffname port/sysfile.c 1997/1105
## diff -e /n/emeliedump/1997/1104/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/1105/sys/src/brazil/port/sysfile.c
8,14d
## diffname port/sysfile.c 1997/1203
## diff -e /n/emeliedump/1997/1105/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/1203/sys/src/brazil/port/sysfile.c
184d
180a
			unlock(f);
.
179a
		lock(f);
.
## diffname port/sysfile.c 1997/1205
## diff -e /n/emeliedump/1997/1203/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/1205/sys/src/brazil/port/sysfile.c
124a
	poperror();
	if(c == oc)
		cclose(c);

.
122a
	oc = c;
.
118c
	/*
	 * Undomount below may cclose the chan so bump the
	 * reference count to guard against it going to zero
	 * and being freed.
	 */
	c = fdtochan(arg[0], -1, 0, 1);
	if(waserror()) {
		cclose(c);
		nexterror();
	}
.
112c
	Chan *c, *oc;
.
## diffname port/sysfile.c 1997/1208
## diff -e /n/emeliedump/1997/1205/sys/src/brazil/port/sysfile.c /n/emeliedump/1997/1208/sys/src/brazil/port/sysfile.c
518a
okchan("after stat routine", c->type);
.
517a
okchan("before stat routine", c->type);
.
233a
okchan("after open namec", 0);
.
232a
okchan("before open namec", 0);
.
## diffname port/sysfile.c 1998/0221
## diff -e /n/emeliedump/1997/1208/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0221/sys/src/brazil/port/sysfile.c
522d
520d
235d
233d
## diffname port/sysfile.c 1998/0224
## diff -e /n/emeliedump/1998/0221/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0224/sys/src/brazil/port/sysfile.c
169,170c
	if(walk(&c[0], "data", 1) < 0)
		error(Egreg);
	if(walk(&c[1], "data1", 1) < 0)
		error(Egreg);
.
## diffname port/sysfile.c 1998/0319
## diff -e /n/emeliedump/1998/0224/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0319/sys/src/brazil/port/sysfile.c
505a
}

long
sysseek(ulong *arg)
{
	union {
		vlong v;
		ulong u[2];
	} o;
	ulong a[4];

	o.v = arg[1];
	a[0] = arg[0];
	a[1] = o.u[0];
	a[2] = o.u[1];
	a[3] = arg[2];
	return sysvseek(a);
.
501,502c
		off = (long)dir.length2 + o.v;	/* BOTCH */
		c->offset = off;
.
493,494c
		off = o.v + c->offset;
		c->offset = off;
.
488c
		off = o.v;
		c->offset = off;
.
486c
	o.u[0] = arg[1];
	o.u[1] = arg[2];
	switch(arg[3]){
.
476c
	vlong off;
	union {
		vlong v;
		ulong u[2];
	} o;
.
471c
sysvseek(ulong *arg)
.
## diffname port/sysfile.c 1998/0320
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0320/sys/src/brazil/port/sysfile.c
508c
		off = (long)dir.length1 + o.v;	/* BOTCH */
.
## diffname port/sysfile.c 1998/0326
## diff -e /n/emeliedump/1998/0320/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0326/sys/src/brazil/port/sysfile.c
525,529c
	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;
.
522c
	ulong a[5];
.
515a
sysvseek(ulong *arg)
{
	validaddr(arg[0], BY2V, 1);
	sseek(arg);
	return 0;
}

long
.
512c
	*(vlong*)arg[0] = off;
.
508c
		off = dir.length + o.v;
.
490,492c
	o.u[0] = arg[2];
	o.u[1] = arg[3];
	switch(arg[4]){
.
482c
	c = fdtochan(arg[1], -1, 1, 0);
.
470,471c
static void
sseek(ulong *arg)
.
## diffname port/sysfile.c 1998/0403
## diff -e /n/emeliedump/1998/0326/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0403/sys/src/brazil/port/sysfile.c
512a
	cclose(c);
	poperror();
.
482c
	c = fdtochan(arg[1], -1, 1, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}
.
## diffname port/sysfile.c 1998/0512
## diff -e /n/emeliedump/1998/0403/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0512/sys/src/brazil/port/sysfile.c
711c
	poperror();
.
314c
		c->offset = nc->offset;
.
305c
		if(waserror()) {
.
## diffname port/sysfile.c 1998/0829
## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0829/sys/src/brazil/port/sysfile.c
516a
	c->uri = 0;
.
397c
	if(dir && c->mh)
.
357c
	if(dir && c->mh)
.
330c
	runlock(&m->lock);
.
327d
324,325c
		c->uri++;
		mount = mount->next;
		if(mount == nil)
.
319c
			runlock(&m->lock);
.
297,303d
294c
		nc = cclone(mount->to, 0);
.
291c
			runlock(&m->lock);
.
286,287c
	m = c->mh;
	rlock(&m->lock);
	mount = m->mount;
	for(i = 0; mount != nil && i < c->uri; i++)
		mount = mount->next;
.
284c
	Mhead *m;
	Mount *mount;
.
281a
	int i;
.
## diffname port/sysfile.c 1998/0901
## diff -e /n/emeliedump/1998/0829/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0901/sys/src/brazil/port/sysfile.c
298a
		if(mount->to == nil)
			goto next;
.
294c
	while(mount != nil) {
.
## diffname port/sysfile.c 1998/0915
## diff -e /n/emeliedump/1998/0901/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0915/sys/src/brazil/port/sysfile.c
531c
sysoseek(ulong *arg)
.
523c
sysseek(ulong *arg)
.
## diffname port/sysfile.c 1998/0922
## diff -e /n/emeliedump/1998/0915/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0922/sys/src/brazil/port/sysfile.c
462a

	m = devtab[c->type]->write(c, (void*)arg[1], n, oo);

	if(m < n){
		lock(c);
		c->offset = oo + m;
		unlock(c);
	}
.
460a
	oo = c->offset;
.
458,459d
451a
		lock(c);
		c->offset -= n;
		unlock(c);
.
448a
	n = arg[2];
.
446c
	long m, n;
	uvlong oo;
.
388d
382a

.
381c
	n = arg[2];
	validaddr(arg[1], n, 1);
.
## diffname port/sysfile.c 1998/0923
## diff -e /n/emeliedump/1998/0922/sys/src/brazil/port/sysfile.c /n/emeliedump/1998/0923/sys/src/brazil/port/sysfile.c
473c
		c->offset -= n - m;
.
## diffname port/sysfile.c 1999/0122
## diff -e /n/emeliedump/1998/0923/sys/src/brazil/port/sysfile.c /n/emeliedump/1999/0122/sys/src/brazil/port/sysfile.c
99,100d
## diffname port/sysfile.c 1999/0528
## diff -e /n/emeliedump/1999/0122/sys/src/brazil/port/sysfile.c /n/emeliedump/1999/0528/sys/src/brazil/port/sysfile.c
112,114c
	validaddr(arg[1], arg[2], 1);
.
## diffname port/sysfile.c 1999/0629
## diff -e /n/emeliedump/1999/0528/sys/src/brazil/port/sysfile.c /n/emeliedump/1999/0629/sys/src/brazil/port/sysfile.c
167c
	if(walkname(&c[1], "data1", 1) < 0)
.
165c
	if(walkname(&c[0], "data", 1) < 0)
.
135c
	if(c->name == nil)
		snprint((char*)arg[1], arg[2], "<null>");
	else
		snprint((char*)arg[1], arg[2], "%s", c->name->s);

	poperror();
.
124,133d
110c
	Chan *c;
.
## diffname port/sysfile.c 1999/0709
## diff -e /n/emeliedump/1999/0629/sys/src/brazil/port/sysfile.c /n/emeliedump/1999/0709/sys/src/brazil/port/sysfile.c
129,130c
	cclose(c);
.
120,123d
114,118d
## diffname port/sysfile.c 1999/0717
## diff -e /n/emeliedump/1999/0709/sys/src/brazil/port/sysfile.c /n/emeliedump/1999/0717/sys/src/brazil/port/sysfile.c
626a
		nameok(bogus.spec);
		poperror();
.
625c
		if(waserror())
.
## diffname port/sysfile.c 1999/0718
## diff -e /n/emeliedump/1999/0717/sys/src/brazil/port/sysfile.c /n/emeliedump/1999/0718/sys/src/brazil/port/sysfile.c
779c
	nameok((char*)arg[1], 0);
.
760c
	nameok((char*)arg[1], 0);
.
627c
		nameok(bogus.spec, 1);
.
## diffname port/sysfile.c 1999/0811
## diff -e /n/emeliedump/1999/0718/sys/src/brazil/port/sysfile.c /n/emeliedump/1999/0811/sys/src/brazil/port/sysfile.c
152c
	if(walk(&c[1], "data1", 1) < 0)
.
150c
	if(walk(&c[0], "data", 1) < 0)
.
## diffname port/sysfile.c 1999/0812
## diff -e /n/emeliedump/1999/0811/sys/src/brazil/port/sysfile.c /n/emeliedump/1999/0812/sys/src/brazil/port/sysfile.c
789a

long
sysexportfs(ulong*)
{
	error("exportfs not implemented");
	return -1;
}

long
systunnel(ulong*)
{
	error("tunnel not implemented");
	return -1;
}
.
## diffname port/sysfile.c 1999/1105
## diff -e /n/emeliedump/1999/0812/sys/src/brazil/port/sysfile.c /n/emeliedump/1999/1105/sys/src/9/port/sysfile.c
610c
	bogus.flags = flag & MCACHE;
.
## diffname port/sysfile.c 2000/0209
## diff -e /n/emeliedump/1999/1105/sys/src/9/port/sysfile.c /n/emeliedump/2000/0209/sys/src/9/port/sysfile.c
790,803d
## diffname port/sysfile.c 2000/0215
## diff -e /n/emeliedump/2000/0209/sys/src/9/port/sysfile.c /n/emeliedump/2000/0215/sys/src/9/port/sysfile.c
726a
	if(fd < 0)
		error(Enofd);
.
217a
	if(fd < 0)
		error(Enofd);
.
196a
		if(fd < 0)
			error(Enofd);
.
178c
		if(fd<0 || growfd(f, fd)<0) {
.
157a
	if(fd[0] < 0 || fd[1] < 0)
		error(Enofd);
.
48,51c
	return fd;
.
45,46c
	if(fd > f->maxfd)
		f->maxfd = fd;
	return 1;
}

int
newfd(Chan *c)
{
	int fd;
	Fgrp *f;

	f = up->fgrp;
	lock(f);
	for(fd=0; fd<f->nfd; fd++)
		if(f->fd[fd] == 0)
			break;
	if(fd >= f->nfd && growfd(f, fd) < 0){
		unlock(f);
		return -1;
	}
	if(fd > f->maxfd)
		f->maxfd = fd;
	f->fd[fd] = c;
.
43a
	free(oldfd);
.
33,34c
    Exhausted:
.
19,27c
	if(fd < f->nfd)
		return 0;
	if(fd >= f->nfd+DELTAFD)
		return -1;	/* out of range */
	if(fd % 100 == 0)
		pprint("warning: process exceeds %d file descriptors\n", fd);
.
15,16d
13c
growfd(Fgrp *f, int fd)	/* fd is always >= 0 */
.
## diffname port/sysfile.c 2000/0322
## diff -e /n/emeliedump/2000/0215/sys/src/9/port/sysfile.c /n/emeliedump/2000/0322/sys/src/9/port/sysfile.c
631a
		if(up->pgrp->noattach)
			error(Enoattach);

.
## diffname port/sysfile.c 2000/0505
## diff -e /n/emeliedump/2000/0322/sys/src/9/port/sysfile.c /n/emeliedump/2000/0505/sys/src/9/port/sysfile.c
480c
	return m;
.
## diffname port/sysfile.c 2000/0719
## diff -e /n/emeliedump/2000/0505/sys/src/9/port/sysfile.c /n/emeliedump/2000/0719/sys/src/9/port/sysfile.c
29c
		print("no free file descriptors\n");
.
## diffname port/sysfile.c 2000/0814
## diff -e /n/emeliedump/2000/0719/sys/src/9/port/sysfile.c /n/emeliedump/2000/0814/sys/src/9/port/sysfile.c
175d
172a
	poperror();

.
169,171c
	if(newfd2(fd, c) < 0)
.
156,159d
151a

.
143d
66a
int
newfd2(int fd[2], Chan *c[2])
{
	Fgrp *f;

	f = up->fgrp;
	lock(f);
	fd[0] = findfreefd(f, 0);
	if(fd[0] < 0){
		unlock(f);
		return -1;
	}
	fd[1] = findfreefd(f, fd[0]+1);
	if(fd[1] < 0){
		unlock(f);
		return -1;
	}
	if(fd[1] > f->maxfd)
		f->maxfd = fd[1];
	f->fd[fd[0]] = c[0];
	f->fd[fd[1]] = c[1];
	unlock(f);

	return 0;
}

.
53,56c
	fd = findfreefd(f, 0);
	if(fd < 0){
.
45a
findfreefd(Fgrp *f, int start)
{
	int fd;

	for(fd=start; fd<f->nfd; fd++)
		if(f->fd[fd] == 0)
			break;
	if(fd >= f->nfd && growfd(f, fd) < 0)
		return -1;
	return fd;
}

int
.
44a
/*
 *  this assumes that the fgrp is locked
 */
.
## diffname port/sysfile.c 2001/0207
## diff -e /n/emeliedump/2000/0814/sys/src/9/port/sysfile.c /n/emeliedump/2001/0207/sys/src/9/port/sysfile.c
587c
	o.v = (long)arg[1];
.
## diffname port/sysfile.c 2001/0223
## diff -e /n/emeliedump/2001/0207/sys/src/9/port/sysfile.c /n/emeliedump/2001/0223/sys/src/9/port/sysfile.c
510a

	poperror();
	cclose(c);

	return m;
}

long
syspwrite(ulong *arg)
{
	Chan *c;
	long m, n;
	union {
		uvlong v;
		ulong u[2];
	} o;

	validaddr(arg[1], arg[2], 0);
	n = arg[2];
	c = fdtochan(arg[0], OWRITE, 1, 1);
	o.u[0] = arg[3];
	o.u[1] = arg[4];
	if(waserror()) {
		cclose(c);
		nexterror();
	}

	if(c->qid.path & CHDIR)
		error(Eisdir);

	m = devtab[c->type]->write(c, (void*)arg[1], n, o.v);
.
448a
syspread(ulong *arg)
{
	long n;
	Chan *c;
	union {
		uvlong v;
		ulong u[2];
	} o;

	n = arg[2];
	validaddr(arg[1], n, 1);
	c = fdtochan(arg[0], OREAD, 1, 1);
	o.u[0] = arg[3];
	o.u[1] = arg[4];

	if(waserror()) {
		cclose(c);
		nexterror();
	}

	if(c->qid.path&CHDIR)
		error(Eisdir);

	n = devtab[c->type]->read(c, (void*)arg[1], n, o.v);

	poperror();
	cclose(c);

	return n;
}

long
.
## diffname port/sysfile.c 2001/0502
## diff -e /n/emeliedump/2001/0223/sys/src/9/port/sysfile.c /n/emeliedump/2001/0502/sys/src/9/port/sysfile.c
558a

	if(arg[3] == ~0UL && arg[4] == ~0UL)
		return syswrite(arg);
.
457a
	if(arg[3] == ~0UL && arg[4] == ~0UL)
		return sysread(arg);

.
## diffname port/sysfile.c 2001/0527
## diff -e /n/emeliedump/2001/0502/sys/src/9/port/sysfile.c /n/emeliedump/2001/0527/sys/src/9/port/sysfile.c
916a
}

long
sys_fstat(ulong *arg)
{
	Chan *c;
	uint l;
	uchar buf[128];	/* old DIRLEN plus a little should be plenty */
	char strs[128];
	Dir d;
	char old[] = "old fstat system call - recompile";

	validaddr(arg[1], 116, 1);
	c = fdtochan(arg[0], -1, 0, 1);
	if(waserror()){
		cclose(c);
		nexterror();
	}
	l = devtab[c->type]->stat(c, buf, sizeof buf);
	/* buf contains a new stat buf; convert to old. yuck. */
	if(l <= BIT16SZ)	/* buffer too small; time to face reality */
		error(old);
	l = convM2D(buf, l, &d, strs);
	if(l == 0)
		error(old);
	packoldstat((uchar*)arg[1], &d);
	
	poperror();
	cclose(c);
	return 0;
}

long
sys_wstat(ulong *)
{
	error("old wstat system call - recompile");
	return -1;
}

long
sys_fwstat(ulong *)
{
	error("old fwstat system call - recompile");
	return -1;
.
915a
	return l;
}

static void
packoldstat(uchar *buf, Dir *d)
{
	uchar *p;
	ulong q;

	/* lay down old stat buffer - grotty code but it's temporary */
	p = buf;
	strncpy((char*)p, d->name, 28);
	p += 28;
	strncpy((char*)p, d->uid, 28);
	p += 28;
	strncpy((char*)p, d->gid, 28);
	p += 28;
	q = d->qid.path & ~DMDIR;	/* make sure doesn't accidentally look like directory */
	if(d->qid.type & QTDIR)	/* this is the real test of a new directory */
		q |= DMDIR;
	PBIT32(p, q);
	p += BIT32SZ;
	PBIT32(p, d->qid.vers);
	p += BIT32SZ;
	PBIT32(p, d->mode);
	p += BIT32SZ;
	PBIT32(p, d->atime);
	p += BIT32SZ;
	PBIT32(p, d->mtime);
	p += BIT32SZ;
	PBIT64(p, d->length);
	p += BIT64SZ;
	PBIT16(p, d->type);
	p += BIT16SZ;
	PBIT16(p, d->dev);
}

long
sys_stat(ulong *arg)
{
	Chan *c;
	uint l;
	uchar buf[128];	/* old DIRLEN plus a little should be plenty */
	char strs[128];
	Dir d;
	char old[] = "old stat system call - recompile";

	validaddr(arg[1], 116, 1);
	validaddr(arg[0], 1, 0);
	c = namec((char*)arg[0], Aaccess, 0, 0);
	if(waserror()){
		cclose(c);
		nexterror();
	}
	l = devtab[c->type]->stat(c, buf, sizeof buf);
	/* buf contains a new stat buf; convert to old. yuck. */
	if(l <= BIT16SZ)	/* buffer too small; time to face reality */
		error(old);
	l = convM2D(buf, l, &d, strs);
	if(l == 0)
		error(old);
	packoldstat((uchar*)arg[1], &d);
	
	poperror();
	cclose(c);
.
913c
	l = devtab[c->type]->wstat(c, (uchar*)arg[1], l);
.
906,907c
	l = arg[2];
	validaddr(arg[1], l, 0);
	validstat((uchar*)arg[1], l);
.
904a
	uint l;
.
898c
	return l;
.
895c
	l = devtab[c->type]->wstat(c, (uchar*)arg[1], l);
.
887,888c
	l = arg[2];
	validaddr(arg[1], l, 0);
	validstat((uchar*)arg[1], l);
.
885a
	uint l;
.
865c
	c = namec((char*)arg[0], Aremove, 0, 0);
.
780c
	ret = cmount(&c0, c1, flag, bogus.spec);
.
765c
		c0 = namec((char*)arg[0], Amount, 0, 0);
.
753c
		validname(bogus.spec, 1);
.
747,748c
		validname((char*)arg[3], 1);
.
700c
	return l;
.
697c
	l = devtab[c->type]->stat(c, (uchar*)arg[1], l);
.
689,690c
	l = arg[2];
	validaddr(arg[1], l, 1);
.
687a
	uint l;
.
681c
	return l;
.
678c
	l = devtab[c->type]->stat(c, (uchar*)arg[1], l);
.
671,672c
	l = arg[2];
	validaddr(arg[1], l, 1);
.
669a
	uint l;
.
665a
void
validstat(uchar *s, int n)
{
	int m;
	char buf[64];

	if(statcheck(s, n) < 0)
		error(Ebadstat);
	/* verify that name entry is acceptable */
	s += STATFIXLEN - 4*BIT16SZ;	/* location of first string */
	/*
	 * s now points at count for first string.
	 * if it's too long, let the server decide; this is
	 * only for his protection anyway. otherwise
	 * we'd have to allocate and waserror.
	 */
	m = GBIT16(s);
	s += BIT16SZ;
	if(m+1 > sizeof buf)
		return;
	memmove(buf, s, m);
	buf[m] = '\0';
	/* name could be '/' */
	if(strcmp(buf, "/") != 0)
		validname(buf, 0);
}

.
631a

	default:
		error(Ebadarg);
.
627,628c
		if(c->qid.type & QTDIR)
			error(Eisdir);
		n = devtab[c->type]->stat(c, buf, sizeof buf);
		if(convM2D(buf, n, &dir, nil) == 0)
			error("internal error: stat error in seek");
.
619a
		if(c->qid.type & QTDIR)
			error(Eisdir);
.
615a
		if((c->qid.type & QTDIR) && off != 0)
			error(Eisdir);
.
604,606d
592a
	int n;
.
591c
	uchar buf[sizeof(Dir)+100];
.
576,584c
	return write(arg, &o.v);
.
571,574d
566,568d
563,564c
	if(arg[3]==~0UL && arg[4]==~0UL)
		return write(arg, nil);
.
556,557d
553a
sys_write(ulong *arg)
{
	return write(arg, nil);
}

long
.
534,541c
	if(offp == nil && m < n){
.
531,532c
	m = devtab[c->type]->write(c, (void*)arg[1], n, off);
.
528,529c
	}else
		off = *offp;
.
526c
		off = c->offset;
		c->offset += n;
.
522,524c

	if(offp == nil){	/* use and maintain channel's offset */
.
499,520d
496c
	if(c->qid.type & QTDIR)
.
491a
		if(offp == nil){
			lock(c);
			c->offset -= n;
			unlock(c);
		}
.
489a
	n = 0;
.
487c
	long m, n;
	uvlong off;
.
483,484c
static long
write(ulong *arg, uvlong *offp)
.
467,480c
	return read(arg, &o.v);
.
461,463d
458,459c
	if(arg[3]==~0UL && arg[4]==~0UL)
		return read(arg, nil);
.
451,452d
412,445c
	return read(arg, nil);
.
410c
sys_read(ulong *arg)
.
399,401c
	if(offp == nil){
		lock(c);
		c->offset += n;
		unlock(c);
	}
.
397c
		n = devtab[c->type]->read(c, (void*)arg[1], n, off);
.
394,395d
392c
	if(dir && c->umh)
.
386,390c
	if(offp == nil)	/* use and maintain channel's offset */
		off = c->offset;
	else
		off = *offp;
.
383,384c
	dir = c->qid.type&QTDIR;
	/*
	 * The offset is passed through on directories, normally. sysseek complains but
	 * pread is used by servers and e.g. exportfs that shouldn't need to worry about this issue.
	 */
.
377a

.
376c
	n = arg[2];
	validaddr(arg[1], n, 1);
.
374a
	uvlong off;
.
369,370c
static long
read(ulong *arg, uvlong *offp)
.
366c
	qunlock(&c->umqlock);
	return nr;
.
361,363d
359a
		if(c->umc) {
			cclose(c->umc);
			c->umc = nil;
		}
.
358d
345,356d
343a
		if(nr > 0)
			break;
.
340,342c
		if(mount->to && !waserror()) {
			if(c->umc == nil){
				c->umc = cclone(mount->to);
				c->umc = devtab[c->umc->type]->open(c->umc, OREAD);
			}
	
			nr = devtab[c->umc->type]->read(c->umc, va, n, c->umc->offset);
			c->umc->offset += nr;
			poperror();
.
330,338d
328a
	nr = 0;
.
325a
	/* bring mount in sync with c->uri and c->umc */
.
323c
	qlock(&c->umqlock);
	m = c->umh;
.
319d
201c
	if(walk(&c[1], datastr+1, 1, 1) < 0)
.
198,199c
	c[1] = cclone(c[0]);
	if(walk(&c[0], datastr+0, 1, 1) < 0)
.
182a
	static char *datastr[] = {"data", "data1"};
.
## diffname port/sysfile.c 2001/0528
## diff -e /n/emeliedump/2001/0527/sys/src/9/port/sysfile.c /n/emeliedump/2001/0528/sys/src/9/port/sysfile.c
459a

	if(off < 0)
		error(Enegoff);
.
433c
	vlong off;
.
387a
	if(off < 0)
		error(Enegoff);

.
366c
	vlong off;
.
## diffname port/sysfile.c 2001/0727
## diff -e /n/emeliedump/2001/0528/sys/src/9/port/sysfile.c /n/emeliedump/2001/0727/sys/src/9/port/sysfile.c
498,501c
	return write(arg, &v);
.
495c
	va_start(list, arg[2]);
	v = va_arg(list, uvlong);
	va_end(list);

	if(v ==~0ULL)
.
490,493c
	uvlong v;
	va_list list;
.
425,428c
	return read(arg, &v);
.
422c
	va_start(list, arg[2]);
	v = va_arg(list, uvlong);
	va_end(list);

	if(v ==~0ULL)
.
417,420c
	uvlong v;
	va_list list;
.
## diffname port/sysfile.c 2001/0728
## diff -e /n/emeliedump/2001/0727/sys/src/9/port/sysfile.c /n/emeliedump/2001/0728/sys/src/9/port/sysfile.c
491a
	/* use varargs to guarantee alignment of vlong */
.
419a
	/* use varargs to guarantee alignment of vlong */
.
## diffname port/sysfile.c 2001/0731
## diff -e /n/emeliedump/2001/0728/sys/src/9/port/sysfile.c /n/emeliedump/2001/0731/sys/src/9/port/sysfile.c
498c
	if(v == ~0ULL)
.
495c
	v = va_arg(list, vlong);
.
490c
	vlong v;
.
432c
write(ulong *arg, vlong *offp)
.
425c
	if(v == ~0ULL)
.
422c
	v = va_arg(list, vlong);
.
417c
	vlong v;
.
361c
read(ulong *arg, vlong *offp)
.
## diffname port/sysfile.c 2001/0819
## diff -e /n/emeliedump/2001/0731/sys/src/9/port/sysfile.c /n/emeliedump/2001/0819/sys/src/9/port/sysfile.c
753c
	return bindmount(1, arg[0], arg[1], nil, (char*)arg[2], arg[3], (char*)arg[4]);
}

long
sys_mount(ulong *arg)
{
	return bindmount(1, arg[0], -1, nil, (char*)arg[1], arg[2], (char*)arg[3]);
.
747c
	return bindmount(0, -1, -1, (char*)arg[0], (char*)arg[1], arg[2], nil);
.
740a

.
726,727c
	validaddr((ulong)arg1, 1, 0);
	c1 = namec(arg1, Amount, 0, 0);
.
717,718c
		validaddr((ulong)arg0, 1, 0);
		c0 = namec(arg0, Amount, 0, 0);
.
712a
		if(ac)
			cclose(ac);
.
706d
703c
		bogus.spec = spec;
.
700,701c
		validaddr((ulong)spec, 1, 0);
		validname(spec, 1);
.
698a
		bogus.authchan = ac;
.
697a

		if(afd >= 0)
			ac = fdtochan(afd, ORDWR, 0, 1);

.
694a
			if(ac)
				cclose(ac);
.
692a
		ac = nil;
.
682,683d
677a
		Chan	*authchan;
.
673,675c
	int ret;
	Chan *c0, *c1, *ac, *bc;
.
671c
bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec)
.
273a
if(strstr(up->text, "syscall")!=0) pprint("open %s ref count %d\n", c2name(c), c->ref); // BUG
.
## diffname port/sysfile.c 2001/0820
## diff -e /n/emeliedump/2001/0819/sys/src/9/port/sysfile.c /n/emeliedump/2001/0820/sys/src/9/port/sysfile.c
274d
## diffname port/sysfile.c 2001/0822
## diff -e /n/emeliedump/2001/0820/sys/src/9/port/sysfile.c /n/emeliedump/2001/0822/sys/src/9/port/sysfile.c
786c
		cmounted = namec((char*)arg[0], Aaccess, OREAD, 0);
.
559a
	c->dri = 0;
.
## diffname port/sysfile.c 2001/0912
## diff -e /n/emeliedump/2001/0822/sys/src/9/port/sysfile.c /n/emeliedump/2001/0912/sys/src/9/port/sysfile.c
787c
		/*
		 * This has to be namec(..., Aopen, ...) because
		 * if arg[0] is something like /srv/cs or /fd/0,
		 * opening it is the only way to get at the real
		 * Chan underneath.
		 */
		cmounted = namec((char*)arg[0], Aopen, OREAD, 0);
.
## diffname port/sysfile.c 2001/0919
## diff -e /n/emeliedump/2001/0912/sys/src/9/port/sysfile.c /n/emeliedump/2001/0919/sys/src/9/port/sysfile.c
726c
		c0 = namec(arg0, Abind, 0, 0);
.
722,723c
	}else{
.
## diffname port/sysfile.c 2001/1111
## diff -e /n/emeliedump/2001/0919/sys/src/9/port/sysfile.c /n/emeliedump/2001/1111/sys/src/9/port/sysfile.c
551a
		if(off < 0)
			error(Enegoff);
.
540a
		if(off < 0)
			error(Enegoff);
.
532a
		if(off < 0)
			error(Enegoff);
.
## diffname port/sysfile.c 2001/1118
## diff -e /n/emeliedump/2001/1111/sys/src/9/port/sysfile.c /n/emeliedump/2001/1118/sys/src/9/port/sysfile.c
823c
	openmode(arg[1]&~OEXCL);	/* error check only; OEXCL okay here */
.
## diffname port/sysfile.c 2001/1212
## diff -e /n/emeliedump/2001/1118/sys/src/9/port/sysfile.c /n/emeliedump/2001/1212/sys/src/9/port/sysfile.c
689c
	if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER))
.
## diffname port/sysfile.c 2001/1230
## diff -e /n/emeliedump/2001/1212/sys/src/9/port/sysfile.c /n/emeliedump/2001/1230/sys/src/9/port/sysfile.c
718a
		validname(spec, 1);
.
714,715d
## diffname port/sysfile.c 2002/0104
## diff -e /n/emeliedump/2001/1230/sys/src/9/port/sysfile.c /n/emeliedump/2002/0104/sys/src/9/port/sysfile.c
202c
	if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
.
200c
	if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
.
## diffname port/sysfile.c 2003/0326
## diff -e /n/emeliedump/2002/0104/sys/src/9/port/sysfile.c /n/emeliedump/2003/0326/sys/src/9/port/sysfile.c
239c
		unlockfgrp(f);
.
230c
			unlockfgrp(f);
.
102c
	unlockfgrp(f);
.
95c
		unlockfgrp(f);
.
90c
		unlockfgrp(f);
.
77c
	unlockfgrp(f);
.
71c
		unlockfgrp(f);
.
41a
	}
.
40c
	if(fd > f->maxfd){
		if(fd/100 > f->maxfd/100)
			f->exceed = (fd/100)*100;
.
21,22d
11a
static void
unlockfgrp(Fgrp *f)
{
	int ex;

	ex = f->exceed;
	f->exceed = 0;
	unlock(f);
	if(ex)
		pprint("warning: process exceeds %d file descriptors\n", ex);
}

.
## diffname port/sysfile.c 2003/0509
## diff -e /n/emeliedump/2003/0326/sys/src/9/port/sysfile.c /n/emeliedump/2003/0509/sys/src/9/port/sysfile.c
998a
	name = cnamelast(c->name);
	if(name)
		l = dirsetname(name, strlen(name), (uchar*)arg[1], l, arg[2]);
.
982a
	char *name;
.
904,911c
	return wstat(c, (uchar*)arg[1], l);
.
884,891c
	return wstat(c, (uchar*)arg[1], l);
.
872a
static long
wstat(Chan *c, uchar *d, int nd)
{
	long l;
	int namelen;

	if(waserror()){
		cclose(c);
		nexterror();
	}
	if(c->ismtpt){
		/*
		 * Renaming mount points is disallowed to avoid surprises
		 * (which should be renamed: the mount point or the mounted Chan?).
		 */
		dirname(d, &namelen);
		if(namelen)
			nameerror(channame(c), Eismtpt);
	}
	l = devtab[c->type]->wstat(c, d, nd);
	poperror();
	cclose(c);
	return l;
}

.
861a
	/*
	 * Removing mount points is disallowed to avoid surprises
	 * (which should be removed: the mount point or the mounted Chan?).
	 */
	if(c->ismtpt)
		error(Eismtpt);
.
671a
	name = cnamelast(c->name);
	if(name)
		l = dirsetname(name, strlen(name), (uchar*)arg[1], l, arg[2]);

.
659a
	char *name;
.
637a
static char*
cnamelast(Cname *n)
{
	char *s;

	if(n == nil)
		return nil;
	if(n->len == 0)
		return nil;
	s = strrchr(n->s, '/');
	if(s)
		return s+1;
	return n->s;
}

.
418c
	return nnn;
.
414a
	lock(c);
	c->devoffset += nn;
	c->offset += nnn;
	unlock(c);

.
413a
	if(dir)
		nnn = mountfix(c, p, nn, n);
	else
		nnn = nn;
.
409,412c
	dir = c->qid.type&QTDIR;
	if(dir && mountrockread(c, p, n, &nn)){
		/* do nothing: mountrockread filled buffer */
	}else{
		if(dir && c->umh)
			nn = unionread(c, p, n);
		else
			nn = devtab[c->type]->read(c, p, n, off);
.
404,407c
	if(off == 0){	/* rewind to the beginning of the directory */
		if(offp == nil){
			c->offset = 0;
			c->devoffset = 0;
		}
		mountrewind(c);
		unionrewind(c);
	}
.
400d
395d
392,393c
	 * The offset is passed through on directories, normally.
	 * Sysseek complains, but pread is used by servers like exportfs,
	 * that shouldn't need to worry about this issue.
	 *
	 * Notice that c->devoffset is the offset that c's dev is seeing.
	 * The number of bytes read on this fd (c->offset) may be different
	 * due to rewritings in rockfix.
.
390d
385c
	if(waserror()){
.
382a
	p = (void*)arg[1];
.
377c
	long n, nn, nnn;
	uchar *p;
.
373a
dirsetname(char *name, int len, uchar *p, long n, long maxn)
{
	char *oname;
	int olen;
	long nn;

	if(n == BIT16SZ)
		return BIT16SZ;

	oname = dirname(p, &olen);

	nn = n+len-olen;
	PBIT16(p, nn-BIT16SZ);
	if(nn > maxn)
		return BIT16SZ;

	if(len != olen)
		memmove(oname+len, oname+olen, p+n-(uchar*)(oname+olen));
	PBIT16((uchar*)(oname-2), len);
	memmove(oname, name, len);
	return nn;
}

/*
 * Mountfix might have caused the fixed results of the directory read
 * to overflow the buffer.  Catch the overflow in c->dirrock.
 */
static void
mountrock(Chan *c, uchar *p, uchar **pe)
{
	uchar *e, *r;
	int len, n;

	e = *pe;

	/* find last directory entry */
	for(;;){
		len = BIT16SZ+GBIT16(p);
		if(p+len >= e)
			break;
		p += len;
	}

	/* save it away */
	qlock(&c->rockqlock);
	if(c->nrock+len > c->mrock){
		n = ROUND(c->nrock+len, 1024);
		r = smalloc(n);
		memmove(r, c->dirrock, c->nrock);
		free(c->dirrock);
		c->dirrock = r;
		c->mrock = n;
	}
	memmove(c->dirrock+c->nrock, p, len);
	c->nrock += len;
	qunlock(&c->rockqlock);

	/* drop it */
	*pe = p;
}

/*
 * Satisfy a directory read with the results saved in c->dirrock.
 */
static int
mountrockread(Chan *c, uchar *op, long n, long *nn)
{
	long dirlen;
	uchar *rp, *erp, *ep, *p;

	/* common case */
	if(c->nrock == 0)
		return 0;

	/* copy out what we can */
	qlock(&c->rockqlock);
	rp = c->dirrock;
	erp = rp+c->nrock;
	p = op;
	ep = p+n;
	while(rp+BIT16SZ <= erp){
		dirlen = BIT16SZ+GBIT16(rp);
		if(p+dirlen > ep)
			break;
		memmove(p, rp, dirlen);
		p += dirlen;
		rp += dirlen;
	}

	if(p == op){
		qunlock(&c->rockqlock);
		return 0;
	}

	/* shift the rest */
	if(rp != erp)
		memmove(c->dirrock, rp, erp-rp);
	c->nrock = erp - rp;

	*nn = p - op;
	qunlock(&c->rockqlock);
	return 1;
}

static void
mountrewind(Chan *c)
{
	c->nrock = 0;
}

/*
 * Rewrite the results of a directory read to reflect current 
 * name space bindings and mounts.  Specifically, replace
 * directory entries for bind and mount points with the results
 * of statting what is mounted there.  Except leave the old names.
 */
static long
mountfix(Chan *c, uchar *op, long n, long maxn)
{
	char *name;
	int nbuf, nname;
	Chan *nc;
	Mhead *mh;
	Mount *m;
	uchar *p;
	int dirlen, rest;
	long l;
	Qid q;
	uchar *buf, *e;

	p = op;
	buf = nil;
	nbuf = 0;
	for(e=&p[n]; p+BIT16SZ<e; p+=dirlen){
		dirlen = BIT16SZ+GBIT16(p);
		if(p+dirlen > e)
			break;
		dirqid(p, &q);
		nc = nil;
		mh = nil;
		if(findmount(&nc, &mh, c->type, c->dev, q)){
			/*
			 * If it's a union directory and the original is
			 * in the union, don't rewrite anything.
			 */
			for(m=mh->mount; m; m=m->next)
				if(eqchantdqid(m->to, c->type, c->dev, q, 1))
					goto Norewrite;

			name = dirname(p, &nname);
		//	print("mnted %.*s\n", utfnlen(name, nname), name);
			/*
			 * Do the stat but fix the name.  If it fails, leave old entry.
			 * BUG: If it fails because there isn't room for the entry,
			 * what can we do?  Nothing, really.  Might as well skip it.
			 */
			if(buf == nil){
				buf = smalloc(4096);
				nbuf = 4096;
			}
			if(waserror())
				goto Norewrite;
			l = devtab[nc->type]->stat(nc, buf, nbuf);
			l = dirsetname(name, nname, buf, l, nbuf);
			if(l == BIT16SZ)
				goto Norewrite;
			poperror();

			/*
			 * Shift data in buffer to accomodate new entry,
			 * possibly overflowing into rock.
			 */
			rest = e - (p+dirlen);
			if(l > dirlen){
				while(p+l+rest > op+maxn){
					mountrock(c, p, &e);
					if(e == p){
						dirlen = 0;
						goto Norewrite;
					}
					rest = e - (p+dirlen);
				}
			}
			if(l != dirlen){
				memmove(p+l, p+dirlen, rest);
				dirlen = l;
				e = p+dirlen+rest;
			}

			/*
			 * Rewrite directory entry.
			 */
			memmove(p, buf, l);

		    Norewrite:
			cclose(nc);
			putmhead(mh);
		}
	}
	if(buf)
		free(buf);

	if(p != e)
		error("oops in rockfix");

	return e-op;
}

static long
.
372a
static void
unionrewind(Chan *c)
{
	qlock(&c->umqlock);
	c->uri = 0;
	if(c->umc){
		cclose(c->umc);
		c->umc = nil;
	}
	qunlock(&c->umqlock);
}

static void
dirqid(uchar *p, Qid *q)
{
	p += BIT16SZ+BIT16SZ+BIT32SZ;
	q->type = GBIT8(p);
	p += BIT8SZ;
	q->vers = GBIT32(p);
	p += BIT32SZ;
	q->path = GBIT64(p);
}

static char*
dirname(uchar *p, int *n)
{
	p += BIT16SZ+BIT16SZ+BIT32SZ+BIT8SZ+BIT32SZ+BIT64SZ
		+ BIT32SZ+BIT32SZ+BIT32SZ+BIT64SZ;
	*n = GBIT16(p);
	return (char*)p+BIT16SZ;
}

.
362c
		if(c->umc){
.
347c
		if(mount->to && !waserror()){
.
345c
	while(mount != nil){
.
## diffname port/sysfile.c 2003/0510
## diff -e /n/emeliedump/2003/0509/sys/src/9/port/sysfile.c /n/emeliedump/2003/0510/sys/src/9/port/sysfile.c
1301c
		l = dirsetname(name, strlen(name), buf, l, sizeof buf);
.
1267a
	name = cnamelast(c->name);
	if(name)
		l = dirsetname(name, strlen(name), buf, l, sizeof buf);
.
1253c
	char strs[128], *name;
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].