blob: ec133c821835f90e750720a6baa0dad825defd71 [file] [log] [blame]
rsc4f604b12004-06-09 14:04:33 +00001#include <u.h>
2#include <libc.h>
3#include <fcall.h>
rscb4e8c4b2005-01-04 22:21:23 +00004#include <9pclient.h>
rsc4f604b12004-06-09 14:04:33 +00005#include "plumb.h"
6
rscb4e8c4b2005-01-04 22:21:23 +00007static CFsys *fsplumb;
rsc4f604b12004-06-09 14:04:33 +00008static int pfd = -1;
rscb4e8c4b2005-01-04 22:21:23 +00009static CFid *pfid;
rsc4f604b12004-06-09 14:04:33 +000010
11int
rsc1dc6e082006-06-25 23:55:37 +000012plumbunmount(void)
13{
14 CFsys *fsys;
15
16 if(fsplumb){
17 fsys = fsplumb;
18 fsplumb = nil;
19 fsunmount(fsys);
20 }
21 return 0;
22}
23
24int
rsc4f604b12004-06-09 14:04:33 +000025plumbopen(char *name, int omode)
26{
27 if(fsplumb == nil)
28 fsplumb = nsmount("plumb", "");
29 if(fsplumb == nil)
30 return -1;
31 /*
32 * It's important that when we send something,
33 * we find out whether it was a valid plumb write.
34 * (If it isn't, the client might fall back to some
35 * other mechanism or indicate to the user what happened.)
36 * We can't use a pipe for this, so we have to use the
37 * fid interface. But we need to return a fd.
38 * Return a fd for /dev/null so that we return a unique
39 * file descriptor. In plumbsend we'll look for pfd
40 * and use the recorded fid instead.
41 */
42 if((omode&3) == OWRITE){
43 if(pfd != -1){
44 werrstr("already have plumb send open");
45 return -1;
46 }
47 pfd = open("/dev/null", OWRITE);
48 if(pfd < 0)
49 return -1;
50 pfid = fsopen(fsplumb, name, omode);
51 if(pfid == nil){
52 close(pfd);
53 pfd = -1;
54 return -1;
55 }
56 return pfd;
57 }
58
59 return fsopenfd(fsplumb, name, omode);
60}
61
rscb4e8c4b2005-01-04 22:21:23 +000062CFid*
rsc4f604b12004-06-09 14:04:33 +000063plumbopenfid(char *name, int mode)
64{
rsc57d7df42005-03-18 19:04:28 +000065 if(fsplumb == nil){
rsc4f604b12004-06-09 14:04:33 +000066 fsplumb = nsmount("plumb", "");
rsc57d7df42005-03-18 19:04:28 +000067 if(fsplumb == nil){
68 werrstr("mount plumb: %r");
69 return nil;
70 }
71 }
rsc4f604b12004-06-09 14:04:33 +000072 return fsopen(fsplumb, name, mode);
73}
74
75int
rscb4e8c4b2005-01-04 22:21:23 +000076plumbsendtofid(CFid *fid, Plumbmsg *m)
rsc4f604b12004-06-09 14:04:33 +000077{
78 char *buf;
79 int n;
80
81 if(fid == nil){
82 werrstr("invalid fid");
83 return -1;
84 }
85 buf = plumbpack(m, &n);
86 if(buf == nil)
87 return -1;
88 n = fswrite(fid, buf, n);
89 free(buf);
90 return n;
91}
92
93int
94plumbsend(int fd, Plumbmsg *m)
95{
96 if(fd == -1){
97 werrstr("invalid fd");
98 return -1;
99 }
100 if(fd != pfd){
101 werrstr("fd is not the plumber");
102 return -1;
103 }
104 return plumbsendtofid(pfid, m);
105}
106
107Plumbmsg*
108plumbrecv(int fd)
109{
110 char *buf;
111 Plumbmsg *m;
112 int n, more;
113
114 buf = malloc(8192);
115 if(buf == nil)
116 return nil;
117 n = read(fd, buf, 8192);
118 m = nil;
119 if(n > 0){
120 m = plumbunpackpartial(buf, n, &more);
121 if(m==nil && more>0){
122 /* we now know how many more bytes to read for complete message */
123 buf = realloc(buf, n+more);
124 if(buf == nil)
125 return nil;
126 if(readn(fd, buf+n, more) == more)
127 m = plumbunpackpartial(buf, n+more, nil);
128 }
129 }
130 free(buf);
131 return m;
132}
133
134Plumbmsg*
rscb4e8c4b2005-01-04 22:21:23 +0000135plumbrecvfid(CFid *fid)
rsc4f604b12004-06-09 14:04:33 +0000136{
137 char *buf;
138 Plumbmsg *m;
139 int n, more;
140
141 buf = malloc(8192);
142 if(buf == nil)
143 return nil;
144 n = fsread(fid, buf, 8192);
145 m = nil;
146 if(n > 0){
147 m = plumbunpackpartial(buf, n, &more);
148 if(m==nil && more>0){
149 /* we now know how many more bytes to read for complete message */
150 buf = realloc(buf, n+more);
151 if(buf == nil)
152 return nil;
153 if(fsreadn(fid, buf+n, more) == more)
154 m = plumbunpackpartial(buf, n+more, nil);
155 }
156 }
157 free(buf);
158 return m;
159}
160