#include <9pm/u.h> #include <9pm/libc.h> #include <9pm/fcall.h> #include <9pm/ns.h> /* Qid is (2*fd + (file is ctl))+1 */ static int dupqidgen(Qid *qid, int s) { Chan *c; if(s == DEVDOTDOT || s == DEVDOT) return 1; s--; if(waserror()) return -1; c = fd2chan(s/2, -1); cclose(c); poperror(); mkqid(qid, s+1, 0, QTFILE); return 1; } static int dupqidstat(Qid q, uchar *edir, int nedir) { int fd; char buf[20]; Chan *c; Dir d; static int perm[] = { 0400, 0200, 0600, 0 }; devdir(&d); d.qid = q; switch((long)q.path){ case 0: d.name = "/"; d.mode = DMDIR|0555; break; default: fd = (q.path-1)/2; if((q.path-1)&1){ d.mode = 0400; sprint(buf, "%dctl", fd); }else{ if(!waserror()){ c = fd2chan(fd, -1); cclose(c); poperror(); d.mode = perm[c->omode]; }else d.mode = 0600; sprint(buf, "%d", fd); } d.name = buf; break; } return convD2M(&d, edir, nedir); } static int dupgen(Qid q, int i, uchar *edir, int nedir) { switch(dupqidgen(&q, i)){ case -1: return -1; case 0: return 0; default: return dupqidstat(q, edir, nedir); } } static Chan* dupopen(Chan *c, Mnt *mnt, char *path, int omode) { Chan *f; int fd, twicefd; c->qid = devqid(mnt, path); if(c->qid.type & QTDIR){ if(omode != 0) error(Eisdir); c->omode = 0; return c; } if(c->qid.type & QTAUTH) error(Eperm); twicefd = c->qid.path - 1; fd = twicefd/2; if((twicefd & 1) == 0){ /* fd file */ f = fd2chan(fd, omode); cclose(c); c = f; } return c; } static int procqidwidth(Chan *c) { char buf[32]; return sprint(buf, "%lud", c->qid.vers); } int procfdprint(Chan *c, int fd, int w, char *s, int ns) { int n; if(w == 0) w = procqidwidth(c); n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n", fd, &"r w rw"[(c->omode&3)<<1], c->mnt->dev->dc, c->mnt->id, c->qid.path, w, c->qid.vers, c->qid.type, c->iounit, c->offset, c->path); return n; } static long duppread(Chan *c, void *va, long n, vlong offset) { char *a = va; char buf[256]; int fd, twicefd; if(c->qid.type == QTDIR) return devdirread(c, a, n, offset); twicefd = c->qid.path - 1; fd = twicefd/2; if(twicefd & 1){ c = fd2chan(fd, -1); procfdprint(c, fd, 0, buf, sizeof buf); cclose(c); return readstr(offset, va, n, buf); } error("dupread"); return 0; } static long duppwrite(Chan *c, void *va, long n, vlong offset) { USED(c); USED(va); USED(n); USED(offset); error("duppwrite"); return -1; } Dev devdup = { (Rune)'d', devchdir, devclunk, devcreate, devfstat, devfwstat, dupopen, duppread, duppwrite, devread, devremove, devseek, devstat, devwrite, devwstat, devattach, devserves, dupgen, };