#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h" enum { Qroot, Qcroot, Qshr, Qcshr, Qcmpt,}; typedef struct Ent Ent;typedef struct Shr Shr;typedef struct Mpt Mpt;typedef struct Sch Sch; struct Ent{ Ref; int id; char *name; char *owner; ulong perm;}; struct Shr{ Ent; Mhead umh; Shr *next;}; struct Mpt{ Ent; Mount m;}; struct Sch{ int level; Shr *shr; Mpt *mpt; Chan *chan;}; static QLock shrslk;static Shr *shrs; static int shrid;static int mptid; static Mpt*tompt(Mount *m){ return (Mpt*)((char*)m - (char*)&((Mpt*)0)->m);} static Sch*tosch(Chan *c){ Sch *sch; if(c == nil) error("nil chan"); sch = c->aux; if(sch == nil) error("nil chan aux"); if(sch->chan != c) error("bad chan"); return sch;} static voidshrinit(void){ shrid = 1; mptid = 1;} static voidputmpt(Mpt *mpt){ if(decref(mpt)) return; if(mpt->m.to != nil) cclose(mpt->m.to); free(mpt->name); free(mpt->owner); free(mpt);} static voidputshr(Shr *shr){ if(decref(shr)) return; free(shr->name); free(shr->owner); free(shr);} static Qidshrqid(int level, int id){ Qid q; q.type = (level == Qcmpt) ? QTFILE : QTDIR; q.path = (uvlong)id<<4 | level; q.vers = 0; return q;} static Chan*shrattach(char *spec){ Sch *sch; Chan *c; if(!(spec[0] == 'c' && spec[1] == 0 || spec[0] == 0)) error(Enoattach); c = devattach(L'σ', spec); sch = smalloc(sizeof(*sch)); sch->level = spec[0] == 'c' ? Qcroot : Qroot; sch->mpt = nil; sch->shr = nil; sch->chan = c; c->aux = sch; c->qid = shrqid(sch->level, 0); return c;} static Chan*shrclone(Chan *c){ Chan *nc; Sch *sch, *och; och = tosch(c); nc = devclone(c); sch = smalloc(sizeof(*sch)); memmove(sch, och, sizeof(*sch)); if(sch->shr != nil) incref(sch->shr); if(sch->mpt != nil) incref(sch->mpt); sch->chan = nc; nc->aux = sch; return nc;} static voidshrclunk(Chan *c){ Sch *sch; sch = tosch(c); c->aux = nil; sch->chan = nil; if(sch->mpt != nil) putmpt(sch->mpt); if(sch->shr != nil) putshr(sch->shr); free(sch); } static Walkqid*shrwalk(Chan *c, Chan *nc, char **name, int nname){ Walkqid *wq, *wq2; int alloc, j; char *nam; Sch *sch; Shr *shr; Mpt *mpt; Mount *m; Mhead *h; alloc = 0; if(nc == nil){ nc = shrclone(c); alloc = 1; } wq = smalloc(sizeof(Walkqid) + (nname - 1) * sizeof(Qid)); wq->nqid = 0; wq->clone = nc; if(waserror()){ if(alloc) cclose(wq->clone); if(wq->nqid > 0) wq->clone = nil; else { free(wq); wq = nil; } return wq; } sch = tosch(nc); for(j = 0; j < nname; j++){ if(nc->qid.type != QTDIR) error(Enotdir); nam = name[j]; if(nam[0] == '.' && nam[1] == 0) { /* nop */ } else if(nam[0] == '.' && nam[1] == '.' && nam[2] == 0) { switch(sch->level){ default: error(Egreg); case Qshr: nc->qid = shrqid(sch->level = Qroot, 0); break; case Qcshr: nc->qid = shrqid(sch->level = Qcroot, 0); break; } putshr(sch->shr); sch->shr = nil; } else if(sch->level == Qcroot || sch->level == Qroot) { qlock(&shrslk); for(shr = shrs; shr != nil; shr = shr->next) if(strcmp(nam, shr->name) == 0){ incref(shr); break; } qunlock(&shrslk); if(shr == nil) error(Enonexist); sch->level = sch->level == Qcroot ? Qcshr : Qshr; sch->shr = shr; nc->qid = shrqid(sch->level, shr->id); } else if(sch->level == Qcshr) { mpt = nil; shr = sch->shr; h = &shr->umh; rlock(&h->lock); for(m = h->mount; m != nil; m = m->next){ mpt = tompt(m); if(strcmp(nam, mpt->name) == 0){ incref(mpt); break; } } runlock(&h->lock); if(m == nil) error(Enonexist); sch->mpt = mpt; nc->qid = shrqid(sch->level = Qcmpt, mpt->id); } else if(sch->level == Qshr) { shr = sch->shr; h = &shr->umh; wq2 = nil; rlock(&h->lock); for(m = h->mount; m != nil && wq2 == nil; m = m->next){ if(m->to == nil) continue; if(waserror()) continue; wq2 = devtab[m->to->type]->walk(m->to, nil, name + j, nname - j); poperror(); } runlock(&h->lock); if(wq2 == nil) error(Enonexist); memmove(wq->qid + wq->nqid, wq2->qid, wq2->nqid); wq->nqid += wq2->nqid; if(alloc) cclose(wq->clone); wq->clone = wq2->clone; free(wq2); poperror(); return wq; } else error(Egreg); wq->qid[wq->nqid++] = nc->qid; } poperror(); return wq;} static intshrgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp){ Mpt *mpt; Sch *sch; Shr *shr; Mhead *h; Mount *m; sch = tosch(c); switch(sch->level){ default: return -1; case Qroot: case Qcroot: qlock(&shrslk); for(shr = shrs; shr != nil && s > 0; shr = shr->next) s--; if(shr == nil){ qunlock(&shrslk); return -1; } kstrcpy(up->genbuf, shr->name, sizeof up->genbuf); if(sch->level == Qroot) devdir(c, shrqid(Qshr, shr->id), up->genbuf, 0, shr->owner, shr->perm & ~0222, dp); else devdir(c, shrqid(Qcshr, shr->id), up->genbuf, 0, shr->owner, shr->perm, dp); qunlock(&shrslk); return 1; case Qcshr: shr = sch->shr; h = &shr->umh; rlock(&h->lock); for(m = h->mount; m != nil && s > 0; m = m->next) s--; if(m == nil){ runlock(&h->lock); return -1; } mpt = tompt(m); kstrcpy(up->genbuf, mpt->name, sizeof up->genbuf); devdir(c, shrqid(Qcmpt, mpt->id), up->genbuf, 0, mpt->owner, mpt->perm, dp); runlock(&h->lock); return 1; }} static intshrstat(Chan *c, uchar *db, int n){ Sch *sch; Dir dir; int rc; sch = tosch(c); switch(sch->level){ default: error(Egreg); case Qroot: devdir(c, c->qid, "#σ", 0, eve, 0555, &dir); break; case Qcroot: devdir(c, c->qid, "#σc", 0, eve, 0777, &dir); break; case Qshr: devdir(c, c->qid, sch->shr->name, 0, sch->shr->owner, sch->shr->perm & ~0222, &dir); break; case Qcshr: devdir(c, c->qid, sch->shr->name, 0, sch->shr->owner, sch->shr->perm, &dir); break; case Qcmpt: devdir(c, c->qid, sch->mpt->name, 0, sch->mpt->owner, sch->mpt->perm, &dir); break; } rc = convD2M(&dir, db, n); if(rc == 0) error(Ebadarg); return rc;} static Chan*shropen(Chan *c, int omode){ Chan *nc; Sch *sch; Shr *shr; Mpt *mpt; int mode; if(c->qid.type == QTDIR && omode != OREAD) error(Eisdir); mode = openmode(omode); sch = tosch(c); switch(sch->level){ default: error(Egreg); case Qroot: case Qcroot: break; case Qshr: case Qcshr: shr = sch->shr; devpermcheck(shr->owner, shr->perm, mode); break; case Qcmpt: if(omode&OTRUNC) error(Eexist); shr = sch->shr; mpt = sch->mpt; devpermcheck(mpt->owner, mpt->perm, mode); rlock(&shr->umh.lock); if(mpt->m.to == nil || mpt->m.to->mchan == nil){ runlock(&shr->umh.lock); error(Eshutdown); } nc = mpt->m.to->mchan; incref(nc); runlock(&shr->umh.lock); if(mode != nc->mode){ cclose(nc); error(Eperm); } cclose(c); return nc; } c->mode = mode; c->flag |= COPEN; c->offset = 0; return c;} /* chan.c */Chan* createdir(Chan *c, Mhead *m); static Chan*shrcreate(Chan *c, char *name, int omode, ulong perm){ Sch *sch; Shr *shr; Mpt *mpt; Mhead *h; Mount *m; Chan *nc; int mode; mode = openmode(omode); sch = tosch(c); switch(sch->level){ case Qcroot: case Qcshr: if(strcmp(up->user, "none") == 0) error(Eperm); } switch(sch->level){ default: error(Eperm); case Qshr: incref(c); if(waserror()){ cclose(c); nexterror(); } nc = createdir(c, &sch->shr->umh); poperror(); if(waserror()){ cclose(nc); nexterror(); } nc = devtab[nc->type]->create(nc, name, omode, perm); poperror(); cclose(c); return nc; case Qcroot: if(up->pgrp->noattach) error(Enoattach); if((perm & DMDIR) == 0 || mode != OREAD) error(Eperm); if(strlen(name) >= sizeof(up->genbuf)) error(Etoolong); qlock(&shrslk); if(waserror()){ qunlock(&shrslk); nexterror(); } for(shr = shrs; shr != nil; shr = shr->next) if(strcmp(name, shr->name) == 0) error(Eexist); shr = smalloc(sizeof(*shr)); incref(shr); shr->id = shrid++; kstrdup(&shr->name, name); kstrdup(&shr->owner, up->user); shr->perm = perm; incref(shr); shr->next = shrs; shrs = shr; poperror(); qunlock(&shrslk); c->qid = shrqid(sch->level = Qcshr, shr->id); sch->shr = shr; break; case Qcshr: if(up->pgrp->noattach) error(Enoattach);Lines 1–500 of 827. Load more
#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" enum { Qroot, Qcroot, Qshr, Qcshr, Qcmpt, }; typedef struct Ent Ent; typedef struct Shr Shr; typedef struct Mpt Mpt; typedef struct Sch Sch; struct Ent { Ref; int id; char *name; char *owner; ulong perm; }; struct Shr { Ent; Mhead umh; Shr *next; }; struct Mpt { Ent; Mount m; }; struct Sch { int level; Shr *shr; Mpt *mpt; Chan *chan; }; static QLock shrslk; static Shr *shrs; static int shrid; static int mptid; static Mpt* tompt(Mount *m) { return (Mpt*)((char*)m - (char*)&((Mpt*)0)->m); } static Sch* tosch(Chan *c) { Sch *sch; if(c == nil) error("nil chan"); sch = c->aux; if(sch == nil) error("nil chan aux"); if(sch->chan != c) error("bad chan"); return sch; } static void shrinit(void) { shrid = 1; mptid = 1; } static void putmpt(Mpt *mpt) { if(decref(mpt)) return; if(mpt->m.to != nil) cclose(mpt->m.to); free(mpt->name); free(mpt->owner); free(mpt); } static void putshr(Shr *shr) { if(decref(shr)) return; free(shr->name); free(shr->owner); free(shr); } static Qid shrqid(int level, int id) { Qid q; q.type = (level == Qcmpt) ? QTFILE : QTDIR; q.path = (uvlong)id<<4 | level; q.vers = 0; return q; } static Chan* shrattach(char *spec) { Sch *sch; Chan *c; if(!(spec[0] == 'c' && spec[1] == 0 || spec[0] == 0)) error(Enoattach); c = devattach(L'σ', spec); sch = smalloc(sizeof(*sch)); sch->level = spec[0] == 'c' ? Qcroot : Qroot; sch->mpt = nil; sch->shr = nil; sch->chan = c; c->aux = sch; c->qid = shrqid(sch->level, 0); return c; } static Chan* shrclone(Chan *c) { Chan *nc; Sch *sch, *och; och = tosch(c); nc = devclone(c); sch = smalloc(sizeof(*sch)); memmove(sch, och, sizeof(*sch)); if(sch->shr != nil) incref(sch->shr); if(sch->mpt != nil) incref(sch->mpt); sch->chan = nc; nc->aux = sch; return nc; } static void shrclunk(Chan *c) { Sch *sch; sch = tosch(c); c->aux = nil; sch->chan = nil; if(sch->mpt != nil) putmpt(sch->mpt); if(sch->shr != nil) putshr(sch->shr); free(sch); } static Walkqid* shrwalk(Chan *c, Chan *nc, char **name, int nname) { Walkqid *wq, *wq2; int alloc, j; char *nam; Sch *sch; Shr *shr; Mpt *mpt; Mount *m; Mhead *h; alloc = 0; if(nc == nil){ nc = shrclone(c); alloc = 1; } wq = smalloc(sizeof(Walkqid) + (nname - 1) * sizeof(Qid)); wq->nqid = 0; wq->clone = nc; if(waserror()){ if(alloc) cclose(wq->clone); if(wq->nqid > 0) wq->clone = nil; else { free(wq); wq = nil; } return wq; } sch = tosch(nc); for(j = 0; j < nname; j++){ if(nc->qid.type != QTDIR) error(Enotdir); nam = name[j]; if(nam[0] == '.' && nam[1] == 0) { /* nop */ } else if(nam[0] == '.' && nam[1] == '.' && nam[2] == 0) { switch(sch->level){ default: error(Egreg); case Qshr: nc->qid = shrqid(sch->level = Qroot, 0); break; case Qcshr: nc->qid = shrqid(sch->level = Qcroot, 0); break; } putshr(sch->shr); sch->shr = nil; } else if(sch->level == Qcroot || sch->level == Qroot) { qlock(&shrslk); for(shr = shrs; shr != nil; shr = shr->next) if(strcmp(nam, shr->name) == 0){ incref(shr); break; } qunlock(&shrslk); if(shr == nil) error(Enonexist); sch->level = sch->level == Qcroot ? Qcshr : Qshr; sch->shr = shr; nc->qid = shrqid(sch->level, shr->id); } else if(sch->level == Qcshr) { mpt = nil; shr = sch->shr; h = &shr->umh; rlock(&h->lock); for(m = h->mount; m != nil; m = m->next){ mpt = tompt(m); if(strcmp(nam, mpt->name) == 0){ incref(mpt); break; } } runlock(&h->lock); if(m == nil) error(Enonexist); sch->mpt = mpt; nc->qid = shrqid(sch->level = Qcmpt, mpt->id); } else if(sch->level == Qshr) { shr = sch->shr; h = &shr->umh; wq2 = nil; rlock(&h->lock); for(m = h->mount; m != nil && wq2 == nil; m = m->next){ if(m->to == nil) continue; if(waserror()) continue; wq2 = devtab[m->to->type]->walk(m->to, nil, name + j, nname - j); poperror(); } runlock(&h->lock); if(wq2 == nil) error(Enonexist); memmove(wq->qid + wq->nqid, wq2->qid, wq2->nqid); wq->nqid += wq2->nqid; if(alloc) cclose(wq->clone); wq->clone = wq2->clone; free(wq2); poperror(); return wq; } else error(Egreg); wq->qid[wq->nqid++] = nc->qid; } poperror(); return wq; } static int shrgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp) { Mpt *mpt; Sch *sch; Shr *shr; Mhead *h; Mount *m; sch = tosch(c); switch(sch->level){ default: return -1; case Qroot: case Qcroot: qlock(&shrslk); for(shr = shrs; shr != nil && s > 0; shr = shr->next) s--; if(shr == nil){ qunlock(&shrslk); return -1; } kstrcpy(up->genbuf, shr->name, sizeof up->genbuf); if(sch->level == Qroot) devdir(c, shrqid(Qshr, shr->id), up->genbuf, 0, shr->owner, shr->perm & ~0222, dp); else devdir(c, shrqid(Qcshr, shr->id), up->genbuf, 0, shr->owner, shr->perm, dp); qunlock(&shrslk); return 1; case Qcshr: shr = sch->shr; h = &shr->umh; rlock(&h->lock); for(m = h->mount; m != nil && s > 0; m = m->next) s--; if(m == nil){ runlock(&h->lock); return -1; } mpt = tompt(m); kstrcpy(up->genbuf, mpt->name, sizeof up->genbuf); devdir(c, shrqid(Qcmpt, mpt->id), up->genbuf, 0, mpt->owner, mpt->perm, dp); runlock(&h->lock); return 1; } } static int shrstat(Chan *c, uchar *db, int n) { Sch *sch; Dir dir; int rc; sch = tosch(c); switch(sch->level){ default: error(Egreg); case Qroot: devdir(c, c->qid, "#σ", 0, eve, 0555, &dir); break; case Qcroot: devdir(c, c->qid, "#σc", 0, eve, 0777, &dir); break; case Qshr: devdir(c, c->qid, sch->shr->name, 0, sch->shr->owner, sch->shr->perm & ~0222, &dir); break; case Qcshr: devdir(c, c->qid, sch->shr->name, 0, sch->shr->owner, sch->shr->perm, &dir); break; case Qcmpt: devdir(c, c->qid, sch->mpt->name, 0, sch->mpt->owner, sch->mpt->perm, &dir); break; } rc = convD2M(&dir, db, n); if(rc == 0) error(Ebadarg); return rc; } static Chan* shropen(Chan *c, int omode) { Chan *nc; Sch *sch; Shr *shr; Mpt *mpt; int mode; if(c->qid.type == QTDIR && omode != OREAD) error(Eisdir); mode = openmode(omode); sch = tosch(c); switch(sch->level){ default: error(Egreg); case Qroot: case Qcroot: break; case Qshr: case Qcshr: shr = sch->shr; devpermcheck(shr->owner, shr->perm, mode); break; case Qcmpt: if(omode&OTRUNC) error(Eexist); shr = sch->shr; mpt = sch->mpt; devpermcheck(mpt->owner, mpt->perm, mode); rlock(&shr->umh.lock); if(mpt->m.to == nil || mpt->m.to->mchan == nil){ runlock(&shr->umh.lock); error(Eshutdown); } nc = mpt->m.to->mchan; incref(nc); runlock(&shr->umh.lock); if(mode != nc->mode){ cclose(nc); error(Eperm); } cclose(c); return nc; } c->mode = mode; c->flag |= COPEN; c->offset = 0; return c; } /* chan.c */ Chan* createdir(Chan *c, Mhead *m); static Chan* shrcreate(Chan *c, char *name, int omode, ulong perm) { Sch *sch; Shr *shr; Mpt *mpt; Mhead *h; Mount *m; Chan *nc; int mode; mode = openmode(omode); sch = tosch(c); switch(sch->level){ case Qcroot: case Qcshr: if(strcmp(up->user, "none") == 0) error(Eperm); } switch(sch->level){ default: error(Eperm); case Qshr: incref(c); if(waserror()){ cclose(c); nexterror(); } nc = createdir(c, &sch->shr->umh); poperror(); if(waserror()){ cclose(nc); nexterror(); } nc = devtab[nc->type]->create(nc, name, omode, perm); poperror(); cclose(c); return nc; case Qcroot: if(up->pgrp->noattach) error(Enoattach); if((perm & DMDIR) == 0 || mode != OREAD) error(Eperm); if(strlen(name) >= sizeof(up->genbuf)) error(Etoolong); qlock(&shrslk); if(waserror()){ qunlock(&shrslk); nexterror(); } for(shr = shrs; shr != nil; shr = shr->next) if(strcmp(name, shr->name) == 0) error(Eexist); shr = smalloc(sizeof(*shr)); incref(shr); shr->id = shrid++; kstrdup(&shr->name, name); kstrdup(&shr->owner, up->user); shr->perm = perm; incref(shr); shr->next = shrs; shrs = shr; poperror(); qunlock(&shrslk); c->qid = shrqid(sch->level = Qcshr, shr->id); sch->shr = shr; break; case Qcshr: if(up->pgrp->noattach) error(Enoattach);