1 /* 2 * Copyright 2016 Jakub Klama <jceel@FreeBSD.org> 3 * All rights reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted providing that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28 /* 29 * Based on libixp code: ©2007-2010 Kris Maglione <maglione.k at Gmail> 30 */ 31 32 #include <stdlib.h> 33 #include <string.h> 34 #include <assert.h> 35 #include <sys/types.h> 36 #include <sys/param.h> 37 #ifdef __APPLE__ 38 # include "apple_endian.h" 39 #else 40 # include <sys/endian.h> 41 #endif 42 #include <sys/uio.h> 43 #include "lib9p.h" 44 #include "lib9p_impl.h" 45 #include "log.h" 46 47 #define N(ary) (sizeof(ary) / sizeof(*ary)) 48 #define STRING_SIZE(s) (L9P_WORD + (s != NULL ? (uint16_t)strlen(s) : 0)) 49 #define QID_SIZE (L9P_BYTE + L9P_DWORD + L9P_QWORD) 50 51 static ssize_t l9p_iov_io(struct l9p_message *, void *, size_t); 52 static inline ssize_t l9p_pu8(struct l9p_message *, uint8_t *); 53 static inline ssize_t l9p_pu16(struct l9p_message *, uint16_t *); 54 static inline ssize_t l9p_pu32(struct l9p_message *, uint32_t *); 55 static inline ssize_t l9p_pu64(struct l9p_message *, uint64_t *); 56 static ssize_t l9p_pustring(struct l9p_message *, char **s); 57 static ssize_t l9p_pustrings(struct l9p_message *, uint16_t *, char **, size_t); 58 static ssize_t l9p_puqid(struct l9p_message *, struct l9p_qid *); 59 static ssize_t l9p_puqids(struct l9p_message *, uint16_t *, struct l9p_qid *q); 60 61 /* 62 * Transfer data from incoming request, or to outgoing response, 63 * using msg to track position and direction within request/response. 64 * 65 * Returns the number of bytes actually transferred (which is always 66 * just len itself, converted to signed), or -1 if we ran out of space. 67 * 68 * Note that if we return -1, subsequent l9p_iov_io() calls with 69 * the same (and not-reset) msg and len > 0 will also return -1. 70 * This means most users can just check the *last* call for failure. 71 */ 72 static ssize_t 73 l9p_iov_io(struct l9p_message *msg, void *buffer, size_t len) 74 { 75 size_t done = 0; 76 size_t left = len; 77 78 assert(msg != NULL); 79 80 if (len == 0) 81 return (0); 82 83 if (msg->lm_cursor_iov >= msg->lm_niov) 84 return (-1); 85 86 assert(buffer != NULL); 87 88 while (left > 0) { 89 size_t idx = msg->lm_cursor_iov; 90 size_t space = msg->lm_iov[idx].iov_len - msg->lm_cursor_offset; 91 size_t towrite = MIN(space, left); 92 93 if (msg->lm_mode == L9P_PACK) { 94 memcpy((char *)msg->lm_iov[idx].iov_base + 95 msg->lm_cursor_offset, (char *)buffer + done, 96 towrite); 97 } 98 99 if (msg->lm_mode == L9P_UNPACK) { 100 memcpy((char *)buffer + done, 101 (char *)msg->lm_iov[idx].iov_base + 102 msg->lm_cursor_offset, towrite); 103 } 104 105 msg->lm_cursor_offset += towrite; 106 107 done += towrite; 108 left -= towrite; 109 110 if (space - towrite == 0) { 111 /* Advance to next iov */ 112 msg->lm_cursor_iov++; 113 msg->lm_cursor_offset = 0; 114 115 if (msg->lm_cursor_iov >= msg->lm_niov && left > 0) 116 return (-1); 117 } 118 } 119 120 msg->lm_size += done; 121 return ((ssize_t)done); 122 } 123 124 /* 125 * Pack or unpack a byte (8 bits). 126 * 127 * Returns 1 (success, 1 byte) or -1 (error). 128 */ 129 static inline ssize_t 130 l9p_pu8(struct l9p_message *msg, uint8_t *val) 131 { 132 133 return (l9p_iov_io(msg, val, sizeof (uint8_t))); 134 } 135 136 /* 137 * Pack or unpack 16-bit value. 138 * 139 * Returns 2 or -1. 140 */ 141 static inline ssize_t 142 l9p_pu16(struct l9p_message *msg, uint16_t *val) 143 { 144 #if _BYTE_ORDER != _LITTLE_ENDIAN 145 /* 146 * The ifdefs are annoying, but there is no need 147 * for all of this foolery on little-endian hosts, 148 * and I don't expect the compiler to optimize it 149 * all away. 150 */ 151 uint16_t copy; 152 ssize_t ret; 153 154 if (msg->lm_mode == L9P_PACK) { 155 copy = htole16(*val); 156 return (l9p_iov_io(msg, ©, sizeof (uint16_t))); 157 } 158 ret = l9p_iov_io(msg, val, sizeof (uint16_t)); 159 *val = le16toh(*val); 160 return (ret); 161 #else 162 return (l9p_iov_io(msg, val, sizeof (uint16_t))); 163 #endif 164 } 165 166 /* 167 * Pack or unpack 32-bit value. 168 * 169 * Returns 4 or -1. 170 */ 171 static inline ssize_t 172 l9p_pu32(struct l9p_message *msg, uint32_t *val) 173 { 174 #if _BYTE_ORDER != _LITTLE_ENDIAN 175 uint32_t copy; 176 ssize_t ret; 177 178 if (msg->lm_mode == L9P_PACK) { 179 copy = htole32(*val); 180 return (l9p_iov_io(msg, ©, sizeof (uint32_t))); 181 } 182 ret = l9p_iov_io(msg, val, sizeof (uint32_t)); 183 *val = le32toh(*val); 184 return (ret); 185 #else 186 return (l9p_iov_io(msg, val, sizeof (uint32_t))); 187 #endif 188 } 189 190 /* 191 * Pack or unpack 64-bit value. 192 * 193 * Returns 8 or -1. 194 */ 195 static inline ssize_t 196 l9p_pu64(struct l9p_message *msg, uint64_t *val) 197 { 198 #if _BYTE_ORDER != _LITTLE_ENDIAN 199 uint64_t copy; 200 ssize_t ret; 201 202 if (msg->lm_mode == L9P_PACK) { 203 copy = htole64(*val); 204 return (l9p_iov_io(msg, ©, sizeof (uint64_t))); 205 } 206 ret = l9p_iov_io(msg, val, sizeof (uint32_t)); 207 *val = le64toh(*val); 208 return (ret); 209 #else 210 return (l9p_iov_io(msg, val, sizeof (uint64_t))); 211 #endif 212 } 213 214 /* 215 * Pack or unpack a string, encoded as 2-byte length followed by 216 * string bytes. The returned length is 2 greater than the 217 * length of the string itself. 218 * 219 * When unpacking, this allocates a new string (NUL-terminated). 220 * 221 * Return -1 on error (not space, or failed to allocate string, 222 * or illegal string). 223 * 224 * Note that pustring (and hence pustrings) can return an error 225 * even when l9p_iov_io succeeds. 226 */ 227 static ssize_t 228 l9p_pustring(struct l9p_message *msg, char **s) 229 { 230 uint16_t len; 231 232 if (msg->lm_mode == L9P_PACK) 233 len = *s != NULL ? (uint16_t)strlen(*s) : 0; 234 235 if (l9p_pu16(msg, &len) < 0) 236 return (-1); 237 238 if (msg->lm_mode == L9P_UNPACK) { 239 *s = l9p_calloc(1, len + 1); 240 if (*s == NULL) 241 return (-1); 242 } 243 244 if (l9p_iov_io(msg, *s, len) < 0) 245 return (-1); 246 247 if (msg->lm_mode == L9P_UNPACK) { 248 /* 249 * An embedded NUL byte in a string is illegal. 250 * We don't necessarily have to check (we'll just 251 * treat it as a shorter string), but checking 252 * seems like a good idea. 253 */ 254 if (memchr(*s, '\0', len) != NULL) 255 return (-1); 256 } 257 258 return ((ssize_t)len + 2); 259 } 260 261 /* 262 * Pack or unpack a number (*num) of strings (but at most max of 263 * them). 264 * 265 * Returns the number of bytes transferred, including the packed 266 * number of strings. If packing and the packed number of strings 267 * was reduced, the original *num value is unchanged; only the 268 * wire-format number is reduced. If unpacking and the input 269 * number of strings exceeds the max, the incoming *num is reduced 270 * to lim, if needed. (NOTE ASYMMETRY HERE!) 271 * 272 * Returns -1 on error. 273 */ 274 static ssize_t 275 l9p_pustrings(struct l9p_message *msg, uint16_t *num, char **strings, 276 size_t max) 277 { 278 size_t i, lim; 279 ssize_t r, ret; 280 uint16_t adjusted; 281 282 if (msg->lm_mode == L9P_PACK) { 283 lim = *num; 284 if (lim > max) 285 lim = max; 286 adjusted = (uint16_t)lim; 287 r = l9p_pu16(msg, &adjusted); 288 } else { 289 r = l9p_pu16(msg, num); 290 lim = *num; 291 if (lim > max) 292 *num = (uint16_t)(lim = max); 293 } 294 if (r < 0) 295 return (-1); 296 297 for (i = 0; i < lim; i++) { 298 ret = l9p_pustring(msg, &strings[i]); 299 if (ret < 1) 300 return (-1); 301 302 r += ret; 303 } 304 305 return (r); 306 } 307 308 /* 309 * Pack or unpack a qid. 310 * 311 * Returns 13 (success) or -1 (error). 312 */ 313 static ssize_t 314 l9p_puqid(struct l9p_message *msg, struct l9p_qid *qid) 315 { 316 ssize_t r; 317 uint8_t type; 318 319 if (msg->lm_mode == L9P_PACK) { 320 type = qid->type; 321 r = l9p_pu8(msg, &type); 322 } else { 323 r = l9p_pu8(msg, &type); 324 qid->type = type; 325 } 326 if (r > 0) 327 r = l9p_pu32(msg, &qid->version); 328 if (r > 0) 329 r = l9p_pu64(msg, &qid->path); 330 331 return (r > 0 ? QID_SIZE : r); 332 } 333 334 /* 335 * Pack or unpack *num qids. 336 * 337 * Returns 2 + 13 * *num (after possibly setting *num), or -1 on error. 338 */ 339 static ssize_t 340 l9p_puqids(struct l9p_message *msg, uint16_t *num, struct l9p_qid *qids) 341 { 342 size_t i, lim; 343 ssize_t ret, r; 344 345 r = l9p_pu16(msg, num); 346 if (r <= 0) 347 return (r); 348 349 if (*num > L9P_MAX_WELEM) 350 return (-1); 351 352 for (i = 0, lim = *num; i < lim; i++) { 353 ret = l9p_puqid(msg, &qids[i]); 354 if (ret < 0) 355 return (-1); 356 r += ret; 357 } 358 return (r); 359 } 360 361 /* 362 * Pack or unpack a l9p_stat. 363 * 364 * These have variable size, and the size further depends on 365 * the protocol version. 366 * 367 * Returns the number of bytes packed/unpacked, or -1 on error. 368 */ 369 ssize_t 370 l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat, 371 enum l9p_version version) 372 { 373 ssize_t r = 0; 374 uint16_t size; 375 376 /* The on-wire size field excludes the size of the size field. */ 377 if (msg->lm_mode == L9P_PACK) 378 size = l9p_sizeof_stat(stat, version) - 2; 379 380 r += l9p_pu16(msg, &size); 381 r += l9p_pu16(msg, &stat->type); 382 r += l9p_pu32(msg, &stat->dev); 383 r += l9p_puqid(msg, &stat->qid); 384 r += l9p_pu32(msg, &stat->mode); 385 r += l9p_pu32(msg, &stat->atime); 386 r += l9p_pu32(msg, &stat->mtime); 387 r += l9p_pu64(msg, &stat->length); 388 r += l9p_pustring(msg, &stat->name); 389 r += l9p_pustring(msg, &stat->uid); 390 r += l9p_pustring(msg, &stat->gid); 391 r += l9p_pustring(msg, &stat->muid); 392 393 if (version >= L9P_2000U) { 394 r += l9p_pustring(msg, &stat->extension); 395 r += l9p_pu32(msg, &stat->n_uid); 396 r += l9p_pu32(msg, &stat->n_gid); 397 r += l9p_pu32(msg, &stat->n_muid); 398 } 399 400 if (r < size + 2) 401 return (-1); 402 403 return (r); 404 } 405 406 /* 407 * Pack or unpack a variable-length dirent. 408 * 409 * If unpacking, the name field is malloc()ed and the caller must 410 * free it. 411 * 412 * Returns the wire-format length, or -1 if we ran out of room. 413 */ 414 ssize_t 415 l9p_pudirent(struct l9p_message *msg, struct l9p_dirent *de) 416 { 417 ssize_t r, s; 418 419 r = l9p_puqid(msg, &de->qid); 420 r += l9p_pu64(msg, &de->offset); 421 r += l9p_pu8(msg, &de->type); 422 s = l9p_pustring(msg, &de->name); 423 if (r < QID_SIZE + 8 + 1 || s < 0) 424 return (-1); 425 return (r + s); 426 } 427 428 /* 429 * Pack or unpack a request or response (fcall). 430 * 431 * Returns 0 on success, -1 on error. (It's up to the caller 432 * to call l9p_freefcall on our failure.) 433 */ 434 int 435 l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall, 436 enum l9p_version version) 437 { 438 uint32_t length = 0; 439 ssize_t r; 440 441 /* 442 * Get overall length, type, and tag, which should appear 443 * in all messages. If not even that works, abort immediately. 444 */ 445 l9p_pu32(msg, &length); 446 l9p_pu8(msg, &fcall->hdr.type); 447 r = l9p_pu16(msg, &fcall->hdr.tag); 448 if (r < 0) 449 return (-1); 450 451 /* 452 * Decode remainder of message. When unpacking, this may 453 * allocate memory, even if we fail during the decode. 454 * Note that the initial fcall is zeroed out, though, so 455 * we can just freefcall() to release whatever might have 456 * gotten allocated, if the unpack fails due to a short 457 * packet. 458 */ 459 switch (fcall->hdr.type) { 460 case L9P_TVERSION: 461 case L9P_RVERSION: 462 l9p_pu32(msg, &fcall->version.msize); 463 r = l9p_pustring(msg, &fcall->version.version); 464 break; 465 466 case L9P_TAUTH: 467 l9p_pu32(msg, &fcall->tauth.afid); 468 r = l9p_pustring(msg, &fcall->tauth.uname); 469 if (r < 0) 470 break; 471 r = l9p_pustring(msg, &fcall->tauth.aname); 472 if (r < 0) 473 break; 474 if (version >= L9P_2000U) 475 r = l9p_pu32(msg, &fcall->tauth.n_uname); 476 break; 477 478 case L9P_RAUTH: 479 r = l9p_puqid(msg, &fcall->rauth.aqid); 480 break; 481 482 case L9P_TATTACH: 483 l9p_pu32(msg, &fcall->hdr.fid); 484 l9p_pu32(msg, &fcall->tattach.afid); 485 r = l9p_pustring(msg, &fcall->tattach.uname); 486 if (r < 0) 487 break; 488 r = l9p_pustring(msg, &fcall->tattach.aname); 489 if (r < 0) 490 break; 491 if (version >= L9P_2000U) 492 r = l9p_pu32(msg, &fcall->tattach.n_uname); 493 break; 494 495 case L9P_RATTACH: 496 r = l9p_puqid(msg, &fcall->rattach.qid); 497 break; 498 499 case L9P_RERROR: 500 r = l9p_pustring(msg, &fcall->error.ename); 501 if (r < 0) 502 break; 503 if (version >= L9P_2000U) 504 r = l9p_pu32(msg, &fcall->error.errnum); 505 break; 506 507 case L9P_RLERROR: 508 r = l9p_pu32(msg, &fcall->error.errnum); 509 break; 510 511 case L9P_TFLUSH: 512 r = l9p_pu16(msg, &fcall->tflush.oldtag); 513 break; 514 515 case L9P_RFLUSH: 516 break; 517 518 case L9P_TWALK: 519 l9p_pu32(msg, &fcall->hdr.fid); 520 l9p_pu32(msg, &fcall->twalk.newfid); 521 r = l9p_pustrings(msg, &fcall->twalk.nwname, 522 fcall->twalk.wname, N(fcall->twalk.wname)); 523 break; 524 525 case L9P_RWALK: 526 r = l9p_puqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid); 527 break; 528 529 case L9P_TOPEN: 530 l9p_pu32(msg, &fcall->hdr.fid); 531 r = l9p_pu8(msg, &fcall->topen.mode); 532 break; 533 534 case L9P_ROPEN: 535 l9p_puqid(msg, &fcall->ropen.qid); 536 r = l9p_pu32(msg, &fcall->ropen.iounit); 537 break; 538 539 case L9P_TCREATE: 540 l9p_pu32(msg, &fcall->hdr.fid); 541 r = l9p_pustring(msg, &fcall->tcreate.name); 542 if (r < 0) 543 break; 544 l9p_pu32(msg, &fcall->tcreate.perm); 545 r = l9p_pu8(msg, &fcall->tcreate.mode); 546 if (version >= L9P_2000U) 547 r = l9p_pustring(msg, &fcall->tcreate.extension); 548 break; 549 550 case L9P_RCREATE: 551 l9p_puqid(msg, &fcall->rcreate.qid); 552 r = l9p_pu32(msg, &fcall->rcreate.iounit); 553 break; 554 555 case L9P_TREAD: 556 case L9P_TREADDIR: 557 l9p_pu32(msg, &fcall->hdr.fid); 558 l9p_pu64(msg, &fcall->io.offset); 559 r = l9p_pu32(msg, &fcall->io.count); 560 break; 561 562 case L9P_RREAD: 563 case L9P_RREADDIR: 564 r = l9p_pu32(msg, &fcall->io.count); 565 break; 566 567 case L9P_TWRITE: 568 l9p_pu32(msg, &fcall->hdr.fid); 569 l9p_pu64(msg, &fcall->io.offset); 570 r = l9p_pu32(msg, &fcall->io.count); 571 break; 572 573 case L9P_RWRITE: 574 r = l9p_pu32(msg, &fcall->io.count); 575 break; 576 577 case L9P_TCLUNK: 578 case L9P_TSTAT: 579 case L9P_TREMOVE: 580 case L9P_TSTATFS: 581 r = l9p_pu32(msg, &fcall->hdr.fid); 582 break; 583 584 case L9P_RCLUNK: 585 case L9P_RREMOVE: 586 break; 587 588 case L9P_RSTAT: 589 { 590 uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat, 591 version); 592 l9p_pu16(msg, &size); 593 r = l9p_pustat(msg, &fcall->rstat.stat, version); 594 } 595 break; 596 597 case L9P_TWSTAT: 598 { 599 uint16_t size; 600 l9p_pu32(msg, &fcall->hdr.fid); 601 l9p_pu16(msg, &size); 602 r = l9p_pustat(msg, &fcall->twstat.stat, version); 603 } 604 break; 605 606 case L9P_RWSTAT: 607 break; 608 609 case L9P_RSTATFS: 610 l9p_pu32(msg, &fcall->rstatfs.statfs.type); 611 l9p_pu32(msg, &fcall->rstatfs.statfs.bsize); 612 l9p_pu64(msg, &fcall->rstatfs.statfs.blocks); 613 l9p_pu64(msg, &fcall->rstatfs.statfs.bfree); 614 l9p_pu64(msg, &fcall->rstatfs.statfs.bavail); 615 l9p_pu64(msg, &fcall->rstatfs.statfs.files); 616 l9p_pu64(msg, &fcall->rstatfs.statfs.ffree); 617 l9p_pu64(msg, &fcall->rstatfs.statfs.fsid); 618 r = l9p_pu32(msg, &fcall->rstatfs.statfs.namelen); 619 break; 620 621 case L9P_TLOPEN: 622 l9p_pu32(msg, &fcall->hdr.fid); 623 r = l9p_pu32(msg, &fcall->tlopen.flags); 624 break; 625 626 case L9P_RLOPEN: 627 l9p_puqid(msg, &fcall->rlopen.qid); 628 r = l9p_pu32(msg, &fcall->rlopen.iounit); 629 break; 630 631 case L9P_TLCREATE: 632 l9p_pu32(msg, &fcall->hdr.fid); 633 r = l9p_pustring(msg, &fcall->tlcreate.name); 634 if (r < 0) 635 break; 636 l9p_pu32(msg, &fcall->tlcreate.flags); 637 l9p_pu32(msg, &fcall->tlcreate.mode); 638 r = l9p_pu32(msg, &fcall->tlcreate.gid); 639 break; 640 641 case L9P_RLCREATE: 642 l9p_puqid(msg, &fcall->rlcreate.qid); 643 r = l9p_pu32(msg, &fcall->rlcreate.iounit); 644 break; 645 646 case L9P_TSYMLINK: 647 l9p_pu32(msg, &fcall->hdr.fid); 648 r = l9p_pustring(msg, &fcall->tsymlink.name); 649 if (r < 0) 650 break; 651 r = l9p_pustring(msg, &fcall->tsymlink.symtgt); 652 if (r < 0) 653 break; 654 r = l9p_pu32(msg, &fcall->tlcreate.gid); 655 break; 656 657 case L9P_RSYMLINK: 658 r = l9p_puqid(msg, &fcall->rsymlink.qid); 659 break; 660 661 case L9P_TMKNOD: 662 l9p_pu32(msg, &fcall->hdr.fid); 663 r = l9p_pustring(msg, &fcall->tmknod.name); 664 if (r < 0) 665 break; 666 l9p_pu32(msg, &fcall->tmknod.mode); 667 l9p_pu32(msg, &fcall->tmknod.major); 668 l9p_pu32(msg, &fcall->tmknod.minor); 669 r = l9p_pu32(msg, &fcall->tmknod.gid); 670 break; 671 672 case L9P_RMKNOD: 673 r = l9p_puqid(msg, &fcall->rmknod.qid); 674 break; 675 676 case L9P_TRENAME: 677 l9p_pu32(msg, &fcall->hdr.fid); 678 l9p_pu32(msg, &fcall->trename.dfid); 679 r = l9p_pustring(msg, &fcall->trename.name); 680 break; 681 682 case L9P_RRENAME: 683 break; 684 685 case L9P_TREADLINK: 686 r = l9p_pu32(msg, &fcall->hdr.fid); 687 break; 688 689 case L9P_RREADLINK: 690 r = l9p_pustring(msg, &fcall->rreadlink.target); 691 break; 692 693 case L9P_TGETATTR: 694 l9p_pu32(msg, &fcall->hdr.fid); 695 r = l9p_pu64(msg, &fcall->tgetattr.request_mask); 696 break; 697 698 case L9P_RGETATTR: 699 l9p_pu64(msg, &fcall->rgetattr.valid); 700 l9p_puqid(msg, &fcall->rgetattr.qid); 701 l9p_pu32(msg, &fcall->rgetattr.mode); 702 l9p_pu32(msg, &fcall->rgetattr.uid); 703 l9p_pu32(msg, &fcall->rgetattr.gid); 704 l9p_pu64(msg, &fcall->rgetattr.nlink); 705 l9p_pu64(msg, &fcall->rgetattr.rdev); 706 l9p_pu64(msg, &fcall->rgetattr.size); 707 l9p_pu64(msg, &fcall->rgetattr.blksize); 708 l9p_pu64(msg, &fcall->rgetattr.blocks); 709 l9p_pu64(msg, &fcall->rgetattr.atime_sec); 710 l9p_pu64(msg, &fcall->rgetattr.atime_nsec); 711 l9p_pu64(msg, &fcall->rgetattr.mtime_sec); 712 l9p_pu64(msg, &fcall->rgetattr.mtime_nsec); 713 l9p_pu64(msg, &fcall->rgetattr.ctime_sec); 714 l9p_pu64(msg, &fcall->rgetattr.ctime_nsec); 715 l9p_pu64(msg, &fcall->rgetattr.btime_sec); 716 l9p_pu64(msg, &fcall->rgetattr.btime_nsec); 717 l9p_pu64(msg, &fcall->rgetattr.gen); 718 r = l9p_pu64(msg, &fcall->rgetattr.data_version); 719 break; 720 721 case L9P_TSETATTR: 722 l9p_pu32(msg, &fcall->hdr.fid); 723 l9p_pu32(msg, &fcall->tsetattr.valid); 724 l9p_pu32(msg, &fcall->tsetattr.mode); 725 l9p_pu32(msg, &fcall->tsetattr.uid); 726 l9p_pu32(msg, &fcall->tsetattr.gid); 727 l9p_pu64(msg, &fcall->tsetattr.size); 728 l9p_pu64(msg, &fcall->tsetattr.atime_sec); 729 l9p_pu64(msg, &fcall->tsetattr.atime_nsec); 730 l9p_pu64(msg, &fcall->tsetattr.mtime_sec); 731 r = l9p_pu64(msg, &fcall->tsetattr.mtime_nsec); 732 break; 733 734 case L9P_RSETATTR: 735 break; 736 737 case L9P_TXATTRWALK: 738 l9p_pu32(msg, &fcall->hdr.fid); 739 l9p_pu32(msg, &fcall->txattrwalk.newfid); 740 r = l9p_pustring(msg, &fcall->txattrwalk.name); 741 break; 742 743 case L9P_RXATTRWALK: 744 r = l9p_pu64(msg, &fcall->rxattrwalk.size); 745 break; 746 747 case L9P_TXATTRCREATE: 748 l9p_pu32(msg, &fcall->hdr.fid); 749 r = l9p_pustring(msg, &fcall->txattrcreate.name); 750 if (r < 0) 751 break; 752 l9p_pu64(msg, &fcall->txattrcreate.attr_size); 753 r = l9p_pu32(msg, &fcall->txattrcreate.flags); 754 break; 755 756 case L9P_RXATTRCREATE: 757 break; 758 759 case L9P_TFSYNC: 760 r = l9p_pu32(msg, &fcall->hdr.fid); 761 break; 762 763 case L9P_RFSYNC: 764 break; 765 766 case L9P_TLOCK: 767 l9p_pu32(msg, &fcall->hdr.fid); 768 l9p_pu8(msg, &fcall->tlock.type); 769 l9p_pu32(msg, &fcall->tlock.flags); 770 l9p_pu64(msg, &fcall->tlock.start); 771 l9p_pu64(msg, &fcall->tlock.length); 772 l9p_pu32(msg, &fcall->tlock.proc_id); 773 r = l9p_pustring(msg, &fcall->tlock.client_id); 774 break; 775 776 case L9P_RLOCK: 777 r = l9p_pu8(msg, &fcall->rlock.status); 778 break; 779 780 case L9P_TGETLOCK: 781 l9p_pu32(msg, &fcall->hdr.fid); 782 /* FALLTHROUGH */ 783 784 case L9P_RGETLOCK: 785 l9p_pu8(msg, &fcall->getlock.type); 786 l9p_pu64(msg, &fcall->getlock.start); 787 l9p_pu64(msg, &fcall->getlock.length); 788 l9p_pu32(msg, &fcall->getlock.proc_id); 789 r = l9p_pustring(msg, &fcall->getlock.client_id); 790 break; 791 792 case L9P_TLINK: 793 l9p_pu32(msg, &fcall->tlink.dfid); 794 l9p_pu32(msg, &fcall->hdr.fid); 795 r = l9p_pustring(msg, &fcall->tlink.name); 796 break; 797 798 case L9P_RLINK: 799 break; 800 801 case L9P_TMKDIR: 802 l9p_pu32(msg, &fcall->hdr.fid); 803 r = l9p_pustring(msg, &fcall->tmkdir.name); 804 if (r < 0) 805 break; 806 l9p_pu32(msg, &fcall->tmkdir.mode); 807 r = l9p_pu32(msg, &fcall->tmkdir.gid); 808 break; 809 810 case L9P_RMKDIR: 811 r = l9p_puqid(msg, &fcall->rmkdir.qid); 812 break; 813 814 case L9P_TRENAMEAT: 815 l9p_pu32(msg, &fcall->hdr.fid); 816 r = l9p_pustring(msg, &fcall->trenameat.oldname); 817 if (r < 0) 818 break; 819 l9p_pu32(msg, &fcall->trenameat.newdirfid); 820 r = l9p_pustring(msg, &fcall->trenameat.newname); 821 break; 822 823 case L9P_RRENAMEAT: 824 break; 825 826 case L9P_TUNLINKAT: 827 l9p_pu32(msg, &fcall->hdr.fid); 828 r = l9p_pustring(msg, &fcall->tunlinkat.name); 829 if (r < 0) 830 break; 831 r = l9p_pu32(msg, &fcall->tunlinkat.flags); 832 break; 833 834 case L9P_RUNLINKAT: 835 break; 836 837 default: 838 L9P_LOG(L9P_ERROR, "%s(): missing case for type %d", 839 __func__, fcall->hdr.type); 840 break; 841 } 842 843 /* Check for over- or under-run, or pustring error. */ 844 if (r < 0) 845 return (-1); 846 847 if (msg->lm_mode == L9P_PACK) { 848 /* Rewind to the beginning and install size at front. */ 849 uint32_t len = (uint32_t)msg->lm_size; 850 msg->lm_cursor_offset = 0; 851 msg->lm_cursor_iov = 0; 852 853 /* 854 * Subtract 4 bytes from current size, becase we're 855 * overwriting size (rewinding message to the beginning) 856 * and writing again, which will increase it 4 more. 857 */ 858 msg->lm_size -= sizeof(uint32_t); 859 860 if (fcall->hdr.type == L9P_RREAD || 861 fcall->hdr.type == L9P_RREADDIR) 862 len += fcall->io.count; 863 864 l9p_pu32(msg, &len); 865 } 866 867 return (0); 868 } 869 870 /* 871 * Free any strings or other data malloc'ed in the process of 872 * packing or unpacking an fcall. 873 */ 874 void 875 l9p_freefcall(union l9p_fcall *fcall) 876 { 877 uint16_t i; 878 879 switch (fcall->hdr.type) { 880 881 case L9P_TVERSION: 882 case L9P_RVERSION: 883 free(fcall->version.version); 884 return; 885 886 case L9P_TATTACH: 887 free(fcall->tattach.aname); 888 free(fcall->tattach.uname); 889 return; 890 891 case L9P_TWALK: 892 for (i = 0; i < fcall->twalk.nwname; i++) 893 free(fcall->twalk.wname[i]); 894 return; 895 896 case L9P_TCREATE: 897 case L9P_TOPEN: 898 free(fcall->tcreate.name); 899 free(fcall->tcreate.extension); 900 return; 901 902 case L9P_RSTAT: 903 l9p_freestat(&fcall->rstat.stat); 904 return; 905 906 case L9P_TWSTAT: 907 l9p_freestat(&fcall->twstat.stat); 908 return; 909 910 case L9P_TLCREATE: 911 free(fcall->tlcreate.name); 912 return; 913 914 case L9P_TSYMLINK: 915 free(fcall->tsymlink.name); 916 free(fcall->tsymlink.symtgt); 917 return; 918 919 case L9P_TMKNOD: 920 free(fcall->tmknod.name); 921 return; 922 923 case L9P_TRENAME: 924 free(fcall->trename.name); 925 return; 926 927 case L9P_RREADLINK: 928 free(fcall->rreadlink.target); 929 return; 930 931 case L9P_TXATTRWALK: 932 free(fcall->txattrwalk.name); 933 return; 934 935 case L9P_TXATTRCREATE: 936 free(fcall->txattrcreate.name); 937 return; 938 939 case L9P_TLOCK: 940 free(fcall->tlock.client_id); 941 return; 942 943 case L9P_TGETLOCK: 944 case L9P_RGETLOCK: 945 free(fcall->getlock.client_id); 946 return; 947 948 case L9P_TLINK: 949 free(fcall->tlink.name); 950 return; 951 952 case L9P_TMKDIR: 953 free(fcall->tmkdir.name); 954 return; 955 956 case L9P_TRENAMEAT: 957 free(fcall->trenameat.oldname); 958 free(fcall->trenameat.newname); 959 return; 960 961 case L9P_TUNLINKAT: 962 free(fcall->tunlinkat.name); 963 return; 964 } 965 } 966 967 void 968 l9p_freestat(struct l9p_stat *stat) 969 { 970 free(stat->name); 971 free(stat->extension); 972 free(stat->uid); 973 free(stat->gid); 974 free(stat->muid); 975 } 976 977 uint16_t 978 l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version) 979 { 980 uint16_t size = L9P_WORD /* size */ 981 + L9P_WORD /* type */ 982 + L9P_DWORD /* dev */ 983 + QID_SIZE /* qid */ 984 + 3 * L9P_DWORD /* mode, atime, mtime */ 985 + L9P_QWORD /* length */ 986 + STRING_SIZE(stat->name) 987 + STRING_SIZE(stat->uid) 988 + STRING_SIZE(stat->gid) 989 + STRING_SIZE(stat->muid); 990 991 if (version >= L9P_2000U) { 992 size += STRING_SIZE(stat->extension) 993 + 3 * L9P_DWORD; 994 } 995 996 return (size); 997 } 998