#include #include #include #include #include #include #include <9p.h> ulong messagesize = IOHDRSZ+8192; int subfd; int old9p = -1; uchar* rxbuf; uchar* txbuf; void usage(void) { fprint(2, "usage: substfs [...] /srv/service | -c command | -n networkaddress\n"); exits("usage"); } void* emalloc(ulong n) { void *p; p = malloc(n); if(p == 0) sysfatal("malloc(%ld) fails", (long)n); memset(p, 0, n); return p; } void getfcallnew(int fd, Fcall *fc, int have) { int len; if(have > BIT32SZ) sysfatal("cannot happen: %r"); if(have < BIT32SZ && readn(fd, rxbuf+have, BIT32SZ-have) != BIT32SZ-have) sysfatal("couldn't read message: %r"); len = GBIT32(rxbuf); if(len <= BIT32SZ) sysfatal("bogus message"); len -= BIT32SZ; if(readn(fd, rxbuf+BIT32SZ, len) != len) sysfatal("short message: %r"); if(convM2S(rxbuf, len+BIT32SZ, fc) != len+BIT32SZ) sysfatal("badly sized message type %d: %r", rxbuf[0]); } void putfcallnew(int wfd, Fcall *tx) { ulong n; if((n = convS2M(tx, txbuf, messagesize)) == 0) sysfatal("couldn't format message type %d: %r", tx->type); fprint(2, "substfs: %F\n", tx); if(write(wfd, txbuf, n) != n) sysfatal("couldn't send message: %r"); } void getfcall(int fd, Fcall *fc) { //getfcallnew(fd, fc, 0); int res; res = read9pmsg(fd, rxbuf, messagesize); if (res < 0) { fprint(2, "%s", rxbuf); sysfatal("couldn't read message: %r"); } if (res == 0) sysfatal("end of file on fd"); if(convM2S(rxbuf, messagesize, fc) == 0) sysfatal("badly sized message type %d: %r", rxbuf[0]); fprint(2, "substfs: %F\n", fc); } static void handle(Req* r) { fprint(2, "substfs: putfcallnew...\n"); putfcallnew(subfd, &r->ifcall); fprint(2, "substfs: putfcallnew... done\n"); fprint(2, "substfs: getfcall... \n"); getfcall(subfd, &r->ofcall); fprint(2, "substfs: getfcall... done\n"); if(r->ofcall.type == Rerror) respond(r, r->ofcall.ename); else if (r->ofcall.type == Rstat) { if(convM2D(r->ofcall.stat, r->ofcall.nstat, &r->d, (char*)r->ofcall.stat) != r->ofcall.nstat) respond(r, "error bad dir"); else { // hack to avoid too much freeing r->d.name = strdup(r->d.name); r->d.uid = strdup(r->d.uid); r->d.gid = strdup(r->d.gid); r->d.muid = strdup(r->d.muid); if(r->d.mode & DMDIR) r->fid->qid.type |= QTDIR; if(r->d.mode & DMAPPEND) r->fid->qid.type |= QTAPPEND; if(r->d.mode & DMEXCL) r->fid->qid.type |= QTEXCL; respond(r, nil); } } else respond(r, nil); } Srv substsrv = { //.destroyfid = won't work because we need the req! .attach= handle, .auth= handle, .open= handle, .create= handle, .read= handle, .write= handle, .remove= handle, .flush= handle, .stat= handle, .wstat= handle, .walk= handle, }; int connectcmd(char *cmd) { int p[2]; if(pipe(p) < 0) return -1; switch(fork()){ case -1: fprint(2, "fork failed: %r\n"); _exits("exec"); case 0: dup(p[0], 0); dup(p[0], 1); close(p[1]); execl("/bin/rc", "rc", "-c", cmd, nil); fprint(2, "exec failed: %r\n"); _exits("exec"); default: close(p[0]); return p[1]; } } void main(int argc, char **argv) { char *mtpt, *service; int cmd, net; int sfd[2]; mtpt = nil; service = nil; cmd = 0; net = 0; ARGBEGIN{ case 'D': chatty9p++; break; case 's': service = EARGF(usage()); break; case 'm': mtpt = EARGF(usage()); break; case 'c': cmd = 1; break; case 'n': net = 1; break; default: usage(); }ARGEND if(argc != 1) usage(); fmtinstall('F', fcallfmt); rxbuf = emalloc(messagesize); txbuf = emalloc(messagesize); if(cmd && net) usage(); if(cmd) subfd = connectcmd(argv[0]); else if(net){ subfd = dial(netmkaddr(argv[0], "net", "9fs"), 0, 0, 0); if(subfd < 0) sysfatal("dial: %r"); }else{ subfd = open(argv[0], ORDWR); if(subfd < 0) sysfatal("open: %r"); } //postmountsrv(&substsrv, service, mtpt, MREPL); //exits(nil); if(pipe(sfd) < 0) sysfatal("pipe: %r"); if(service) if(postfd(service, sfd[0]) < 0) sysfatal("postfd %s: %r", service); substsrv.infd = sfd[1]; substsrv.outfd = sfd[1]; srv(&substsrv); }