diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/unix/drawterm/kern/unused/syscall.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/unix/drawterm/kern/unused/syscall.c')
-rwxr-xr-x | sys/src/cmd/unix/drawterm/kern/unused/syscall.c | 837 |
1 files changed, 837 insertions, 0 deletions
diff --git a/sys/src/cmd/unix/drawterm/kern/unused/syscall.c b/sys/src/cmd/unix/drawterm/kern/unused/syscall.c new file mode 100755 index 000000000..1ae9a7cb2 --- /dev/null +++ b/sys/src/cmd/unix/drawterm/kern/unused/syscall.c @@ -0,0 +1,837 @@ +#include "u.h" +#include "lib.h" +#include "dat.h" +#include "fns.h" +#include "error.h" + +Chan* +fdtochan(int fd, int mode, int chkmnt, int iref) +{ + Fgrp *f; + Chan *c; + + c = 0; + f = up->fgrp; + + lock(&f->ref.lk); + if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) { + unlock(&f->ref.lk); + error(Ebadfd); + } + if(iref) + refinc(&c->ref); + unlock(&f->ref.lk); + + if(chkmnt && (c->flag&CMSG)) + goto bad; + if(mode<0 || c->mode==ORDWR) + return c; + if((mode&OTRUNC) && c->mode==OREAD) + goto bad; + if((mode&~OTRUNC) != c->mode) + goto bad; + return c; +bad: + if(iref) + cclose(c); + error(Ebadusefd); + return nil; /* shut up compiler */ +} + +static void +fdclose(int fd, int flag) +{ + int i; + Chan *c; + Fgrp *f; + + f = up->fgrp; + + lock(&f->ref.lk); + c = f->fd[fd]; + if(c == 0) { + unlock(&f->ref.lk); + return; + } + if(flag) { + if(c==0 || !(c->flag&flag)) { + unlock(&f->ref.lk); + return; + } + } + f->fd[fd] = 0; + if(fd == f->maxfd) + for(i=fd; --i>=0 && f->fd[i]==0; ) + f->maxfd = i; + + unlock(&f->ref.lk); + cclose(c); +} + +static int +newfd(Chan *c) +{ + int i; + Fgrp *f; + + f = up->fgrp; + lock(&f->ref.lk); + for(i=0; i<NFD; i++) + if(f->fd[i] == 0){ + if(i > f->maxfd) + f->maxfd = i; + f->fd[i] = c; + unlock(&f->ref.lk); + return i; + } + unlock(&f->ref.lk); + error("no file descriptors"); + return 0; +} + +int +sysclose(int fd) +{ + if(waserror()) + return -1; + + fdtochan(fd, -1, 0, 0); + fdclose(fd, 0); + poperror(); + return 0; +} + +int +syscreate(char *path, int mode, ulong perm) +{ + int fd; + Chan *c = 0; + + if(waserror()) { + cclose(c); + return -1; + } + + openmode(mode); /* error check only */ + c = namec(path, Acreate, mode, perm); + fd = newfd((Chan*)c); + poperror(); + return fd; +} + +int +sysdup(int old, int new) +{ + Chan *oc; + Fgrp *f = up->fgrp; + Chan *c = 0; + + if(waserror()) + return -1; + + c = fdtochan(old, -1, 0, 1); + if(new != -1) { + if(new < 0 || NFD <= new) { + cclose(c); + error(Ebadfd); + } + lock(&f->ref.lk); + if(new > f->maxfd) + f->maxfd = new; + oc = f->fd[new]; + f->fd[new] = (Chan*)c; + unlock(&f->ref.lk); + if(oc != 0) + cclose(oc); + } + else { + if(waserror()) { + cclose(c); + nexterror(); + } + new = newfd((Chan*)c); + poperror(); + } + poperror(); + return new; +} + +int +sysfstat(int fd, char *buf) +{ + Chan *c = 0; + + if(waserror()) { + cclose(c); + return -1; + } + c = fdtochan(fd, -1, 0, 1); + devtab[c->type]->stat((Chan*)c, buf); + poperror(); + cclose(c); + return 0; +} + +int +sysfwstat(int fd, char *buf) +{ + Chan *c = 0; + + if(waserror()) { + cclose(c); + return -1; + } + nameok(buf); + c = fdtochan(fd, -1, 1, 1); + devtab[c->type]->wstat((Chan*)c, buf); + poperror(); + cclose(c); + return 0; +} + +int +syschdir(char *dir) +{ + return 0; +} + +long +bindmount(Chan *c0, char *old, int flag, char *spec) +{ + int ret; + Chan *c1 = 0; + + if(flag>MMASK || (flag&MORDER) == (MBEFORE|MAFTER)) + error(Ebadarg); + + c1 = namec(old, Amount, 0, 0); + if(waserror()){ + cclose(c1); + nexterror(); + } + + ret = cmount(c0, c1, flag, spec); + + poperror(); + cclose(c1); + return ret; +} + +int +sysbind(char *new, char *old, int flags) +{ + long r; + Chan *c0 = 0; + + if(waserror()) { + cclose(c0); + return -1; + } + c0 = namec(new, Aaccess, 0, 0); + r = bindmount(c0, old, flags, ""); + poperror(); + cclose(c0); + return 0; +} + +int +sysmount(int fd, char *old, int flags, char *spec) +{ + long r; + Chan *c0 = 0, *bc = 0; + struct { + Chan* chan; + char* spec; + int flags; + } mntparam; + + if(waserror()) { + cclose(bc); + cclose(c0); + return -1; + } + bc = fdtochan(fd, ORDWR, 0, 1); + mntparam.chan = (Chan*)bc; + mntparam.spec = spec; + mntparam.flags = flags; + c0 = (*devtab[devno('M', 0)].attach)(&mntparam); + cclose(bc); + r = bindmount(c0, old, flags, spec); + poperror(); + cclose(c0); + + return r; +} + +int +sysunmount(char *old, char *new) +{ + Chan *cmount = 0, *cmounted = 0; + + if(waserror()) { + cclose(cmount); + cclose(cmounted); + return -1; + } + + cmount = namec(new, Amount, OREAD, 0); + if(old != 0) + cmounted = namec(old, Aopen, OREAD, 0); + + cunmount(cmount, cmounted); + poperror(); + cclose(cmount); + cclose(cmounted); + return 0; +} + +int +sysopen(char *path, int mode) +{ + int fd; + Chan *c = 0; + + if(waserror()){ + cclose(c); + return -1; + } + openmode(mode); /* error check only */ + c = namec(path, Aopen, mode, 0); + fd = newfd((Chan*)c); + poperror(); + return fd; +} + +long +unionread(Chan *c, void *va, long n) +{ + long nr; + Chan *nc = 0; + Pgrp *pg = 0; + + pg = up->pgrp; + rlock(&pg->ns); + + for(;;) { + if(waserror()) { + runlock(&pg->ns); + nexterror(); + } + nc = clone(c->mnt->to, 0); + poperror(); + + if(c->mountid != c->mnt->mountid) { + runlock(&pg->ns); + cclose(nc); + return 0; + } + + /* Error causes component of union to be skipped */ + if(waserror()) { + cclose(nc); + goto next; + } + + nc = (*devtab[nc->type].open)((Chan*)nc, OREAD); + nc->offset = c->offset; + nr = (*devtab[nc->type].read)((Chan*)nc, va, n, nc->offset); + /* devdirread e.g. changes it */ + c->offset = nc->offset; + poperror(); + + cclose(nc); + if(nr > 0) { + runlock(&pg->ns); + return nr; + } + /* Advance to next element */ + next: + c->mnt = c->mnt->next; + if(c->mnt == 0) + break; + c->mountid = c->mnt->mountid; + c->offset = 0; + } + runlock(&pg->ns); + return 0; +} + +long +sysread(int fd, void *va, long n) +{ + int dir; + Lock *cl; + Chan *c = 0; + + if(waserror()) { + cclose(c); + return -1; + } + c = fdtochan(fd, OREAD, 1, 1); + + dir = c->qid.path&CHDIR; + if(dir) { + n -= n%DIRLEN; + if(c->offset%DIRLEN || n==0) + error(Etoosmall); + } + + if(dir && c->mnt) + n = unionread((Chan*)c, va, n); + else + n = (*devtab[c->type].read)((Chan*)c, va, n, c->offset); + + cl = (Lock*)&c->r.l; + lock(cl); + c->offset += n; + unlock(cl); + + poperror(); + cclose(c); + + return n; +} + +int +sysremove(char *path) +{ + Chan *c = 0; + + if(waserror()) { + if(c != 0) + c->type = 0; /* see below */ + cclose(c); + return -1; + } + c = namec(path, Aaccess, 0, 0); + (*devtab[c->type].remove)((Chan*)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; + poperror(); + cclose(c); + return 0; +} + +long +sysseek(int fd, long off, int whence) +{ + Dir dir; + Chan *c; + char buf[DIRLEN]; + + if(waserror()) + return -1; + + c = fdtochan(fd, -1, 1, 0); + if(c->qid.path & CHDIR) + error(Eisdir); + + switch(whence) { + case 0: + c->offset = off; + break; + + case 1: + lock(&c->r.l); /* lock for read/write update */ + c->offset += off; + off = c->offset; + unlock(&c->r.l); + break; + + case 2: + (*devtab[c->type].stat)(c, buf); + convM2D(buf, &dir); + c->offset = dir.length + off; + off = c->offset; + break; + } + poperror(); + return off; +} + +int +sysstat(char *path, char *buf) +{ + Chan *c = 0; + + if(waserror()){ + cclose(c); + return -1; + } + c = namec(path, Aaccess, 0, 0); + (*devtab[c->type].stat)((Chan*)c, buf); + poperror(); + cclose(c); + return 0; +} + +long +syswrite(int fd, void *va, long n) +{ + Lock *cl; + Chan *c = 0; + + if(waserror()) { + cclose(c); + return -1; + } + c = fdtochan(fd, OWRITE, 1, 1); + if(c->qid.path & CHDIR) + error(Eisdir); + + n = (*devtab[c->type].write)((Chan*)c, va, n, c->offset); + + cl = (Lock*)&c->r.l; + lock(cl); + c->offset += n; + unlock(cl); + + poperror(); + cclose(c); + + return n; +} + +int +syswstat(char *path, char *buf) +{ + Chan *c = 0; + + if(waserror()) { + cclose(c); + return -1; + } + + nameok(buf); + c = namec(path, Aaccess, 0, 0); + (*devtab[c->type].wstat)((Chan*)c, buf); + poperror(); + cclose(c); + return 0; +} + +int +sysdirstat(char *name, Dir *dir) +{ + char buf[DIRLEN]; + + if(sysstat(name, buf) == -1) + return -1; + convM2D(buf, dir); + return 0; +} + +int +sysdirfstat(int fd, Dir *dir) +{ + char buf[DIRLEN]; + + if(sysfstat(fd, buf) == -1) + return -1; + + convM2D(buf, dir); + return 0; +} + +int +sysdirwstat(char *name, Dir *dir) +{ + char buf[DIRLEN]; + + convD2M(dir, buf); + return syswstat(name, buf); +} + +int +sysdirfwstat(int fd, Dir *dir) +{ + char buf[DIRLEN]; + + convD2M(dir, buf); + return sysfwstat(fd, buf); +} + +long +sysdirread(int fd, Dir *dbuf, long count) +{ + int c, n, i, r; + char buf[DIRLEN*50]; + + n = 0; + count = (count/sizeof(Dir)) * DIRLEN; + while(n < count) { + c = count - n; + if(c > sizeof(buf)) + c = sizeof(buf); + r = sysread(fd, buf, c); + if(r == 0) + break; + if(r < 0 || r % DIRLEN) + return -1; + for(i=0; i<r; i+=DIRLEN) { + convM2D(buf+i, dbuf); + dbuf++; + } + n += r; + if(r != c) + break; + } + + return (n/DIRLEN) * sizeof(Dir); +} + +static int +call(char *clone, char *dest, int *cfdp, char *dir, char *local) +{ + int fd, cfd, n; + char *p, name[3*NAMELEN+5], data[3*NAMELEN+10]; + + cfd = sysopen(clone, ORDWR); + if(cfd < 0){ + werrstr("%s: %r", clone); + return -1; + } + + /* get directory name */ + n = sysread(cfd, name, sizeof(name)-1); + if(n < 0) { + sysclose(cfd); + return -1; + } + name[n] = 0; + sprint(name, "%d", strtoul(name, 0, 0)); + p = strrchr(clone, '/'); + *p = 0; + if(dir) + snprint(dir, 2*NAMELEN, "%s/%s", clone, name); + snprint(data, sizeof(data), "%s/%s/data", clone, name); + + /* connect */ + /* set local side (port number, for example) if we need to */ + if(local) + snprint(name, sizeof(name), "connect %s %s", dest, local); + else + snprint(name, sizeof(name), "connect %s", dest); + if(syswrite(cfd, name, strlen(name)) < 0){ + werrstr("%s failed: %r", name); + sysclose(cfd); + return -1; + } + + /* open data connection */ + fd = sysopen(data, ORDWR); + if(fd < 0){ + werrstr("can't open %s: %r", data); + sysclose(cfd); + return -1; + } + if(cfdp) + *cfdp = cfd; + else + sysclose(cfd); + return fd; +} + +int +sysdial(char *dest, char *local, char *dir, int *cfdp) +{ + int n, fd, rv; + char *p, net[128], clone[NAMELEN+12]; + + /* go for a standard form net!... */ + p = strchr(dest, '!'); + if(p == 0){ + snprint(net, sizeof(net), "net!%s", dest); + } else { + strncpy(net, dest, sizeof(net)-1); + net[sizeof(net)-1] = 0; + } + + /* call the connection server */ + fd = sysopen("/net/cs", ORDWR); + if(fd < 0){ + /* no connection server, don't translate */ + p = strchr(net, '!'); + *p++ = 0; + snprint(clone, sizeof(clone), "/net/%s/clone", net); + return call(clone, p, cfdp, dir, local); + } + + /* + * send dest to connection to translate + */ + if(syswrite(fd, net, strlen(net)) < 0){ + werrstr("%s: %r", net); + sysclose(fd); + return -1; + } + + /* + * loop through each address from the connection server till + * we get one that works. + */ + rv = -1; + sysseek(fd, 0, 0); + while((n = sysread(fd, net, sizeof(net) - 1)) > 0){ + net[n] = 0; + p = strchr(net, ' '); + if(p == 0) + continue; + *p++ = 0; + rv = call(net, p, cfdp, dir, local); + if(rv >= 0) + break; + } + sysclose(fd); + return rv; +} + +static int +identtrans(char *addr, char *naddr, int na, char *file, int nf) +{ + char *p; + char reply[4*NAMELEN]; + + /* parse the network */ + strncpy(reply, addr, sizeof(reply)); + reply[sizeof(reply)-1] = 0; + p = strchr(reply, '!'); + if(p) + *p++ = 0; + + sprint(file, "/net/%.*s/clone", na - sizeof("/net//clone"), reply); + strncpy(naddr, p, na); + naddr[na-1] = 0; + return 1; +} + +static int +nettrans(char *addr, char *naddr, int na, char *file, int nf) +{ + long n; + int fd; + char *cp; + char reply[4*NAMELEN]; + + /* + * ask the connection server + */ + fd = sysopen("/net/cs", ORDWR); + if(fd < 0) + return identtrans(addr, naddr, na, file, nf); + if(syswrite(fd, addr, strlen(addr)) < 0){ + sysclose(fd); + return -1; + } + sysseek(fd, 0, 0); + n = sysread(fd, reply, sizeof(reply)-1); + sysclose(fd); + if(n <= 0) + return -1; + reply[n] = '\0'; + + /* + * parse the reply + */ + cp = strchr(reply, ' '); + if(cp == 0) + return -1; + *cp++ = 0; + strncpy(naddr, cp, na); + naddr[na-1] = 0; + strncpy(file, reply, nf); + file[nf-1] = 0; + return 0; +} + +int +sysannounce(char *addr, char *dir) +{ + char *cp; + int ctl, n, m; + char buf[3*NAMELEN]; + char buf2[3*NAMELEN]; + char netdir[2*NAMELEN]; + char naddr[3*NAMELEN]; + + /* + * translate the address + */ + if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0){ + werrstr("can't translate address"); + return -1; + } + + /* + * get a control channel + */ + ctl = sysopen(netdir, ORDWR); + if(ctl<0){ + werrstr("can't open control channel"); + return -1; + } + cp = strrchr(netdir, '/'); + *cp = 0; + + /* + * find out which line we have + */ + n = sprint(buf, "%.*s/", 2*NAMELEN+1, netdir); + m = sysread(ctl, &buf[n], sizeof(buf)-n-1); + if(m <= 0) { + sysclose(ctl); + werrstr("can't read control file"); + return -1; + } + buf[n+m] = 0; + + /* + * make the call + */ + n = sprint(buf2, "announce %.*s", 2*NAMELEN, naddr); + if(syswrite(ctl, buf2, n) != n) { + sysclose(ctl); + werrstr("announcement fails"); + return -1; + } + + strcpy(dir, buf); + + return ctl; +} + +int +syslisten(char *dir, char *newdir) +{ + char *cp; + int ctl, n, m; + char buf[3*NAMELEN]; + + /* + * open listen, wait for a call + */ + sprint(buf, "%.*s/listen", 2*NAMELEN+1, dir); + ctl = sysopen(buf, ORDWR); + if(ctl < 0) + return -1; + + /* + * find out which line we have + */ + strcpy(buf, dir); + cp = strrchr(buf, '/'); + *++cp = 0; + n = cp-buf; + m = sysread(ctl, cp, sizeof(buf) - n - 1); + if(n<=0){ + sysclose(ctl); + return -1; + } + buf[n+m] = 0; + + strcpy(newdir, buf); + return ctl; +} |