#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h" static intgrowfd(Fgrp *f, int fd){ int n; Chan **nfd, **ofd; if(fd < f->nfd) return 0; n = f->nfd+DELTAFD; if(n > MAXNFD) n = MAXNFD; if(fd >= n) return -1; nfd = malloc(n*sizeof(Chan*)); if(nfd == nil) return -1; ofd = f->fd; memmove(nfd, ofd, f->nfd*sizeof(Chan *)); f->fd = nfd; f->nfd = n; free(ofd); return 0;} intnewfd(Chan *c){ int i; Fgrp *f = up->env->fgrp; lock(f); for(i=f->minfd; i<f->nfd; i++) if(f->fd[i] == 0) break; if(i >= f->nfd && growfd(f, i) < 0){ unlock(f); exhausted("file descriptors"); return -1; } f->minfd = i + 1; if(i > f->maxfd) f->maxfd = i; f->fd[i] = c; unlock(f); return i;} Chan*fdtochan(Fgrp *f, int fd, int mode, int chkmnt, int iref){ Chan *c; c = 0; lock(f); if(fd<0 || f->maxfd<fd || (c = f->fd[fd])==0) { unlock(f); error(Ebadfd); } if(iref) incref(c); unlock(f); if(chkmnt && (c->flag&CMSG)) { if(iref) cclose(c); error(Ebadusefd); } if(mode<0 || c->mode==ORDWR) return c; if((mode&OTRUNC) && c->mode==OREAD) { if(iref) cclose(c); error(Ebadusefd); } if((mode&~OTRUNC) != c->mode) { if(iref) cclose(c); error(Ebadusefd); } return c;} longkchanio(void *vc, void *buf, int n, int mode){ int r; Chan *c; c = vc; if(waserror()) return -1; if(mode == OREAD) r = devtab[c->type]->read(c, buf, n, c->offset); else r = devtab[c->type]->write(c, buf, n, c->offset); lock(c); c->offset += r; unlock(c); poperror(); return r;} intopenmode(ulong o){ if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC)) error(Ebadarg); o &= ~(OTRUNC|OCEXEC|ORCLOSE); if(o > OEXEC) error(Ebadarg); if(o == OEXEC) return OREAD; return o;} voidfdclose(Fgrp *f, int fd){ int i; Chan *c; lock(f); c = f->fd[fd]; if(c == 0){ /* can happen for users with shared fd tables */ unlock(f); return; } f->fd[fd] = 0; if(fd == f->maxfd) for(i=fd; --i>=0 && f->fd[i]==0; ) f->maxfd = i; if(fd < f->minfd) f->minfd = fd; unlock(f); cclose(c);} intkchdir(char *path){ Chan *c; Pgrp *pg; if(waserror()) return -1; c = namec(path, Atodir, 0, 0); pg = up->env->pgrp; cclose(pg->dot); pg->dot = c; poperror(); return 0;} intkfgrpclose(Fgrp *f, int fd){ if(waserror()) return -1; /* * Take no reference on the chan because we don't really need the * data structure, and are calling fdtochan only for error checks. * fdclose takes care of processes racing through here. */ fdtochan(f, fd, -1, 0, 0); fdclose(f, fd); poperror(); return 0;} intkclose(int fd){ return kfgrpclose(up->env->fgrp, fd);} intkcreate(char *path, int mode, ulong perm){ int fd; Chan *c; if(waserror()) return -1; openmode(mode&~OEXCL); /* error check only; OEXCL okay here */ c = namec(path, Acreate, mode, perm); if(waserror()) { cclose(c); nexterror(); } fd = newfd(c); if(fd < 0) error(Enofd); poperror(); poperror(); return fd;} intkdup(int old, int new){ int fd; Chan *c, *oc; Fgrp *f = up->env->fgrp; if(waserror()) return -1; c = fdtochan(up->env->fgrp, old, -1, 0, 1); if(c->qid.type & QTAUTH) error(Eperm); fd = new; if(fd != -1){ lock(f); if(fd<0 || growfd(f, fd) < 0) { unlock(f); cclose(c); error(Ebadfd); } if(fd > f->maxfd) f->maxfd = fd; oc = f->fd[fd]; f->fd[fd] = c; unlock(f); if(oc) cclose(oc); }else{ if(waserror()) { cclose(c); nexterror(); } fd = newfd(c); if(fd < 0) error(Enofd); poperror(); } poperror(); return fd;} intkfstat(int fd, uchar *buf, int n){ Chan *c; if(waserror()) return -1; c = fdtochan(up->env->fgrp, fd, -1, 0, 1); if(waserror()) { cclose(c); nexterror(); } devtab[c->type]->stat(c, buf, n); poperror(); cclose(c); poperror(); return n;} char*kfd2path(int fd){ Chan *c; char *s; if(waserror()) return nil; c = fdtochan(up->env->fgrp, fd, -1, 0, 1); s = nil; if(c->name != nil){ s = malloc(c->name->len+1); if(s == nil){ cclose(c); error(Enomem); } memmove(s, c->name->s, c->name->len+1); cclose(c); } poperror(); return s;} intkfauth(int fd, char *aname){ Chan *c, *ac; if(waserror()) return -1; validname(aname, 0); c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1); if(waserror()){ cclose(c); nexterror(); } ac = mntauth(c, aname); /* at this point ac is responsible for keeping c alive */ poperror(); /* c */ cclose(c); if(waserror()){ cclose(ac); nexterror(); } fd = newfd(ac); if(fd < 0) error(Enofd); poperror(); /* ac */ poperror(); return fd;} intkfversion(int fd, uint msize, char *vers, uint arglen){ int m; Chan *c; if(waserror()) return -1; /* check there's a NUL in the version string */ if(arglen==0 || memchr(vers, 0, arglen)==0) error(Ebadarg); c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1); if(waserror()){ cclose(c); nexterror(); } m = mntversion(c, vers, msize, arglen); poperror(); cclose(c); poperror(); return m;} intkpipe(int fd[2]){ Dev *d; Fgrp *f; Chan *c[2]; static char *names[] = {"data", "data1"}; f = up->env->fgrp; d = devtab[devno('|', 0)]; c[0] = namec("#|", Atodir, 0, 0); c[1] = 0; fd[0] = -1; fd[1] = -1; if(waserror()) { if(c[0] != 0) cclose(c[0]); if(c[1] != 0) cclose(c[1]); if(fd[0] >= 0) f->fd[fd[0]]=0; if(fd[1] >= 0) f->fd[fd[1]]=0; return -1; } c[1] = cclone(c[0]); if(walk(&c[0], &names[0], 1, 1, nil) < 0) error(Egreg); if(walk(&c[1], &names[1], 1, 1, nil) < 0) error(Egreg); c[0] = d->open(c[0], ORDWR); c[1] = d->open(c[1], ORDWR); fd[0] = newfd(c[0]); if(fd[0] < 0) error(Enofd); fd[1] = newfd(c[1]); if(fd[1] < 0) error(Enofd); poperror(); return 0;} intkfwstat(int fd, uchar *buf, int n){ Chan *c; if(waserror()) return -1; validstat(buf, n); c = fdtochan(up->env->fgrp, fd, -1, 1, 1); if(waserror()) { cclose(c); nexterror(); } n = devtab[c->type]->wstat(c, buf, n); poperror(); cclose(c); poperror(); return n;} longbindmount(Chan *c, char *old, int flag, char *spec){ int ret; Chan *c1; if(flag>MMASK || (flag&MORDER) == (MBEFORE|MAFTER)) error(Ebadarg); c1 = namec(old, Amount, 0, 0); if(waserror()){ cclose(c1); nexterror(); } ret = cmount(c, c1, flag, spec); poperror(); cclose(c1); return ret;} intkbind(char *new, char *old, int flags){ long r; Chan *c0; if(waserror()) return -1; c0 = namec(new, Abind, 0, 0); if(waserror()) { cclose(c0); nexterror(); } r = bindmount(c0, old, flags, ""); poperror(); cclose(c0); poperror(); return r;} intkmount(int fd, int afd, char *old, int flags, char *spec){ long r; volatile struct { Chan *c; } c0; volatile struct { Chan *c; } bc; volatile struct { Chan *c; } ac; Mntparam mntparam; ac.c = nil; bc.c = nil; c0.c = nil; if(waserror()) { cclose(ac.c); cclose(bc.c); cclose(c0.c); return -1; } bc.c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1); if(afd >= 0) ac.c = fdtochan(up->env->fgrp, afd, ORDWR, 0, 1); mntparam.chan = bc.c; mntparam.authchan = ac.c; mntparam.spec = spec; mntparam.flags = flags;Lines 1–500 of 1125. Load more
#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" static int growfd(Fgrp *f, int fd) { int n; Chan **nfd, **ofd; if(fd < f->nfd) return 0; n = f->nfd+DELTAFD; if(n > MAXNFD) n = MAXNFD; if(fd >= n) return -1; nfd = malloc(n*sizeof(Chan*)); if(nfd == nil) return -1; ofd = f->fd; memmove(nfd, ofd, f->nfd*sizeof(Chan *)); f->fd = nfd; f->nfd = n; free(ofd); return 0; } int newfd(Chan *c) { int i; Fgrp *f = up->env->fgrp; lock(f); for(i=f->minfd; i<f->nfd; i++) if(f->fd[i] == 0) break; if(i >= f->nfd && growfd(f, i) < 0){ unlock(f); exhausted("file descriptors"); return -1; } f->minfd = i + 1; if(i > f->maxfd) f->maxfd = i; f->fd[i] = c; unlock(f); return i; } Chan* fdtochan(Fgrp *f, int fd, int mode, int chkmnt, int iref) { Chan *c; c = 0; lock(f); if(fd<0 || f->maxfd<fd || (c = f->fd[fd])==0) { unlock(f); error(Ebadfd); } if(iref) incref(c); unlock(f); if(chkmnt && (c->flag&CMSG)) { if(iref) cclose(c); error(Ebadusefd); } if(mode<0 || c->mode==ORDWR) return c; if((mode&OTRUNC) && c->mode==OREAD) { if(iref) cclose(c); error(Ebadusefd); } if((mode&~OTRUNC) != c->mode) { if(iref) cclose(c); error(Ebadusefd); } return c; } long kchanio(void *vc, void *buf, int n, int mode) { int r; Chan *c; c = vc; if(waserror()) return -1; if(mode == OREAD) r = devtab[c->type]->read(c, buf, n, c->offset); else r = devtab[c->type]->write(c, buf, n, c->offset); lock(c); c->offset += r; unlock(c); poperror(); return r; } int openmode(ulong o) { if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC)) error(Ebadarg); o &= ~(OTRUNC|OCEXEC|ORCLOSE); if(o > OEXEC) error(Ebadarg); if(o == OEXEC) return OREAD; return o; } void fdclose(Fgrp *f, int fd) { int i; Chan *c; lock(f); c = f->fd[fd]; if(c == 0){ /* can happen for users with shared fd tables */ unlock(f); return; } f->fd[fd] = 0; if(fd == f->maxfd) for(i=fd; --i>=0 && f->fd[i]==0; ) f->maxfd = i; if(fd < f->minfd) f->minfd = fd; unlock(f); cclose(c); } int kchdir(char *path) { Chan *c; Pgrp *pg; if(waserror()) return -1; c = namec(path, Atodir, 0, 0); pg = up->env->pgrp; cclose(pg->dot); pg->dot = c; poperror(); return 0; } int kfgrpclose(Fgrp *f, int fd) { if(waserror()) return -1; /* * Take no reference on the chan because we don't really need the * data structure, and are calling fdtochan only for error checks. * fdclose takes care of processes racing through here. */ fdtochan(f, fd, -1, 0, 0); fdclose(f, fd); poperror(); return 0; } int kclose(int fd) { return kfgrpclose(up->env->fgrp, fd); } int kcreate(char *path, int mode, ulong perm) { int fd; Chan *c; if(waserror()) return -1; openmode(mode&~OEXCL); /* error check only; OEXCL okay here */ c = namec(path, Acreate, mode, perm); if(waserror()) { cclose(c); nexterror(); } fd = newfd(c); if(fd < 0) error(Enofd); poperror(); poperror(); return fd; } int kdup(int old, int new) { int fd; Chan *c, *oc; Fgrp *f = up->env->fgrp; if(waserror()) return -1; c = fdtochan(up->env->fgrp, old, -1, 0, 1); if(c->qid.type & QTAUTH) error(Eperm); fd = new; if(fd != -1){ lock(f); if(fd<0 || growfd(f, fd) < 0) { unlock(f); cclose(c); error(Ebadfd); } if(fd > f->maxfd) f->maxfd = fd; oc = f->fd[fd]; f->fd[fd] = c; unlock(f); if(oc) cclose(oc); }else{ if(waserror()) { cclose(c); nexterror(); } fd = newfd(c); if(fd < 0) error(Enofd); poperror(); } poperror(); return fd; } int kfstat(int fd, uchar *buf, int n) { Chan *c; if(waserror()) return -1; c = fdtochan(up->env->fgrp, fd, -1, 0, 1); if(waserror()) { cclose(c); nexterror(); } devtab[c->type]->stat(c, buf, n); poperror(); cclose(c); poperror(); return n; } char* kfd2path(int fd) { Chan *c; char *s; if(waserror()) return nil; c = fdtochan(up->env->fgrp, fd, -1, 0, 1); s = nil; if(c->name != nil){ s = malloc(c->name->len+1); if(s == nil){ cclose(c); error(Enomem); } memmove(s, c->name->s, c->name->len+1); cclose(c); } poperror(); return s; } int kfauth(int fd, char *aname) { Chan *c, *ac; if(waserror()) return -1; validname(aname, 0); c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1); if(waserror()){ cclose(c); nexterror(); } ac = mntauth(c, aname); /* at this point ac is responsible for keeping c alive */ poperror(); /* c */ cclose(c); if(waserror()){ cclose(ac); nexterror(); } fd = newfd(ac); if(fd < 0) error(Enofd); poperror(); /* ac */ poperror(); return fd; } int kfversion(int fd, uint msize, char *vers, uint arglen) { int m; Chan *c; if(waserror()) return -1; /* check there's a NUL in the version string */ if(arglen==0 || memchr(vers, 0, arglen)==0) error(Ebadarg); c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1); if(waserror()){ cclose(c); nexterror(); } m = mntversion(c, vers, msize, arglen); poperror(); cclose(c); poperror(); return m; } int kpipe(int fd[2]) { Dev *d; Fgrp *f; Chan *c[2]; static char *names[] = {"data", "data1"}; f = up->env->fgrp; d = devtab[devno('|', 0)]; c[0] = namec("#|", Atodir, 0, 0); c[1] = 0; fd[0] = -1; fd[1] = -1; if(waserror()) { if(c[0] != 0) cclose(c[0]); if(c[1] != 0) cclose(c[1]); if(fd[0] >= 0) f->fd[fd[0]]=0; if(fd[1] >= 0) f->fd[fd[1]]=0; return -1; } c[1] = cclone(c[0]); if(walk(&c[0], &names[0], 1, 1, nil) < 0) error(Egreg); if(walk(&c[1], &names[1], 1, 1, nil) < 0) error(Egreg); c[0] = d->open(c[0], ORDWR); c[1] = d->open(c[1], ORDWR); fd[0] = newfd(c[0]); if(fd[0] < 0) error(Enofd); fd[1] = newfd(c[1]); if(fd[1] < 0) error(Enofd); poperror(); return 0; } int kfwstat(int fd, uchar *buf, int n) { Chan *c; if(waserror()) return -1; validstat(buf, n); c = fdtochan(up->env->fgrp, fd, -1, 1, 1); if(waserror()) { cclose(c); nexterror(); } n = devtab[c->type]->wstat(c, buf, n); poperror(); cclose(c); poperror(); return n; } long bindmount(Chan *c, char *old, int flag, char *spec) { int ret; Chan *c1; if(flag>MMASK || (flag&MORDER) == (MBEFORE|MAFTER)) error(Ebadarg); c1 = namec(old, Amount, 0, 0); if(waserror()){ cclose(c1); nexterror(); } ret = cmount(c, c1, flag, spec); poperror(); cclose(c1); return ret; } int kbind(char *new, char *old, int flags) { long r; Chan *c0; if(waserror()) return -1; c0 = namec(new, Abind, 0, 0); if(waserror()) { cclose(c0); nexterror(); } r = bindmount(c0, old, flags, ""); poperror(); cclose(c0); poperror(); return r; } int kmount(int fd, int afd, char *old, int flags, char *spec) { long r; volatile struct { Chan *c; } c0; volatile struct { Chan *c; } bc; volatile struct { Chan *c; } ac; Mntparam mntparam; ac.c = nil; bc.c = nil; c0.c = nil; if(waserror()) { cclose(ac.c); cclose(bc.c); cclose(c0.c); return -1; } bc.c = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1); if(afd >= 0) ac.c = fdtochan(up->env->fgrp, afd, ORDWR, 0, 1); mntparam.chan = bc.c; mntparam.authchan = ac.c; mntparam.spec = spec; mntparam.flags = flags;