#include <u.h>
#include <libc.h>
#include <bio.h>
#include <auth.h>
#include <fcall.h>
#include <thread.h>
#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);
}
|