rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 1 | #include <u.h> |
| 2 | #include <libc.h> |
| 3 | #include <fcall.h> |
rsc | b4e8c4b | 2005-01-04 22:21:23 +0000 | [diff] [blame] | 4 | #include <9pclient.h> |
rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 5 | #include "plumb.h" |
| 6 | |
rsc | b4e8c4b | 2005-01-04 22:21:23 +0000 | [diff] [blame] | 7 | static CFsys *fsplumb; |
rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 8 | static int pfd = -1; |
rsc | b4e8c4b | 2005-01-04 22:21:23 +0000 | [diff] [blame] | 9 | static CFid *pfid; |
rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 10 | |
| 11 | int |
rsc | 1dc6e08 | 2006-06-25 23:55:37 +0000 | [diff] [blame] | 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 |
rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 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 | |
rsc | b4e8c4b | 2005-01-04 22:21:23 +0000 | [diff] [blame] | 62 | CFid* |
rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 63 | plumbopenfid(char *name, int mode) |
| 64 | { |
rsc | 57d7df4 | 2005-03-18 19:04:28 +0000 | [diff] [blame] | 65 | if(fsplumb == nil){ |
rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 66 | fsplumb = nsmount("plumb", ""); |
rsc | 57d7df4 | 2005-03-18 19:04:28 +0000 | [diff] [blame] | 67 | if(fsplumb == nil){ |
| 68 | werrstr("mount plumb: %r"); |
| 69 | return nil; |
| 70 | } |
| 71 | } |
rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 72 | return fsopen(fsplumb, name, mode); |
| 73 | } |
| 74 | |
| 75 | int |
rsc | b4e8c4b | 2005-01-04 22:21:23 +0000 | [diff] [blame] | 76 | plumbsendtofid(CFid *fid, Plumbmsg *m) |
rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 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* |
rsc | b4e8c4b | 2005-01-04 22:21:23 +0000 | [diff] [blame] | 135 | plumbrecvfid(CFid *fid) |
rsc | 4f604b1 | 2004-06-09 14:04:33 +0000 | [diff] [blame] | 136 | { |
| 137 | char *buf; |
| 138 | Plumbmsg *m; |
| 139 | int n, more; |
| 140 | |
| 141 | buf = malloc(8192); |
| 142 | if(buf == nil) |
| 143 | return nil; |
| 144 | n = fsread(fid, buf, 8192); |
| 145 | m = nil; |
| 146 | if(n > 0){ |
| 147 | m = plumbunpackpartial(buf, n, &more); |
| 148 | if(m==nil && more>0){ |
| 149 | /* we now know how many more bytes to read for complete message */ |
| 150 | buf = realloc(buf, n+more); |
| 151 | if(buf == nil) |
| 152 | return nil; |
| 153 | if(fsreadn(fid, buf+n, more) == more) |
| 154 | m = plumbunpackpartial(buf, n+more, nil); |
| 155 | } |
| 156 | } |
| 157 | free(buf); |
| 158 | return m; |
| 159 | } |
| 160 | |