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 plumbopen(char *name, int omode)
13 {
14 if(fsplumb == nil)
15 fsplumb = nsmount("plumb", "");
16 if(fsplumb == nil)
17 return -1;
18 /*
19 * It's important that when we send something,
20 * we find out whether it was a valid plumb write.
21 * (If it isn't, the client might fall back to some
22 * other mechanism or indicate to the user what happened.)
23 * We can't use a pipe for this, so we have to use the
24 * fid interface. But we need to return a fd.
25 * Return a fd for /dev/null so that we return a unique
26 * file descriptor. In plumbsend we'll look for pfd
27 * and use the recorded fid instead.
28 */
29 if((omode&3) == OWRITE){
30 if(pfd != -1){
31 werrstr("already have plumb send open");
32 return -1;
33 }
34 pfd = open("/dev/null", OWRITE);
35 if(pfd < 0)
36 return -1;
37 pfid = fsopen(fsplumb, name, omode);
38 if(pfid == nil){
39 close(pfd);
40 pfd = -1;
41 return -1;
42 }
43 return pfd;
44 }
46 return fsopenfd(fsplumb, name, omode);
47 }
49 CFid*
50 plumbopenfid(char *name, int mode)
51 {
52 if(fsplumb == nil){
53 fsplumb = nsmount("plumb", "");
54 if(fsplumb == nil){
55 werrstr("mount plumb: %r");
56 return nil;
57 }
58 }
59 return fsopen(fsplumb, name, mode);
60 }
62 int
63 plumbsendtofid(CFid *fid, Plumbmsg *m)
64 {
65 char *buf;
66 int n;
68 if(fid == nil){
69 werrstr("invalid fid");
70 return -1;
71 }
72 buf = plumbpack(m, &n);
73 if(buf == nil)
74 return -1;
75 n = fswrite(fid, buf, n);
76 free(buf);
77 return n;
78 }
80 int
81 plumbsend(int fd, Plumbmsg *m)
82 {
83 if(fd == -1){
84 werrstr("invalid fd");
85 return -1;
86 }
87 if(fd != pfd){
88 werrstr("fd is not the plumber");
89 return -1;
90 }
91 return plumbsendtofid(pfid, m);
92 }
94 Plumbmsg*
95 plumbrecv(int fd)
96 {
97 char *buf;
98 Plumbmsg *m;
99 int n, more;
101 buf = malloc(8192);
102 if(buf == nil)
103 return nil;
104 n = read(fd, buf, 8192);
105 m = nil;
106 if(n > 0){
107 m = plumbunpackpartial(buf, n, &more);
108 if(m==nil && more>0){
109 /* we now know how many more bytes to read for complete message */
110 buf = realloc(buf, n+more);
111 if(buf == nil)
112 return nil;
113 if(readn(fd, buf+n, more) == more)
114 m = plumbunpackpartial(buf, n+more, nil);
117 free(buf);
118 return m;
121 Plumbmsg*
122 plumbrecvfid(CFid *fid)
124 char *buf;
125 Plumbmsg *m;
126 int n, more;
128 buf = malloc(8192);
129 if(buf == nil)
130 return nil;
131 n = fsread(fid, buf, 8192);
132 m = nil;
133 if(n > 0){
134 m = plumbunpackpartial(buf, n, &more);
135 if(m==nil && more>0){
136 /* we now know how many more bytes to read for complete message */
137 buf = realloc(buf, n+more);
138 if(buf == nil)
139 return nil;
140 if(fsreadn(fid, buf+n, more) == more)
141 m = plumbunpackpartial(buf, n+more, nil);
144 free(buf);
145 return m;