rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 1 | #include <u.h> |
| 2 | #include <libc.h> |
| 3 | #include <fcall.h> |
| 4 | #include <fs.h> |
| 5 | #include "plumb.h" |
| 6 | |
| 7 | static Fsys *fsplumb; |
| 8 | static int pfd = -1; |
| 9 | static Fid *pfid; |
| 10 | |
| 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 | } |
| 45 | |
| 46 | return fsopenfd(fsplumb, name, omode); |
| 47 | } |
| 48 | |
| 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 | } |
| 58 | |
| 59 | int |
| 60 | plumbsendtofid(Fid *fid, Plumbmsg *m) |
| 61 | { |
| 62 | char *buf; |
| 63 | int n; |
| 64 | |
| 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 | } |
| 76 | |
| 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 | } |
| 90 | |
| 91 | Plumbmsg* |
| 92 | plumbrecv(int fd) |
| 93 | { |
| 94 | char *buf; |
| 95 | Plumbmsg *m; |
| 96 | int n, more; |
| 97 | |
| 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); |
| 112 | } |
| 113 | } |
| 114 | free(buf); |
| 115 | return m; |
| 116 | } |
| 117 | |
| 118 | Plumbmsg* |
| 119 | plumbrecvfid(Fid *fid) |
| 120 | { |
| 121 | char *buf; |
| 122 | Plumbmsg *m; |
| 123 | int n, more; |
| 124 | |
| 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); |
| 139 | } |
| 140 | } |
| 141 | free(buf); |
| 142 | return m; |
| 143 | } |
| 144 | |