static int vcongen(Chan *c, char *d, Dirtab* dir, int i, int s, Dir *dp) { Proc *up = externup(); Qid q; int t = TYPE(c->qid); int vdidx = DEV(c->qid); if(vdidx >= nvcon) error(Ebadarg); switch(t){ case Qtopdir: if(s == DEVDOTDOT){ q = (Qid){QID(0, Qtopdir), 0, QTDIR}; snprint(up->genbuf, sizeof up->genbuf, "#%C", vcondevtab.dc); devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp); return 1; } return devgen(c, nil, topdir, nelem(topdir), s, dp); case Qvirtcon: if(s == DEVDOTDOT){ q = (Qid){QID(0, Qtopdir), 0, QTDIR}; snprint(up->genbuf, sizeof up->genbuf, "#%C", vcondevtab.dc); devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp); return 1; } if(s >= nvcon) return -1; snprint(up->genbuf, sizeof up->genbuf, vcons[s]->devname); q = (Qid) {QID(s, Qvcpipe), 0, 0}; devdir(c, q, up->genbuf, 0, eve, 0666, dp); return 1; } return -1; }
static int cmd3gen(Chan *c, int i, Dir *dp) { Qid q; Conv *cv; cv = cmd.conv[CONV(c->qid)]; switch(i){ default: return -1; case Qdata: mkqid(&q, QID(CONV(c->qid), Qdata), 0, QTFILE); devdir(c, q, "data", 0, cv->owner, cv->perm, dp); return 1; case Qstderr: mkqid(&q, QID(CONV(c->qid), Qstderr), 0, QTFILE); devdir(c, q, "stderr", 0, cv->owner, 0444, dp); return 1; case Qctl: mkqid(&q, QID(CONV(c->qid), Qctl), 0, QTFILE); devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp); return 1; case Qstatus: mkqid(&q, QID(CONV(c->qid), Qstatus), 0, QTFILE); devdir(c, q, "status", 0, cv->owner, 0444, dp); return 1; case Qwait: mkqid(&q, QID(CONV(c->qid), Qwait), 0, QTFILE); devdir(c, q, "wait", 0, cv->owner, 0444, dp); return 1; } }
static Chan* sdattach(char* spec) { Chan *c; char *p; SDev *sdev; int idno, subno; if(*spec == '\0'){ c = devattach(sddevtab.dc, spec); mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR); return c; } if(spec[0] != 's' || spec[1] != 'd') error(Ebadspec); idno = spec[2]; subno = strtol(&spec[3], &p, 0); if(p == &spec[3]) error(Ebadspec); if((sdev=sdgetdev(idno)) == nil) error(Enonexist); if(sdgetunit(sdev, subno) == nil){ decref(&sdev->r); error(Enonexist); } c = devattach(sddevtab.dc, spec); mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR); c->dev = (sdev->idno << UnitLOG) + subno; decref(&sdev->r); return c; }
static int sd2gen(Chan* c, int i, Dir* dp) { Qid q; uvlong l; SDpart *pp; SDperm *perm; SDunit *unit; SDev *sdev; int rv; sdev = sdgetdev(DEV(c->qid)); assert(sdev); unit = sdev->unit[UNIT(c->qid)]; rv = -1; switch(i){ case Qctl: mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl), unit->vers, QTFILE); perm = &unit->ctlperm; if(emptystr(perm->user)){ kstrdup(&perm->user, eve); perm->perm = 0644; /* nothing secret in ctl */ } devdir(c, q, "ctl", 0, perm->user, perm->perm, dp); rv = 1; break; case Qraw: mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw), unit->vers, QTFILE); perm = &unit->rawperm; if(emptystr(perm->user)){ kstrdup(&perm->user, eve); perm->perm = DMEXCL|0600; } devdir(c, q, "raw", 0, perm->user, perm->perm, dp); rv = 1; break; case Qpart: pp = &unit->part[PART(c->qid)]; l = (pp->end - pp->start) * unit->secsize; mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart), unit->vers+pp->vers, QTFILE); if(emptystr(pp->user)) kstrdup(&pp->user, eve); devdir(c, q, pp->name, l, pp->user, pp->perm, dp); rv = 1; break; } decref(&sdev->r); return rv; }
int Fsproto(Fs *f, Proto *p) { if(f->np >= Maxproto) return -1; p->f = f; if(p->ipproto > 0){ if(f->t2p[p->ipproto] != nil) return -1; f->t2p[p->ipproto] = p; } p->qid.type = QTDIR; p->qid.path = QID(f->np, 0, Qprotodir); p->conv = malloc(sizeof(Conv*)*(p->nc+1)); if(p->conv == nil) panic("Fsproto"); p->x = f->np; f->p[f->np++] = p; return 0; }
static int ip2gen(Chan *c, int i, Dir *dp) { Qid q; switch(i) { case Qclone: mkqid(&q, QID(PROTO(c->qid), 0, Qclone), 0, QTFILE); devdir(c, q, "clone", 0, network, 0666, dp); return 1; case Qstats: mkqid(&q, QID(PROTO(c->qid), 0, Qstats), 0, QTFILE); devdir(c, q, "stats", 0, network, 0444, dp); return 1; } return -1; }
static Chan * cmdattach(char *spec) { Chan *c; if(cmd.conv == nil) error(Enomem); c = devattach('C', spec); mkqid(&c->qid, QID(0, Qtopdir), 0, QTDIR); return c; }
Chan * ipattach(char *spec) { Chan *c; c = devattach('I', spec); c->qid.path = QID(0, 0, Qtopdir); c->qid.type = QTDIR; c->qid.vers = 0; return c; }
static int pcmgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp) { int slotno; Qid qid; long len; PCMslot *pp; if(i == DEVDOTDOT){ mkqid(&qid, Qdir, 0, QTDIR); devdir(c, qid, "#y", 0, eve, 0555, dp); return 1; } if(i >= Nents*nslot) return -1; slotno = i/Nents; pp = slot + slotno; len = 0; switch(i%Nents){ case 0: qid.path = QID(slotno, Qmem); snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno); len = pp->memlen; break; case 1: qid.path = QID(slotno, Qattr); snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno); len = pp->memlen; break; case 2: qid.path = QID(slotno, Qctl); snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno); break; } qid.vers = 0; qid.type = QTFILE; devdir(c, qid, up->genbuf, len, eve, 0660, dp); return 1; }
static int sd1gen(Chan* c, int i, Dir* dp) { Qid q; switch(i){ case Qtopctl: mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE); devdir(c, q, "sdctl", 0, eve, 0644, dp); /* no secrets */ return 1; } return -1; }
static int flashgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp) { Qid q; char *n; if(s == DEVDOTDOT){ mkqid(&q, QID(0, Qtopdir), 0, QTDIR); n = "#F"; if(c->dev != 0){ snprint(up->genbuf, sizeof up->genbuf, "#F%ld", c->dev); n = up->genbuf; } devdir(c, q, n, 0, eve, 0555, dp); return 1; } switch(TYPE(c->qid.path)){ case Qtopdir: if(s != 0) break; mkqid(&q, QID(0, Qflashdir), 0, QTDIR); n = "flash"; if(c->dev != 0){ snprint(up->genbuf, sizeof up->genbuf, "flash%ld", c->dev); n = up->genbuf; } devdir(c, q, n, 0, eve, 0555, dp); return 1; case Qflashdir: if(s >= 2*nelem(flash.card[c->dev]->part)) return -1; return flash2gen(c, QID(s>>1, s&1?Qctl:Qdata), dp); case Qctl: case Qdata: return flash2gen(c, (ulong)c->qid.path, dp); } return -1; }
Chan * ipattach(char *spec) { Chan *c; if(atoi(spec) != 0) error("bad specification"); c = devattach('I', spec); mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR); c->dev = 0; return c; }
void ixp_srv_walkandclone(Ixp9Req *req, IxpLookupFn lookup) { IxpFileId *file, *tfile; int i; file = ixp_srv_clonefiles(req->fid->aux); for(i=0; i < req->ifcall.twalk.nwname; i++) { if(!strcmp(req->ifcall.twalk.wname[i], "..")) { if(file->next) { tfile = file; file = file->next; ixp_srv_freefile(tfile); } }else{ tfile = lookup(file, req->ifcall.twalk.wname[i]); if(!tfile) break; assert(!tfile->next); if(strcmp(req->ifcall.twalk.wname[i], ".")) { tfile->next = file; file = tfile; } } req->ofcall.rwalk.wqid[i].type = file->tab.qtype; req->ofcall.rwalk.wqid[i].path = QID(file->tab.type, file->id); } /* There should be a way to do this on freefid() */ if(i < req->ifcall.twalk.nwname) { while((tfile = file)) { file=file->next; ixp_srv_freefile(tfile); } ixp_respond(req, Enofile); return; } /* Remove refs for req->fid if no new fid */ if(req->ifcall.hdr.fid == req->ifcall.twalk.newfid) { tfile = req->fid->aux; req->fid->aux = file; while((file = tfile)) { tfile = tfile->next; ixp_srv_freefile(file); } }else req->newfid->aux = file; req->ofcall.rwalk.nwqid = i; ixp_respond(req, nil); }
static int unitgen(Chan *c, ulong type, Dir *dp) { int perm, t; ulong vers; vlong size; char *p; Aoedev *d; Qid q; d = unit2dev(UNIT(c->qid)); perm = 0644; size = 0; vers = d->vers; t = QTFILE; switch(type){ default: return -1; case Qctl: p = "ctl"; break; case Qdata: p = "data"; perm = 0640; if(UP(d)) size = d->bsize; break; case Qconfig: p = "config"; if(UP(d)) size = d->nconfig; break; case Qident: p = "ident"; if(UP(d)) size = sizeof d->ident; break; case Qdevlinkdir: p = "devlink"; t = QTDIR; perm = 0555; break; } mkqid(&q, QID(UNIT(c->qid), type), vers, t); devdir(c, q, p, size, eve, perm, dp); return 1; }
static int ip1gen(Chan *c, int i, Dir *dp) { Qid q; char *p; int prot; int len = 0; Fs *f; extern ulong kerndate; f = ipfs[c->dev]; prot = 0666; mkqid(&q, QID(0, 0, i), 0, QTFILE); switch(i) { default: return -1; case Qarp: p = "arp"; prot = 0664; break; case Qbootp: p = "bootp"; break; case Qndb: p = "ndb"; len = strlen(f->ndb); q.vers = f->ndbvers; break; case Qiproute: p = "iproute"; prot = 0664; break; case Qipselftab: p = "ipselftab"; prot = 0444; break; case Qlog: p = "log"; break; } devdir(c, q, p, len, network, prot, dp); if(i == Qndb && f->ndbmtime > kerndate) dp->mtime = f->ndbmtime; return 1; }
static int ip3gen(Chan *c, int i, Dir *dp) { Qid q; Conv *cv; char *p; cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)]; if(cv->owner == nil) kstrdup(&cv->owner, eve); mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE); switch(i) { default: return -1; case Qctl: devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp); return 1; case Qdata: devdir(c, q, "data", qlen(cv->rq), cv->owner, cv->perm, dp); return 1; case Qerr: devdir(c, q, "err", qlen(cv->eq), cv->owner, cv->perm, dp); return 1; case Qlisten: devdir(c, q, "listen", 0, cv->owner, cv->perm, dp); return 1; case Qlocal: p = "local"; break; case Qremote: p = "remote"; break; case Qsnoop: if(strcmp(cv->p->name, "ipifc") != 0) return -1; devdir(c, q, "snoop", qlen(cv->sq), cv->owner, 0400, dp); return 1; case Qstatus: p = "status"; break; } devdir(c, q, p, 0, cv->owner, 0444, dp); return 1; }
int dostat(int id, Dirtab *dir, uint8_t *buf, int nbuf, uint clock) { Dir d; d.qid.path = QID(id, dir->qid); d.qid.vers = 0; d.qid.type = dir->type; d.mode = dir->perm; d.length = 0; /* would be nice to do better */ d.name = dir->name; d.uid = user; d.gid = user; d.muid = user; d.atime = clock; d.mtime = clock; return convD2M(&d, buf, nbuf); }
static int efilegen(Chan *c, SDunit *unit, int i, Dir *dp) { Qid q; SDfile *e; i -= SDnpart; if(unit->nefile == 0 || i >= unit->nefile) return -1; if(i < 0) return 0; e = unit->efile + i; if(emptystr(e->user)) kstrdup(&e->user, eve); mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qextra), unit->vers, QTFILE); devdir(c, q, e->name, 0, e->user, e->perm, dp); return 1; }
static Chan* ipattach(char* spec) { Chan *c; int dev; dev = atoi(spec); if(dev >= Nfs) error("bad specification"); ipgetfs(dev); c = devattach('I', spec); mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR); c->dev = dev; c->aux = newipaux(commonuser(), "none"); return c; }
static int dostat(Filsys *fs, int id, Dirtab *dir, uint8_t *buf, int nbuf, uint clock) { Dir d; d.qid.path = QID(id, dir->qid); if(dir->qid == Qsnarf) d.qid.vers = snarfversion; else d.qid.vers = 0; d.qid.type = dir->type; d.mode = dir->perm; d.length = 0; /* would be nice to do better */ d.name = dir->name; d.uid = fs->user; d.gid = fs->user; d.muid = fs->user; d.atime = clock; d.mtime = clock; return convD2M(&d, buf, nbuf); }
static int sd1gen(Chan* c, int i, Dir* dp) { Qid q; SDperm *p; switch(i){ case Qtopctl: mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE); qlock(&topctlunit.ctl); p = &topctlunit.ctlperm; if(p->user == nil || p->user[0] == 0){ kstrdup(&p->name, "sdctl"); kstrdup(&p->user, eve); p->perm = 0640; } devdir(c, q, p->name, 0, p->user, p->perm, dp); qunlock(&topctlunit.ctl); return 1; } return -1; }
static void progclose(Chan *c) { int i; Prog *f; Osenv *o; Progctl *ctl; switch(QID(c->qid)) { case Qns: case Qheap: free(c->aux); break; case Qdbgctl: if((c->flag & COPEN) == 0) return; ctl = c->aux; acquire(); closedbgctl(ctl, progpid(PID(c->qid))); release(); break; case Qwait: acquire(); i = 0; for(;;) { f = progn(i++); if(f == nil) break; o = f->osenv; if(o->waitq == c->aux) o->waitq = nil; if(o->childq == c->aux) o->childq = nil; } release(); qfree(c->aux); } }
static void newproto(char *name, int type, int maxconv) { int l; Proto *p; if(np >= MAXPROTO) { print("no %s: increase MAXPROTO", name); return; } p = &proto[np]; strcpy(p->name, name); p->stype = type; p->qid.path = QID(np, 0, Qprotodir); p->qid.type = QTDIR; p->x = np++; p->maxconv = maxconv; l = sizeof(Conv*)*(p->maxconv+1); p->conv = mallocz(l, 1); if(p->conv == 0) panic("no memory"); }
static Xfid* fsysread(Xfid *x, Fid *f) { Fcall t; uint8_t *b; int i, id, n, o, e, j, k, *ids, nids; Dirtab *d, dt; Column *c; uint clock, len; char buf[16]; if(f->qid.type & QTDIR) { if(FILE(f->qid) == Qacme) { /* empty dir */ t.data = nil; t.count = 0; respond(x, &t, nil); return x; } o = x->offset; e = x->offset+x->count; clock = getclock(); b = emalloc(messagesize); id = WIN(f->qid); n = 0; if(id > 0) d = dirtabw; else d = dirtab; d++; /* first entry is '.' */ for(i=0; d->name!=nil && i<e; i+=len) { len = dostat(WIN(x->f->qid), d, b+n, x->count-n, clock); if(len <= BIT16SZ) break; if(i >= o) n += len; d++; } if(id == 0) { qlock(&row); nids = 0; ids = nil; for(j=0; j<row.ncol; j++) { c = row.col[j]; for(k=0; k<c->nw; k++) { ids = erealloc(ids, (nids+1)*sizeof(int)); ids[nids++] = c->w[k]->id; } } qunlock(&row); qsort(ids, nids, sizeof ids[0], idcmp); j = 0; dt.name = buf; for(; j<nids && i<e; i+=len) { k = ids[j]; sprint(dt.name, "%d", k); dt.qid = QID(k, Qdir); dt.type = QTDIR; dt.perm = DMDIR|0700; len = dostat(k, &dt, b+n, x->count-n, clock); if(len == 0) break; if(i >= o) n += len; j++; } free(ids); } t.data = (char*)b; t.count = n; respond(x, &t, nil); free(b); return x; } sendp(x->c, xfidread); return nil; }
static Xfid* fsyswalk(Xfid *x, Fid *f) { Fcall t; int c, i, j, id; Qid q; uint8_t type; uint32_t path; Fid *nf; Dirtab *d, *dir; Window *w; char *err; nf = nil; w = nil; if(f->open) return respond(x, &t, "walk of open file"); if(x->fid != x->newfid) { nf = newfid(x->newfid); if(nf->busy) return respond(x, &t, "newfid already in use"); nf->busy = TRUE; nf->open = FALSE; nf->mntdir = f->mntdir; if(f->mntdir) f->mntdir->ref++; nf->dir = f->dir; nf->qid = f->qid; nf->w = f->w; nf->nrpart = 0; /* not open, so must be zero */ if(nf->w) incref(nf->w); f = nf; /* walk f */ } t.nwqid = 0; err = nil; dir = nil; id = WIN(f->qid); q = f->qid; if(x->nwname > 0) { for(i=0; i<x->nwname; i++) { if((q.type & QTDIR) == 0) { err = Enotdir; break; } if(strcmp(x->wname[i], "..") == 0) { type = QTDIR; path = Qdir; id = 0; if(w) { winclose(w); w = nil; } Accept: if(i == MAXWELEM) { err = "name too long"; break; } q.type = type; q.vers = 0; q.path = QID(id, path); t.wqid[t.nwqid++] = q; continue; } /* is it a numeric name? */ for(j=0; (c=x->wname[i][j]); j++) if(c<'0' || '9'<c) goto Regular; /* yes: it's a directory */ if(w) /* name has form 27/23; get out before losing w */ break; id = atoi(x->wname[i]); qlock(&row); w = lookid(id, FALSE); if(w == nil) { qunlock(&row); break; } incref(w); /* we'll drop reference at end if there's an error */ path = Qdir; type = QTDIR; qunlock(&row); dir = dirtabw; goto Accept; Regular: // if(FILE(f->qid) == Qacme) /* empty directory */ // break; if(strcmp(x->wname[i], "new") == 0) { if(w) error("w set in walk to new"); sendp(cnewwindow, nil); /* signal newwindowthread */ w = recvp(cnewwindow); /* receive new window */ incref(w); type = QTDIR; path = QID(w->id, Qdir); id = w->id; dir = dirtabw; goto Accept; } if(id == 0) d = dirtab; else d = dirtabw; d++; /* skip '.' */ for(; d->name; d++) if(strcmp(x->wname[i], d->name) == 0) { path = d->qid; type = d->type; dir = d; goto Accept; } break; /* file not found */ } if(i==0 && err == nil) err = Eexist; } if(err!=nil || t.nwqid<x->nwname) { if(nf) { nf->busy = FALSE; fsysdelid(nf->mntdir); } } else if(t.nwqid == x->nwname) { if(w) { f->w = w; w = nil; /* don't drop the reference */ } if(dir) f->dir = dir; f->qid = q; } if(w != nil) winclose(w); return respond(x, &t, err); }
static int loopbackgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp) { Dirtab *tab; int len, type; Qid qid; type = TYPE(c->qid.path); if(i == DEVDOTDOT){ switch(type){ case Qtopdir: case Qloopdir: snprint(up->genbuf, sizeof(up->genbuf), "#X%ld", c->dev); mkqid(&qid, QID(0, Qtopdir), 0, QTDIR); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); break; case Qportdir: snprint(up->genbuf, sizeof(up->genbuf), "loopback%ld", c->dev); mkqid(&qid, QID(0, Qloopdir), 0, QTDIR); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); break; default: panic("loopbackgen %llux", c->qid.path); } return 1; } switch(type){ case Qtopdir: if(i != 0) return -1; snprint(up->genbuf, sizeof(up->genbuf), "loopback%ld", c->dev); mkqid(&qid, QID(0, Qloopdir), 0, QTDIR); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); return 1; case Qloopdir: if(i >= 2) return -1; snprint(up->genbuf, sizeof(up->genbuf), "%d", i); mkqid(&qid, QID(i, QID(0, Qportdir)), 0, QTDIR); devdir(c, qid, up->genbuf, 0, eve, 0555, dp); return 1; case Qportdir: if(i >= nelem(loopportdir)) return -1; tab = &loopportdir[i]; mkqid(&qid, QID(ID(c->qid.path), tab->qid.path), 0, QTFILE); devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp); return 1; default: /* non directory entries end up here; must be in lowest level */ if(c->qid.type & QTDIR) panic("loopbackgen: unexpected directory"); if(i != 0) return -1; tab = &loopdirs[type]; if(tab == nil) panic("loopbackgen: unknown type: %d", type); len = tab->length; devdir(c, c->qid, tab->name, len, eve, tab->perm, dp); return 1; } }
static Chan* loopbackattach(char *spec) { Loop *volatile lb; Queue *q; Chan *c; int chan; int dev; dev = 0; if(spec != nil){ dev = atoi(spec); if(dev >= Nloopbacks) error(Ebadspec); } c = devattach('X', spec); if(waserror()){ chanfree(c); nexterror(); } lb = &loopbacks[dev]; qlock(lb); if(waserror()){ lb->ref--; qunlock(lb); nexterror(); } lb->ref++; if(lb->ref == 1){ for(chan = 0; chan < 2; chan++){ lb->link[chan].ci.mode = Trelative; lb->link[chan].ci.a = &lb->link[chan]; lb->link[chan].ci.f = linkintr; lb->link[chan].limit = Loopqlim; q = qopen(lb->link[chan].limit, 0, 0, 0); lb->link[chan].iq = q; if(q == nil){ freelb(lb); exhausted("memory"); } q = qopen(lb->link[chan].limit, 0, 0, 0); lb->link[chan].oq = q; if(q == nil){ freelb(lb); exhausted("memory"); } lb->link[chan].indrop = 1; lb->link[chan].delaynns = Delayn; lb->link[chan].delay0ns = Delay0; } } poperror(); qunlock(lb); poperror(); mkqid(&c->qid, QID(0, Qtopdir), 0, QTDIR); c->aux = lb; c->dev = dev; return c; }
static int aoegen(Chan *c, char *, Dirtab *, int, int s, Dir *dp) { int i; Aoedev *d; Qid q; if(c->qid.path == 0){ switch(s){ case DEVDOTDOT: q.path = 0; q.type = QTDIR; devdir(c, q, "#æ", 0, eve, 0555, dp); break; case 0: q.path = Qtopdir; q.type = QTDIR; devdir(c, q, "aoe", 0, eve, 0555, dp); break; default: return -1; } return 1; } switch(TYPE(c->qid)){ default: return -1; case Qtopdir: if(s == DEVDOTDOT){ mkqid(&q, Qzero, 0, QTDIR); devdir(c, q, "aoe", 0, eve, 0555, dp); return 1; } if(s < Qtopfiles) return topgen(c, Qtopbase + s, dp); s -= Qtopfiles; if(s >= units.ref) return -1; mkqid(&q, QID(s, Qunitdir), 0, QTDIR); d = unit2dev(s); assert(d != nil); devdir(c, q, unitname(d), 0, eve, 0555, dp); return 1; case Qtopctl: case Qtoplog: return topgen(c, TYPE(c->qid), dp); case Qunitdir: if(s == DEVDOTDOT){ mkqid(&q, QID(0, Qtopdir), 0, QTDIR); uprint("%uld", UNIT(c->qid)); devdir(c, q, up->genbuf, 0, eve, 0555, dp); return 1; } return unitgen(c, Qunitbase+s, dp); case Qctl: case Qdata: case Qconfig: case Qident: return unitgen(c, TYPE(c->qid), dp); case Qdevlinkdir: i = UNIT(c->qid); if(s == DEVDOTDOT){ mkqid(&q, QID(i, Qunitdir), 0, QTDIR); devdir(c, q, "devlink", 0, eve, 0555, dp); return 1; } if(i >= units.ref) return -1; d = unit2dev(i); if(s >= d->ndl) return -1; uprint("%d", s); mkqid(&q, Q3(s, i, Qdevlink), 0, QTFILE); devdir(c, q, up->genbuf, 0, eve, 0755, dp); return 1; case Qdevlink: uprint("%d", s); mkqid(&q, Q3(s, UNIT(c->qid), Qdevlink), 0, QTFILE); devdir(c, q, up->genbuf, 0, eve, 0755, dp); return 1; } }
int devsfgen(Chan *c, char *name, Dirtab *tab, int x, int s, Dir *dp) { int t; Qid q; ulong path; Engine *E = (Engine *)c->aux; USED(name); USED(tab); USED(x); q.vers = 0; if (s == DEVDOTDOT) { switch(QID(c->qid)) { case Qtopdir: case Qmroot: mkqid(&q, Qtopdir, 0, QTDIR); devdir(c, q, "#j", 0, eve, 0500, dp); break; case Qdir: mkqid(&q, Qmroot, 0, QTDIR); devdir(c, q, up->genbuf, 0, eve, 0500, dp); break; default: panic("devsunflowerwalk %llux", c->qid.path); return -1; } return 1; } /* Top level directory (say, /dev) */ t = QID(c->qid); if (t == Qtopdir) { snprint(mname, MAX_MNAME, "sunflower.%s", E->attachspec); switch(s) { case 0: mkqid(&q, Qmroot, 0, QTDIR); devdir(c, q, mname, 0, eve, 0555, dp); break; default: return -1; } return 1; } /* Second level (say /dev/sunflower) */ if (t == Qmroot || t == Qmctl || t == Qminfo || t == Qnetin || t == Qnetout) { switch (s) { case 0: mkqid(&q, Qmctl, 0, QTFILE); devdir(c, q, "ctl", 0, eve, 0200, dp); break; case 1: mkqid(&q, Qminfo, 0, QTFILE); devdir(c, q, "info", 0, eve, 0400, dp); break; case 2: mkqid(&q, Qnetin, 0, QTFILE); devdir(c, q, "netin", 0, eve, 0222, dp); break; case 3: mkqid(&q, Qnetout, 0, QTFILE); devdir(c, q, "netout", 0, eve, 0444, dp); break; default: if (s <= 2*E->nnodes+3) { int n = s-4; int id = n >> 1; if (n & 1) { sprint(up->genbuf, "%d.%d", (E->sp[id])->NODE_ID, (E->sp[id])->runnable); } else { sprint(up->genbuf, "%d", (E->sp[id])->NODE_ID); } mkqid(&q, (id << QSHIFT)|Qdir, 0, QTDIR); devdir(c, q, up->genbuf, 0, eve, 0555, dp); return 1; } else { return -1; } }
static int cmdgen(Chan *c, char *name, Dirtab *d, int nd, int s, Dir *dp) { Qid q; Conv *cv; USED(name); USED(nd); USED(d); if(s == DEVDOTDOT){ switch(TYPE(c->qid)){ case Qtopdir: case Qcmd: mkqid(&q, QID(0, Qtopdir), 0, QTDIR); devdir(c, q, "#C", 0, eve, DMDIR|0555, dp); break; case Qconvdir: mkqid(&q, QID(0, Qcmd), 0, QTDIR); devdir(c, q, "cmd", 0, eve, DMDIR|0555, dp); break; default: panic("cmdgen %llux", c->qid.path); } return 1; } switch(TYPE(c->qid)) { case Qtopdir: if(s >= 1) return -1; mkqid(&q, QID(0, Qcmd), 0, QTDIR); devdir(c, q, "cmd", 0, "cmd", DMDIR|0555, dp); return 1; case Qcmd: if(s < cmd.nc) { cv = cmd.conv[s]; mkqid(&q, QID(s, Qconvdir), 0, QTDIR); sprint(up->genbuf, "%d", s); devdir(c, q, up->genbuf, 0, cv->owner, DMDIR|0555, dp); return 1; } s -= cmd.nc; if(s == 0){ mkqid(&q, QID(0, Qclonus), 0, QTFILE); devdir(c, q, "clone", 0, "cmd", 0666, dp); return 1; } return -1; case Qclonus: if(s == 0){ mkqid(&q, QID(0, Qclonus), 0, QTFILE); devdir(c, q, "clone", 0, "cmd", 0666, dp); return 1; } return -1; case Qconvdir: return cmd3gen(c, Qconvbase+s, dp); case Qdata: case Qstderr: case Qctl: case Qstatus: case Qwait: return cmd3gen(c, TYPE(c->qid), dp); } return -1; }