fid.c (2894B)
1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 #include <9pclient.h> 5 #include "plumb.h" 6 7 static CFsys *fsplumb; 8 static int pfd = -1; 9 static CFid *pfid; 10 11 int 12 plumbunmount(void) 13 { 14 CFsys *fsys; 15 16 if(fsplumb){ 17 fsys = fsplumb; 18 fsplumb = nil; 19 fsunmount(fsys); 20 } 21 return 0; 22 } 23 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 } 58 59 return fsopenfd(fsplumb, name, omode); 60 } 61 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 } 74 75 int 76 plumbsendtofid(CFid *fid, Plumbmsg *m) 77 { 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 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; 103 } 104 return plumbsendtofid(pfid, m); 105 } 106 107 Plumbmsg* 108 plumbrecv(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 134 Plumbmsg* 135 plumbrecvfid(CFid *fid) 136 { 137 char *buf; 138 Plumbmsg *m; 139 int n, more; 140 141 if(fid == nil){ 142 werrstr("invalid fid"); 143 return nil; 144 } 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); 159 } 160 } 161 free(buf); 162 return m; 163 }