| #include <u.h> |
| #include <libc.h> |
| #include <fcall.h> |
| #include <9pclient.h> |
| #include "plumb.h" |
| |
| static CFsys *fsplumb; |
| static int pfd = -1; |
| static CFid *pfid; |
| |
| int |
| plumbunmount(void) |
| { |
| CFsys *fsys; |
| |
| if(fsplumb){ |
| fsys = fsplumb; |
| fsplumb = nil; |
| fsunmount(fsys); |
| } |
| return 0; |
| } |
| |
| int |
| plumbopen(char *name, int omode) |
| { |
| if(fsplumb == nil) |
| fsplumb = nsmount("plumb", ""); |
| if(fsplumb == nil) |
| return -1; |
| /* |
| * It's important that when we send something, |
| * we find out whether it was a valid plumb write. |
| * (If it isn't, the client might fall back to some |
| * other mechanism or indicate to the user what happened.) |
| * We can't use a pipe for this, so we have to use the |
| * fid interface. But we need to return a fd. |
| * Return a fd for /dev/null so that we return a unique |
| * file descriptor. In plumbsend we'll look for pfd |
| * and use the recorded fid instead. |
| */ |
| if((omode&3) == OWRITE){ |
| if(pfd != -1){ |
| werrstr("already have plumb send open"); |
| return -1; |
| } |
| pfd = open("/dev/null", OWRITE); |
| if(pfd < 0) |
| return -1; |
| pfid = fsopen(fsplumb, name, omode); |
| if(pfid == nil){ |
| close(pfd); |
| pfd = -1; |
| return -1; |
| } |
| return pfd; |
| } |
| |
| return fsopenfd(fsplumb, name, omode); |
| } |
| |
| CFid* |
| plumbopenfid(char *name, int mode) |
| { |
| if(fsplumb == nil){ |
| fsplumb = nsmount("plumb", ""); |
| if(fsplumb == nil){ |
| werrstr("mount plumb: %r"); |
| return nil; |
| } |
| } |
| return fsopen(fsplumb, name, mode); |
| } |
| |
| int |
| plumbsendtofid(CFid *fid, Plumbmsg *m) |
| { |
| char *buf; |
| int n; |
| |
| if(fid == nil){ |
| werrstr("invalid fid"); |
| return -1; |
| } |
| buf = plumbpack(m, &n); |
| if(buf == nil) |
| return -1; |
| n = fswrite(fid, buf, n); |
| free(buf); |
| return n; |
| } |
| |
| int |
| plumbsend(int fd, Plumbmsg *m) |
| { |
| if(fd == -1){ |
| werrstr("invalid fd"); |
| return -1; |
| } |
| if(fd != pfd){ |
| werrstr("fd is not the plumber"); |
| return -1; |
| } |
| return plumbsendtofid(pfid, m); |
| } |
| |
| Plumbmsg* |
| plumbrecv(int fd) |
| { |
| char *buf; |
| Plumbmsg *m; |
| int n, more; |
| |
| buf = malloc(8192); |
| if(buf == nil) |
| return nil; |
| n = read(fd, buf, 8192); |
| m = nil; |
| if(n > 0){ |
| m = plumbunpackpartial(buf, n, &more); |
| if(m==nil && more>0){ |
| /* we now know how many more bytes to read for complete message */ |
| buf = realloc(buf, n+more); |
| if(buf == nil) |
| return nil; |
| if(readn(fd, buf+n, more) == more) |
| m = plumbunpackpartial(buf, n+more, nil); |
| } |
| } |
| free(buf); |
| return m; |
| } |
| |
| Plumbmsg* |
| plumbrecvfid(CFid *fid) |
| { |
| char *buf; |
| Plumbmsg *m; |
| int n, more; |
| |
| if(fid == nil){ |
| werrstr("invalid fid"); |
| return nil; |
| } |
| buf = malloc(8192); |
| if(buf == nil) |
| return nil; |
| n = fsread(fid, buf, 8192); |
| m = nil; |
| if(n > 0){ |
| m = plumbunpackpartial(buf, n, &more); |
| if(m==nil && more>0){ |
| /* we now know how many more bytes to read for complete message */ |
| buf = realloc(buf, n+more); |
| if(buf == nil) |
| return nil; |
| if(fsreadn(fid, buf+n, more) == more) |
| m = plumbunpackpartial(buf, n+more, nil); |
| } |
| } |
| free(buf); |
| return m; |
| } |
| |