Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4 #include <9pclient.h>
5 #include "plumb.h"
7 static CFsys *fsplumb;
8 static int pfd = -1;
9 static CFid *pfid;
11 int
12 plumbunmount(void)
13 {
14 CFsys *fsys;
16 if(fsplumb){
17 fsys = fsplumb;
18 fsplumb = nil;
19 fsunmount(fsys);
20 }
21 return 0;
22 }
24 int
25 plumbopen(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 }
59 return fsopenfd(fsplumb, name, omode);
60 }
62 CFid*
63 plumbopenfid(char *name, int mode)
64 {
65 if(fsplumb == nil){
66 fsplumb = nsmount("plumb", "");
67 if(fsplumb == nil){
68 werrstr("mount plumb: %r");
69 return nil;
70 }
71 }
72 return fsopen(fsplumb, name, mode);
73 }
75 int
76 plumbsendtofid(CFid *fid, Plumbmsg *m)
77 {
78 char *buf;
79 int n;
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 }
93 int
94 plumbsend(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;
104 return plumbsendtofid(pfid, m);
107 Plumbmsg*
108 plumbrecv(int fd)
110 char *buf;
111 Plumbmsg *m;
112 int n, more;
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);
130 free(buf);
131 return m;
134 Plumbmsg*
135 plumbrecvfid(CFid *fid)
137 char *buf;
138 Plumbmsg *m;
139 int n, more;
141 if(fid == nil){
142 werrstr("invalid fid");
143 return nil;
145 buf = malloc(8192);
146 if(buf == nil)
147 return nil;
148 n = fsread(fid, buf, 8192);
149 m = nil;
150 if(n > 0){
151 m = plumbunpackpartial(buf, n, &more);
152 if(m==nil && more>0){
153 /* we now know how many more bytes to read for complete message */
154 buf = realloc(buf, n+more);
155 if(buf == nil)
156 return nil;
157 if(fsreadn(fid, buf+n, more) == more)
158 m = plumbunpackpartial(buf, n+more, nil);
161 free(buf);
162 return m;