summaryrefslogtreecommitdiff
path: root/sys/src/cmd/srvold9p/fcall.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/srvold9p/fcall.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/srvold9p/fcall.c')
-rwxr-xr-xsys/src/cmd/srvold9p/fcall.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/sys/src/cmd/srvold9p/fcall.c b/sys/src/cmd/srvold9p/fcall.c
new file mode 100755
index 000000000..a3e007330
--- /dev/null
+++ b/sys/src/cmd/srvold9p/fcall.c
@@ -0,0 +1,150 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include "9p1.h"
+
+#define MAXFDATA (8*1024)
+#define MAXRPC (MAXFDATA+160)
+
+/*
+ * reassemble 9P messages for stream based protocols
+ * interposed between devmnt and the network by srv for tcp connections
+ * fcall expects devmnt on fd0, network fd1
+ */
+uchar msglen[256] =
+{
+ [Tnop9p1] 3,
+ [Rnop9p1] 3,
+ [Tsession9p1] 3+CHALLEN,
+ [Rsession9p1] 3+NAMEREC+DOMLEN+CHALLEN,
+ [Terror9p1] 0,
+ [Rerror9p1] 67,
+ [Tflush9p1] 5,
+ [Rflush9p1] 3,
+ [Tattach9p1] 5+2*NAMEREC+TICKETLEN+AUTHENTLEN,
+ [Rattach9p1] 13+AUTHENTLEN,
+ [Tclone9p1] 7,
+ [Rclone9p1] 5,
+ [Twalk9p1] 33,
+ [Rwalk9p1] 13,
+ [Topen9p1] 6,
+ [Ropen9p1] 13,
+ [Tcreate9p1] 38,
+ [Rcreate9p1] 13,
+ [Tread9p1] 15,
+ [Rread9p1] 8,
+ [Twrite9p1] 16,
+ [Rwrite9p1] 7,
+ [Tclunk9p1] 5,
+ [Rclunk9p1] 5,
+ [Tremove9p1] 5,
+ [Rremove9p1] 5,
+ [Tstat9p1] 5,
+ [Rstat9p1] 121,
+ [Twstat9p1] 121,
+ [Rwstat9p1] 5,
+ [Tclwalk9p1] 35,
+ [Rclwalk9p1] 13,
+};
+
+enum
+{
+ Twritehdr = 16, /* Min bytes for Twrite */
+ Rreadhdr = 8, /* Min bytes for Rread */
+ Twritecnt = 13, /* Offset in byte stream of write count */
+ Rreadcnt = 5, /* Offset for Readcnt */
+};
+
+int
+mntrpclen(uchar *d, int n)
+{
+ uchar t;
+ int len, off;
+
+ if(n < 1)
+ return 0;
+
+ t = d[0];
+ switch(t) { /* This is the type */
+ default:
+ len = msglen[t];
+ if(len == 0) /* Illegal type so consume */
+ return n;
+ if(n < len)
+ return 0;
+ return len;
+ case Twrite9p1: /* Fmt: TGGFFOOOOOOOOCC */
+ len = Twritehdr; /* T = type, G = tag, F = fid */
+ off = Twritecnt; /* O = offset, C = count */
+ break;
+ case Rread9p1: /* Fmt: TGGFFCC */
+ len = Rreadhdr;
+ off = Rreadcnt;
+ break;
+ }
+ if(n < off+2)
+ return 0;
+
+ len += d[off]|(d[off+1]<<8);
+ if(n < len)
+ return 0;
+
+ return len;
+}
+
+int
+fcall(int fd)
+{
+ int i, r, n, l;
+ uchar *p, *buf;
+ int pipefd[2];
+
+ if(pipe(pipefd) < 0)
+ fatal("fcall pipe: %r");
+
+ buf = malloc(MAXRPC);
+ if(buf == nil)
+ fatal("fcall malloc");
+
+ switch(rfork(RFPROC|RFMEM|RFFDG|RFCNAMEG)){
+ default:
+ return pipefd[0]; /* parent returns fd */
+ case 0:
+ break; /* child builds buffers */
+ case -1:
+ fatal("fcall fork: %r");
+ }
+
+ /* close file descriptors */
+ for(i=0; i<20; i++)
+ if(i!=fd && i!=pipefd[1])
+ close(i);
+
+ l = MAXRPC;
+ p = buf;
+ for(;;) {
+ n = read(fd, p, l);
+ if(n < 0)
+ break;
+ p += n;
+ l -= n;
+
+ for(;;) {
+ r = mntrpclen(buf, p - buf);
+ if(r == 0)
+ break;
+
+ if(write(pipefd[1], buf, r) < 0)
+ break;
+
+ n = (p - buf) - r;
+ memmove(buf, buf+r, n);
+ p = buf+n;
+ l = MAXRPC - n;
+ }
+ }
+ close(pipefd[1]);
+ fatal(nil);
+ return -1;
+}