## 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
|