Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4 #include <fs.h>
5 #include "plumb.h"
7 static Fsys *fsplumb;
8 static int pfd = -1;
9 static Fid *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 Fid*
50 plumbopenfid(char *name, int mode)
51 {
52 if(fsplumb == nil)
53 fsplumb = nsmount("plumb", "");
54 if(fsplumb == nil)
55 return nil;
56 return fsopen(fsplumb, name, mode);
57 }
59 int
60 plumbsendtofid(Fid *fid, Plumbmsg *m)
61 {
62 char *buf;
63 int n;
65 if(fid == nil){
66 werrstr("invalid fid");
67 return -1;
68 }
69 buf = plumbpack(m, &n);
70 if(buf == nil)
71 return -1;
72 n = fswrite(fid, buf, n);
73 free(buf);
74 return n;
75 }
77 int
78 plumbsend(int fd, Plumbmsg *m)
79 {
80 if(fd == -1){
81 werrstr("invalid fd");
82 return -1;
83 }
84 if(fd != pfd){
85 werrstr("fd is not the plumber");
86 return -1;
87 }
88 return plumbsendtofid(pfid, m);
89 }
91 Plumbmsg*
92 plumbrecv(int fd)
93 {
94 char *buf;
95 Plumbmsg *m;
96 int n, more;
98 buf = malloc(8192);
99 if(buf == nil)
100 return nil;
101 n = read(fd, buf, 8192);
102 m = nil;
103 if(n > 0){
104 m = plumbunpackpartial(buf, n, &more);
105 if(m==nil && more>0){
106 /* we now know how many more bytes to read for complete message */
107 buf = realloc(buf, n+more);
108 if(buf == nil)
109 return nil;
110 if(readn(fd, buf+n, more) == more)
111 m = plumbunpackpartial(buf, n+more, nil);
114 free(buf);
115 return m;
118 Plumbmsg*
119 plumbrecvfid(Fid *fid)
121 char *buf;
122 Plumbmsg *m;
123 int n, more;
125 buf = malloc(8192);
126 if(buf == nil)
127 return nil;
128 n = fsread(fid, buf, 8192);
129 m = nil;
130 if(n > 0){
131 m = plumbunpackpartial(buf, n, &more);
132 if(m==nil && more>0){
133 /* we now know how many more bytes to read for complete message */
134 buf = realloc(buf, n+more);
135 if(buf == nil)
136 return nil;
137 if(fsreadn(fid, buf+n, more) == more)
138 m = plumbunpackpartial(buf, n+more, nil);
141 free(buf);
142 return m;