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

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


## diffname gnot/sysfile.c 1990/03091
## diff -e /dev/null /n/bootesdump/1990/03091/sys/src/9/68020/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 gnot/sysfile.c 1990/03291
## diff -e /n/bootesdump/1990/03091/sys/src/9/68020/sysfile.c /n/bootesdump/1990/03291/sys/src/9/68020/sysfile.c
409,412d
## diffname gnot/sysfile.c 1990/03292
## diff -e /n/bootesdump/1990/03291/sys/src/9/68020/sysfile.c /n/bootesdump/1990/03292/sys/src/9/68020/sysfile.c
129c
		pprint("unionread: changed underfoot?\n");
.
## diffname gnot/sysfile.c 1990/0703
## diff -e /n/bootesdump/1990/03292/sys/src/9/68020/sysfile.c /n/bootesdump/1990/0703/sys/src/9/68020/sysfile.c
459a
		c->type = 0;	/* see below */
.
## diffname gnot/sysfile.c 1990/08141
## diff -e /n/bootesdump/1990/0703/sys/src/9/68020/sysfile.c /n/bootesdump/1990/08141/sys/src/9/68020/sysfile.c
50c
	o &= ~(OTRUNC|OCEXEC|ORCLOSE);
.
47c
	if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC))
.
## diffname gnot/sysfile.c 1990/0821
## diff -e /n/bootesdump/1990/08141/sys/src/9/68020/sysfile.c /n/bootesdump/1990/0821/sys/src/9/68020/sysfile.c
195c
	if((c->qid&CHDIR) && (c->flag&CMOUNT))
.
150a
	c->offset = nc->offset;		/* devdirread e.g. changes it */
.
## diffname gnot/sysfile.c 1990/0822
## diff -e /n/bootesdump/1990/0821/sys/src/9/68020/sysfile.c /n/bootesdump/1990/0822/sys/src/9/68020/sysfile.c
302,306c
	postnote(u->p, 1, "access is deprecated", NDebug);
.
## diffname gnot/sysfile.c 1990/0918
## diff -e /n/bootesdump/1990/0822/sys/src/9/68020/sysfile.c /n/bootesdump/1990/0918/sys/src/9/68020/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 gnot/sysfile.c 1990/0928
## diff -e /n/bootesdump/1990/0918/sys/src/9/68020/sysfile.c /n/bootesdump/1990/0928/sys/src/9/68020/sysfile.c
39c
	if((mode&~OTRUNC) != c->mode)
.
36c
	if((mode&OTRUNC) && c->mode==OREAD)
.
34c
	if(mode<0 || c->mode==ORDWR)
.
## diffname gnot/sysfile.c 1990/1009
## diff -e /n/bootesdump/1990/0928/sys/src/9/68020/sysfile.c /n/bootesdump/1990/1009/sys/src/9/68020/sysfile.c
383,419d
211c
	c = fdtochan(arg[0], OWRITE);
.
183,184c
	c = fdtochan(arg[0], OREAD);
	validaddr(arg[1], arg[2], 1);
.
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
.
## diffname gnot/sysfile.c 1990/1104
## diff -e /n/bootesdump/1990/1009/sys/src/9/68020/sysfile.c /n/bootesdump/1990/1104/sys/src/9/68020/sysfile.c
510a

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

	c = fdtochan(arg[0], -1);
	validaddr(arg[1], 1, 0);
	if((c->qid&CHDIR) || (c->mode&ORDWR)!=ORDWR)
		error(0, Ebadarg);
	service((char *)arg[1], c, filsys);
	return 0;
}
.
## diffname gnot/sysfile.c 1990/1106
## diff -e /n/bootesdump/1990/1104/sys/src/9/68020/sysfile.c /n/bootesdump/1990/1106/sys/src/9/68020/sysfile.c
521c
	service((char *)arg[2], cin, cout, filsys);
.
517,519c
	cin = fdtochan(arg[0], OREAD);
	cout = fdtochan(arg[1], OWRITE);
	validaddr(arg[2], 1, 0);
	if((cin->qid&CHDIR) || (cout->qid&CHDIR))
.
515c
	Chan *cin, *cout;
.
## diffname gnot/sysfile.c 1990/11211
## diff -e /n/bootesdump/1990/1106/sys/src/9/68020/sysfile.c /n/bootesdump/1990/11211/sys/src/9/68020/sysfile.c
524a
#endif
.
520,521c
	if((cin->qid.path&CHDIR) || (cout->qid.path&CHDIR))
		error(Ebadarg);
.
511a
#ifdef asdf
.
439,457d
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 gnot/sysfile.c 1990/1126
## diff -e /n/bootesdump/1990/11211/sys/src/9/68020/sysfile.c /n/bootesdump/1990/1126/sys/src/9/68020/sysfile.c
332,341d
31a
	c = 0;		/* set */
.
## diffname gnot/sysfile.c 1990/1210 # deleted
## diff -e /n/bootesdump/1990/1126/sys/src/9/68020/sysfile.c /n/bootesdump/1990/1210/sys/src/9/68020/sysfile.c
1,508d

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].