/* * Reconstruct original message, for error diagnostic */ void cmderror(struct cmdbuf *cb, char *s) { int i; char *p, *e; p = get_cur_genbuf(); e = p + GENBUF_SZ - 10; p = seprintf(p, e, "%s \"", s); for (i = 0; i < cb->nf; i++) { if (i > 0) p = seprintf(p, e, " "); p = seprintf(p, e, "%s", cb->f[i]); } seprintf(p, e, "\""); error(EFAIL, get_cur_genbuf()); }
/* * generate a 3 level directory */ static int netifgen(struct chan *c, char *unused_char_p_t, struct dirtab *vp, int unused_int, int i, struct dir *dp) { struct qid q; struct ether *nif = (struct ether *)vp; struct netfile *f; int perm; char *o; q.type = QTFILE; q.vers = 0; /* top level directory contains the name of the network */ if (c->qid.path == 0) { switch (i) { case DEVDOTDOT: q.path = 0; q.type = QTDIR; devdir(c, q, ".", 0, eve, 0555, dp); break; case 0: q.path = N2ndqid; q.type = QTDIR; strncpy(get_cur_genbuf(), nif->name, GENBUF_SZ); devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp); break; default: return -1; } return 1; } /* second level contains clone plus all the conversations. * * This ancient comment is from plan9. Inferno and nxm both had issues * here. You couldn't ls /net/ether0/ when it didn't have any convs. There * were also issues with nxm where you couldn't stat ether0/x/stats * properly. * * The issue is that if we handle things like Nstatqid, then we will never * pass it down to the third level. And since we just set the path == * Nstatqid, we won't have the NETID muxed in. If someone isn't trying to * generate a chan, but instead is looking it up (devwalk generates, devstat * already has the chan), then they are also looking for a devdir with path * containing ID << 5. So if you stat ether0/1/ifstats, devstat is looking * for path 41, but we return path 9 (41 = 32 + 9). (these numbers are * before we tracked NETID + 1). * * We (akaros and plan9) had a big if here, that would catch things that do * not exist in the subdirs of a netif. Things like clone make sense here. * I guess addr too, though that seems to be added since the original * comment. You can see what the 3rd level was expecting to parse by looking * farther down in the code. * * The root of the problem was that the old code couldn't tell the * difference between no netid and netid 0. Now, we determine if we're at * the second level by the lack of a netid, instead of trying to enumerate * the qid types that the second level could have. The latter approach * allowed for something like ether0/1/stats, but we couldn't actually * devstat ether0/stats directly. It's worth noting that there is no * difference to the content of ether0/stats and ether0/x/stats (when you * read), but they have different chan qids. * * Here's the old if block: t = NETTYPE(c->qid.path); if (t == N2ndqid || t == Ncloneqid || t == Naddrqid) { */ if (NETID(c->qid.path) == -1) { switch (i) { case DEVDOTDOT: q.type = QTDIR; q.path = 0; devdir(c, q, ".", 0, eve, DMDIR | 0555, dp); break; case 0: q.path = Ncloneqid; devdir(c, q, "clone", 0, eve, 0666, dp); break; case 1: q.path = Naddrqid; devdir(c, q, "addr", 0, eve, 0666, dp); break; case 2: q.path = Nstatqid; devdir(c, q, "stats", 0, eve, 0444, dp); break; case 3: q.path = Nifstatqid; devdir(c, q, "ifstats", 0, eve, 0444, dp); break; default: i -= 4; if (i >= nif->nfile) return -1; if (nif->f[i] == 0) return 0; q.type = QTDIR; q.path = NETQID(i, N3rdqid); snprintf(get_cur_genbuf(), GENBUF_SZ, "%d", i); devdir(c, q, get_cur_genbuf(), 0, eve, DMDIR | 0555, dp); break; } return 1; } /* third level */ f = nif->f[NETID(c->qid.path)]; if (f == 0) return 0; if (*f->owner) { o = f->owner; perm = f->mode; } else { o = eve; perm = 0666; } switch (i) { case DEVDOTDOT: q.type = QTDIR; q.path = N2ndqid; strncpy(get_cur_genbuf(), nif->name, GENBUF_SZ); devdir(c, q, get_cur_genbuf(), 0, eve, DMDIR | 0555, dp); break; case 0: q.path = NETQID(NETID(c->qid.path), Ndataqid); devdir(c, q, "data", 0, o, perm, dp); break; case 1: q.path = NETQID(NETID(c->qid.path), Nctlqid); devdir(c, q, "ctl", 0, o, perm, dp); break; case 2: q.path = NETQID(NETID(c->qid.path), Nstatqid); devdir(c, q, "stats", 0, eve, 0444, dp); break; case 3: q.path = NETQID(NETID(c->qid.path), Ntypeqid); devdir(c, q, "type", 0, eve, 0444, dp); break; case 4: q.path = NETQID(NETID(c->qid.path), Nifstatqid); devdir(c, q, "ifstats", 0, eve, 0444, dp); break; default: return -1; } return 1; }