1 /* $NetBSD: ninebuf.c,v 1.7 2007/09/06 16:09:09 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2006, 2007 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 #ifndef lint 30 __RCSID("$NetBSD: ninebuf.c,v 1.7 2007/09/06 16:09:09 pooka Exp $"); 31 #endif /* !lint */ 32 33 #include <sys/types.h> 34 #include <sys/time.h> 35 #include <sys/vnode.h> 36 37 #include <err.h> 38 #include <errno.h> 39 #include <stdlib.h> 40 #include <util.h> 41 #include <unistd.h> 42 43 #include "ninepuffs.h" 44 45 #define CHECK(v) if (!(v)) abort() 46 47 uint8_t 48 p9pbuf_get_type(struct puffs_framebuf *pb) 49 { 50 uint8_t val; 51 52 puffs_framebuf_getdata_atoff(pb, 4, &val, 1); 53 return val; 54 } 55 56 uint16_t 57 p9pbuf_get_tag(struct puffs_framebuf *pb) 58 { 59 uint16_t val; 60 61 puffs_framebuf_getdata_atoff(pb, 5, &val, 2); 62 return le16toh(val); 63 } 64 65 static uint32_t 66 p9pbuf_get_len(struct puffs_framebuf *pb) 67 { 68 uint32_t val; 69 70 puffs_framebuf_getdata_atoff(pb, 0, &val, 4); 71 return le32toh(val); 72 } 73 74 #define CUROFF(pb) (puffs_framebuf_telloff(pb)) 75 int 76 p9pbuf_read(struct puffs_usermount *pu, struct puffs_framebuf *pb, 77 int fd, int *done) 78 { 79 void *win; 80 ssize_t n; 81 size_t howmuch, winlen; 82 int lenstate; 83 84 the_next_level: 85 if ((lenstate = (CUROFF(pb) < 4))) 86 howmuch = 4 - CUROFF(pb); 87 else 88 howmuch = p9pbuf_get_len(pb) - CUROFF(pb); 89 90 if (puffs_framebuf_reserve_space(pb, howmuch) == -1) 91 return errno; 92 93 while (howmuch) { 94 winlen = howmuch; 95 if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1) 96 return errno; 97 n = read(fd, win, winlen); 98 switch (n) { 99 case 0: 100 return ECONNRESET; 101 case -1: 102 if (errno == EAGAIN) 103 return 0; 104 return errno; 105 default: 106 howmuch -= n; 107 puffs_framebuf_seekset(pb, CUROFF(pb) + n); 108 break; 109 } 110 } 111 112 if (!lenstate) { 113 puffs_framebuf_seekset(pb, 7); 114 *done = 1; 115 return 0; 116 } else 117 goto the_next_level; 118 } 119 120 int 121 p9pbuf_write(struct puffs_usermount *pu, struct puffs_framebuf *pb, 122 int fd, int *done) 123 { 124 void *win; 125 ssize_t n; 126 size_t winlen, howmuch; 127 128 if (CUROFF(pb) == 0) { 129 uint32_t len; 130 131 len = htole32(puffs_framebuf_tellsize(pb)); 132 puffs_framebuf_putdata_atoff(pb, 0, &len, 4); 133 } 134 135 howmuch = puffs_framebuf_tellsize(pb) - CUROFF(pb); 136 while (howmuch) { 137 winlen = howmuch; 138 if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1) 139 return errno; 140 n = send(fd, win, winlen, MSG_NOSIGNAL); 141 switch (n) { 142 case 0: 143 return ECONNRESET; 144 case -1: 145 if (errno == EAGAIN) 146 return 0; 147 return errno; 148 default: 149 howmuch -= n; 150 puffs_framebuf_seekset(pb, CUROFF(pb) + n); 151 break; 152 } 153 } 154 155 *done = 1; 156 return 0; 157 } 158 #undef CUROFF 159 160 int 161 p9pbuf_cmp(struct puffs_usermount *pu, 162 struct puffs_framebuf *c1, struct puffs_framebuf *c2, int *notresp) 163 { 164 165 return p9pbuf_get_tag(c1) != p9pbuf_get_tag(c2); 166 } 167 168 struct puffs_framebuf * 169 p9pbuf_makeout() 170 { 171 struct puffs_framebuf *pb; 172 173 pb = puffs_framebuf_make(); 174 puffs_framebuf_seekset(pb, 4); 175 return pb; 176 } 177 178 void 179 p9pbuf_recycleout(struct puffs_framebuf *pb) 180 { 181 182 puffs_framebuf_recycle(pb); 183 puffs_framebuf_seekset(pb, 4); 184 } 185 186 void 187 p9pbuf_put_1(struct puffs_framebuf *pb, uint8_t val) 188 { 189 int rv; 190 191 rv = puffs_framebuf_putdata(pb, &val, 1); 192 CHECK(rv == 0); 193 } 194 195 void 196 p9pbuf_put_2(struct puffs_framebuf *pb, uint16_t val) 197 { 198 int rv; 199 200 HTOLE16(val); 201 rv = puffs_framebuf_putdata(pb, &val, 2); 202 CHECK(rv == 0); 203 } 204 205 void 206 p9pbuf_put_4(struct puffs_framebuf *pb, uint32_t val) 207 { 208 int rv; 209 210 HTOLE32(val); 211 rv = puffs_framebuf_putdata(pb, &val, 4); 212 CHECK(rv == 0); 213 } 214 215 void 216 p9pbuf_put_8(struct puffs_framebuf *pb, uint64_t val) 217 { 218 int rv; 219 220 HTOLE64(val); 221 rv = puffs_framebuf_putdata(pb, &val, 8); 222 CHECK(rv == 0); 223 } 224 225 void 226 p9pbuf_put_data(struct puffs_framebuf *pb, const void *data, uint16_t dlen) 227 { 228 int rv; 229 230 p9pbuf_put_2(pb, dlen); 231 rv = puffs_framebuf_putdata(pb, data, dlen); 232 CHECK(rv == 0); 233 } 234 235 void 236 p9pbuf_put_str(struct puffs_framebuf *pb, const char *str) 237 { 238 239 p9pbuf_put_data(pb, str, strlen(str)); 240 } 241 242 void 243 p9pbuf_write_data(struct puffs_framebuf *pb, uint8_t *data, uint32_t dlen) 244 { 245 int rv; 246 247 rv = puffs_framebuf_putdata(pb, data, dlen); 248 CHECK(rv == 0); 249 } 250 251 #define ERETURN(rv) return ((rv) == -1 ? errno : 0) 252 253 int 254 p9pbuf_get_1(struct puffs_framebuf *pb, uint8_t *val) 255 { 256 257 ERETURN(puffs_framebuf_getdata(pb, val, 1)); 258 } 259 260 int 261 p9pbuf_get_2(struct puffs_framebuf *pb, uint16_t *val) 262 { 263 int rv; 264 265 rv = puffs_framebuf_getdata(pb, val, 2); 266 LE16TOH(*val); 267 268 ERETURN(rv); 269 } 270 271 int 272 p9pbuf_get_4(struct puffs_framebuf *pb, uint32_t *val) 273 { 274 int rv; 275 276 rv = puffs_framebuf_getdata(pb, val, 4); 277 LE32TOH(*val); 278 279 ERETURN(rv); 280 } 281 282 int 283 p9pbuf_get_8(struct puffs_framebuf *pb, uint64_t *val) 284 { 285 int rv; 286 287 rv = puffs_framebuf_getdata(pb, val, 8); 288 LE64TOH(*val); 289 290 ERETURN(rv); 291 } 292 293 int 294 p9pbuf_get_data(struct puffs_framebuf *pb, uint8_t **dp, uint16_t *dlenp) 295 { 296 uint8_t *data; 297 uint16_t len; 298 int rv; 299 300 rv = p9pbuf_get_2(pb, &len); 301 if (rv) 302 return errno; 303 304 if (puffs_framebuf_remaining(pb) < len) 305 return EPROTO; 306 307 if (dp) { 308 data = emalloc(len+1); 309 rv = puffs_framebuf_getdata(pb, data, len); 310 if (rv) { 311 free(data); 312 return errno; 313 } 314 data[len] = '\0'; 315 *dp = data; 316 } else 317 puffs_framebuf_seekset(pb, puffs_framebuf_telloff(pb)+len); 318 319 if (dlenp) 320 *dlenp = len; 321 322 return 0; 323 } 324 325 int 326 p9pbuf_read_data(struct puffs_framebuf *pb, uint8_t *buf, uint32_t dlen) 327 { 328 329 ERETURN(puffs_framebuf_getdata(pb, buf, dlen)); 330 } 331 332 int 333 p9pbuf_get_str(struct puffs_framebuf *pb, char **dp, uint16_t *dlenp) 334 { 335 336 return p9pbuf_get_data(pb, (uint8_t **)dp, dlenp); 337 } 338