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 for (i = 0, lim = *num; i < lim; i++) { 348 ret = l9p_puqid(msg, &qids[i]); 349 if (ret < 0) 350 return (-1); 351 r += ret; 352 } 353 } 354 return (r); 355 } 356 357 /* 358 * Pack or unpack a l9p_stat. 359 * 360 * These have variable size, and the size further depends on 361 * the protocol version. 362 * 363 * Returns the number of bytes packed/unpacked, or -1 on error. 364 */ 365 ssize_t 366 l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat, 367 enum l9p_version version) 368 { 369 ssize_t r = 0; 370 uint16_t size; 371 372 /* The on-wire size field excludes the size of the size field. */ 373 if (msg->lm_mode == L9P_PACK) 374 size = l9p_sizeof_stat(stat, version) - 2; 375 376 r += l9p_pu16(msg, &size); 377 r += l9p_pu16(msg, &stat->type); 378 r += l9p_pu32(msg, &stat->dev); 379 r += l9p_puqid(msg, &stat->qid); 380 r += l9p_pu32(msg, &stat->mode); 381 r += l9p_pu32(msg, &stat->atime); 382 r += l9p_pu32(msg, &stat->mtime); 383 r += l9p_pu64(msg, &stat->length); 384 r += l9p_pustring(msg, &stat->name); 385 r += l9p_pustring(msg, &stat->uid); 386 r += l9p_pustring(msg, &stat->gid); 387 r += l9p_pustring(msg, &stat->muid); 388 389 if (version >= L9P_2000U) { 390 r += l9p_pustring(msg, &stat->extension); 391 r += l9p_pu32(msg, &stat->n_uid); 392 r += l9p_pu32(msg, &stat->n_gid); 393 r += l9p_pu32(msg, &stat->n_muid); 394 } 395 396 if (r < size + 2) 397 return (-1); 398 399 return (r); 400 } 401 402 /* 403 * Pack or unpack a variable-length dirent. 404 * 405 * If unpacking, the name field is malloc()ed and the caller must 406 * free it. 407 * 408 * Returns the wire-format length, or -1 if we ran out of room. 409 */ 410 ssize_t 411 l9p_pudirent(struct l9p_message *msg, struct l9p_dirent *de) 412 { 413 ssize_t r, s; 414 415 r = l9p_puqid(msg, &de->qid); 416 r += l9p_pu64(msg, &de->offset); 417 r += l9p_pu8(msg, &de->type); 418 s = l9p_pustring(msg, &de->name); 419 if (r < QID_SIZE + 8 + 1 || s < 0) 420 return (-1); 421 return (r + s); 422 } 423 424 /* 425 * Pack or unpack a request or response (fcall). 426 * 427 * Returns 0 on success, -1 on error. (It's up to the caller 428 * to call l9p_freefcall on our failure.) 429 */ 430 int 431 l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall, 432 enum l9p_version version) 433 { 434 uint32_t length = 0; 435 ssize_t r; 436 437 /* 438 * Get overall length, type, and tag, which should appear 439 * in all messages. If not even that works, abort immediately. 440 */ 441 l9p_pu32(msg, &length); 442 l9p_pu8(msg, &fcall->hdr.type); 443 r = l9p_pu16(msg, &fcall->hdr.tag); 444 if (r < 0) 445 return (-1); 446 447 /* 448 * Decode remainder of message. When unpacking, this may 449 * allocate memory, even if we fail during the decode. 450 * Note that the initial fcall is zeroed out, though, so 451 * we can just freefcall() to release whatever might have 452 * gotten allocated, if the unpack fails due to a short 453 * packet. 454 */ 455 switch (fcall->hdr.type) { 456 case L9P_TVERSION: 457 case L9P_RVERSION: 458 l9p_pu32(msg, &fcall->version.msize); 459 r = l9p_pustring(msg, &fcall->version.version); 460 break; 461 462 case L9P_TAUTH: 463 l9p_pu32(msg, &fcall->tauth.afid); 464 r = l9p_pustring(msg, &fcall->tauth.uname); 465 if (r < 0) 466 break; 467 r = l9p_pustring(msg, &fcall->tauth.aname); 468 if (r < 0) 469 break; 470 if (version >= L9P_2000U) 471 r = l9p_pu32(msg, &fcall->tauth.n_uname); 472 break; 473 474 case L9P_RAUTH: 475 r = l9p_puqid(msg, &fcall->rauth.aqid); 476 break; 477 478 case L9P_TATTACH: 479 l9p_pu32(msg, &fcall->hdr.fid); 480 l9p_pu32(msg, &fcall->tattach.afid); 481 r = l9p_pustring(msg, &fcall->tattach.uname); 482 if (r < 0) 483 break; 484 r = l9p_pustring(msg, &fcall->tattach.aname); 485 if (r < 0) 486 break; 487 if (version >= L9P_2000U) 488 r = l9p_pu32(msg, &fcall->tattach.n_uname); 489 break; 490 491 case L9P_RATTACH: 492 r = l9p_puqid(msg, &fcall->rattach.qid); 493 break; 494 495 case L9P_RERROR: 496 r = l9p_pustring(msg, &fcall->error.ename); 497 if (r < 0) 498 break; 499 if (version >= L9P_2000U) 500 r = l9p_pu32(msg, &fcall->error.errnum); 501 break; 502 503 case L9P_RLERROR: 504 r = l9p_pu32(msg, &fcall->error.errnum); 505 break; 506 507 case L9P_TFLUSH: 508 r = l9p_pu16(msg, &fcall->tflush.oldtag); 509 break; 510 511 case L9P_RFLUSH: 512 break; 513 514 case L9P_TWALK: 515 l9p_pu32(msg, &fcall->hdr.fid); 516 l9p_pu32(msg, &fcall->twalk.newfid); 517 r = l9p_pustrings(msg, &fcall->twalk.nwname, 518 fcall->twalk.wname, N(fcall->twalk.wname)); 519 break; 520 521 case L9P_RWALK: 522 r = l9p_puqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid); 523 break; 524 525 case L9P_TOPEN: 526 l9p_pu32(msg, &fcall->hdr.fid); 527 r = l9p_pu8(msg, &fcall->topen.mode); 528 break; 529 530 case L9P_ROPEN: 531 l9p_puqid(msg, &fcall->ropen.qid); 532 r = l9p_pu32(msg, &fcall->ropen.iounit); 533 break; 534 535 case L9P_TCREATE: 536 l9p_pu32(msg, &fcall->hdr.fid); 537 r = l9p_pustring(msg, &fcall->tcreate.name); 538 if (r < 0) 539 break; 540 l9p_pu32(msg, &fcall->tcreate.perm); 541 r = l9p_pu8(msg, &fcall->tcreate.mode); 542 if (version >= L9P_2000U) 543 r = l9p_pustring(msg, &fcall->tcreate.extension); 544 break; 545 546 case L9P_RCREATE: 547 l9p_puqid(msg, &fcall->rcreate.qid); 548 r = l9p_pu32(msg, &fcall->rcreate.iounit); 549 break; 550 551 case L9P_TREAD: 552 case L9P_TREADDIR: 553 l9p_pu32(msg, &fcall->hdr.fid); 554 l9p_pu64(msg, &fcall->io.offset); 555 r = l9p_pu32(msg, &fcall->io.count); 556 break; 557 558 case L9P_RREAD: 559 case L9P_RREADDIR: 560 r = l9p_pu32(msg, &fcall->io.count); 561 break; 562 563 case L9P_TWRITE: 564 l9p_pu32(msg, &fcall->hdr.fid); 565 l9p_pu64(msg, &fcall->io.offset); 566 r = l9p_pu32(msg, &fcall->io.count); 567 break; 568 569 case L9P_RWRITE: 570 r = l9p_pu32(msg, &fcall->io.count); 571 break; 572 573 case L9P_TCLUNK: 574 case L9P_TSTAT: 575 case L9P_TREMOVE: 576 case L9P_TSTATFS: 577 r = l9p_pu32(msg, &fcall->hdr.fid); 578 break; 579 580 case L9P_RCLUNK: 581 case L9P_RREMOVE: 582 break; 583 584 case L9P_RSTAT: 585 { 586 uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat, 587 version); 588 l9p_pu16(msg, &size); 589 r = l9p_pustat(msg, &fcall->rstat.stat, version); 590 } 591 break; 592 593 case L9P_TWSTAT: 594 { 595 uint16_t size; 596 l9p_pu32(msg, &fcall->hdr.fid); 597 l9p_pu16(msg, &size); 598 r = l9p_pustat(msg, &fcall->twstat.stat, version); 599 } 600 break; 601 602 case L9P_RWSTAT: 603 break; 604 605 case L9P_RSTATFS: 606 l9p_pu32(msg, &fcall->rstatfs.statfs.type); 607 l9p_pu32(msg, &fcall->rstatfs.statfs.bsize); 608 l9p_pu64(msg, &fcall->rstatfs.statfs.blocks); 609 l9p_pu64(msg, &fcall->rstatfs.statfs.bfree); 610 l9p_pu64(msg, &fcall->rstatfs.statfs.bavail); 611 l9p_pu64(msg, &fcall->rstatfs.statfs.files); 612 l9p_pu64(msg, &fcall->rstatfs.statfs.ffree); 613 l9p_pu64(msg, &fcall->rstatfs.statfs.fsid); 614 r = l9p_pu32(msg, &fcall->rstatfs.statfs.namelen); 615 break; 616 617 case L9P_TLOPEN: 618 l9p_pu32(msg, &fcall->hdr.fid); 619 r = l9p_pu32(msg, &fcall->tlopen.flags); 620 break; 621 622 case L9P_RLOPEN: 623 l9p_puqid(msg, &fcall->rlopen.qid); 624 r = l9p_pu32(msg, &fcall->rlopen.iounit); 625 break; 626 627 case L9P_TLCREATE: 628 l9p_pu32(msg, &fcall->hdr.fid); 629 r = l9p_pustring(msg, &fcall->tlcreate.name); 630 if (r < 0) 631 break; 632 l9p_pu32(msg, &fcall->tlcreate.flags); 633 l9p_pu32(msg, &fcall->tlcreate.mode); 634 r = l9p_pu32(msg, &fcall->tlcreate.gid); 635 break; 636 637 case L9P_RLCREATE: 638 l9p_puqid(msg, &fcall->rlcreate.qid); 639 r = l9p_pu32(msg, &fcall->rlcreate.iounit); 640 break; 641 642 case L9P_TSYMLINK: 643 l9p_pu32(msg, &fcall->hdr.fid); 644 r = l9p_pustring(msg, &fcall->tsymlink.name); 645 if (r < 0) 646 break; 647 r = l9p_pustring(msg, &fcall->tsymlink.symtgt); 648 if (r < 0) 649 break; 650 r = l9p_pu32(msg, &fcall->tlcreate.gid); 651 break; 652 653 case L9P_RSYMLINK: 654 r = l9p_puqid(msg, &fcall->rsymlink.qid); 655 break; 656 657 case L9P_TMKNOD: 658 l9p_pu32(msg, &fcall->hdr.fid); 659 r = l9p_pustring(msg, &fcall->tmknod.name); 660 if (r < 0) 661 break; 662 l9p_pu32(msg, &fcall->tmknod.mode); 663 l9p_pu32(msg, &fcall->tmknod.major); 664 l9p_pu32(msg, &fcall->tmknod.minor); 665 r = l9p_pu32(msg, &fcall->tmknod.gid); 666 break; 667 668 case L9P_RMKNOD: 669 r = l9p_puqid(msg, &fcall->rmknod.qid); 670 break; 671 672 case L9P_TRENAME: 673 l9p_pu32(msg, &fcall->hdr.fid); 674 l9p_pu32(msg, &fcall->trename.dfid); 675 r = l9p_pustring(msg, &fcall->trename.name); 676 break; 677 678 case L9P_RRENAME: 679 break; 680 681 case L9P_TREADLINK: 682 r = l9p_pu32(msg, &fcall->hdr.fid); 683 break; 684 685 case L9P_RREADLINK: 686 r = l9p_pustring(msg, &fcall->rreadlink.target); 687 break; 688 689 case L9P_TGETATTR: 690 l9p_pu32(msg, &fcall->hdr.fid); 691 r = l9p_pu64(msg, &fcall->tgetattr.request_mask); 692 break; 693 694 case L9P_RGETATTR: 695 l9p_pu64(msg, &fcall->rgetattr.valid); 696 l9p_puqid(msg, &fcall->rgetattr.qid); 697 l9p_pu32(msg, &fcall->rgetattr.mode); 698 l9p_pu32(msg, &fcall->rgetattr.uid); 699 l9p_pu32(msg, &fcall->rgetattr.gid); 700 l9p_pu64(msg, &fcall->rgetattr.nlink); 701 l9p_pu64(msg, &fcall->rgetattr.rdev); 702 l9p_pu64(msg, &fcall->rgetattr.size); 703 l9p_pu64(msg, &fcall->rgetattr.blksize); 704 l9p_pu64(msg, &fcall->rgetattr.blocks); 705 l9p_pu64(msg, &fcall->rgetattr.atime_sec); 706 l9p_pu64(msg, &fcall->rgetattr.atime_nsec); 707 l9p_pu64(msg, &fcall->rgetattr.mtime_sec); 708 l9p_pu64(msg, &fcall->rgetattr.mtime_nsec); 709 l9p_pu64(msg, &fcall->rgetattr.ctime_sec); 710 l9p_pu64(msg, &fcall->rgetattr.ctime_nsec); 711 l9p_pu64(msg, &fcall->rgetattr.btime_sec); 712 l9p_pu64(msg, &fcall->rgetattr.btime_nsec); 713 l9p_pu64(msg, &fcall->rgetattr.gen); 714 r = l9p_pu64(msg, &fcall->rgetattr.data_version); 715 break; 716 717 case L9P_TSETATTR: 718 l9p_pu32(msg, &fcall->hdr.fid); 719 l9p_pu32(msg, &fcall->tsetattr.valid); 720 l9p_pu32(msg, &fcall->tsetattr.mode); 721 l9p_pu32(msg, &fcall->tsetattr.uid); 722 l9p_pu32(msg, &fcall->tsetattr.gid); 723 l9p_pu64(msg, &fcall->tsetattr.size); 724 l9p_pu64(msg, &fcall->tsetattr.atime_sec); 725 l9p_pu64(msg, &fcall->tsetattr.atime_nsec); 726 l9p_pu64(msg, &fcall->tsetattr.mtime_sec); 727 r = l9p_pu64(msg, &fcall->tsetattr.mtime_nsec); 728 break; 729 730 case L9P_RSETATTR: 731 break; 732 733 case L9P_TXATTRWALK: 734 l9p_pu32(msg, &fcall->hdr.fid); 735 l9p_pu32(msg, &fcall->txattrwalk.newfid); 736 r = l9p_pustring(msg, &fcall->txattrwalk.name); 737 break; 738 739 case L9P_RXATTRWALK: 740 r = l9p_pu64(msg, &fcall->rxattrwalk.size); 741 break; 742 743 case L9P_TXATTRCREATE: 744 l9p_pu32(msg, &fcall->hdr.fid); 745 r = l9p_pustring(msg, &fcall->txattrcreate.name); 746 if (r < 0) 747 break; 748 l9p_pu64(msg, &fcall->txattrcreate.attr_size); 749 r = l9p_pu32(msg, &fcall->txattrcreate.flags); 750 break; 751 752 case L9P_RXATTRCREATE: 753 break; 754 755 case L9P_TFSYNC: 756 r = l9p_pu32(msg, &fcall->hdr.fid); 757 break; 758 759 case L9P_RFSYNC: 760 break; 761 762 case L9P_TLOCK: 763 l9p_pu32(msg, &fcall->hdr.fid); 764 l9p_pu8(msg, &fcall->tlock.type); 765 l9p_pu32(msg, &fcall->tlock.flags); 766 l9p_pu64(msg, &fcall->tlock.start); 767 l9p_pu64(msg, &fcall->tlock.length); 768 l9p_pu32(msg, &fcall->tlock.proc_id); 769 r = l9p_pustring(msg, &fcall->tlock.client_id); 770 break; 771 772 case L9P_RLOCK: 773 r = l9p_pu8(msg, &fcall->rlock.status); 774 break; 775 776 case L9P_TGETLOCK: 777 l9p_pu32(msg, &fcall->hdr.fid); 778 /* FALLTHROUGH */ 779 780 case L9P_RGETLOCK: 781 l9p_pu8(msg, &fcall->getlock.type); 782 l9p_pu64(msg, &fcall->getlock.start); 783 l9p_pu64(msg, &fcall->getlock.length); 784 l9p_pu32(msg, &fcall->getlock.proc_id); 785 r = l9p_pustring(msg, &fcall->getlock.client_id); 786 break; 787 788 case L9P_TLINK: 789 l9p_pu32(msg, &fcall->tlink.dfid); 790 l9p_pu32(msg, &fcall->hdr.fid); 791 r = l9p_pustring(msg, &fcall->tlink.name); 792 break; 793 794 case L9P_RLINK: 795 break; 796 797 case L9P_TMKDIR: 798 l9p_pu32(msg, &fcall->hdr.fid); 799 r = l9p_pustring(msg, &fcall->tmkdir.name); 800 if (r < 0) 801 break; 802 l9p_pu32(msg, &fcall->tmkdir.mode); 803 r = l9p_pu32(msg, &fcall->tmkdir.gid); 804 break; 805 806 case L9P_RMKDIR: 807 r = l9p_puqid(msg, &fcall->rmkdir.qid); 808 break; 809 810 case L9P_TRENAMEAT: 811 l9p_pu32(msg, &fcall->hdr.fid); 812 r = l9p_pustring(msg, &fcall->trenameat.oldname); 813 if (r < 0) 814 break; 815 l9p_pu32(msg, &fcall->trenameat.newdirfid); 816 r = l9p_pustring(msg, &fcall->trenameat.newname); 817 break; 818 819 case L9P_RRENAMEAT: 820 break; 821 822 case L9P_TUNLINKAT: 823 l9p_pu32(msg, &fcall->hdr.fid); 824 r = l9p_pustring(msg, &fcall->tunlinkat.name); 825 if (r < 0) 826 break; 827 r = l9p_pu32(msg, &fcall->tunlinkat.flags); 828 break; 829 830 case L9P_RUNLINKAT: 831 break; 832 833 default: 834 L9P_LOG(L9P_ERROR, "%s(): missing case for type %d", 835 __func__, fcall->hdr.type); 836 break; 837 } 838 839 /* Check for over- or under-run, or pustring error. */ 840 if (r < 0) 841 return (-1); 842 843 if (msg->lm_mode == L9P_PACK) { 844 /* Rewind to the beginning and install size at front. */ 845 uint32_t len = (uint32_t)msg->lm_size; 846 msg->lm_cursor_offset = 0; 847 msg->lm_cursor_iov = 0; 848 849 /* 850 * Subtract 4 bytes from current size, becase we're 851 * overwriting size (rewinding message to the beginning) 852 * and writing again, which will increase it 4 more. 853 */ 854 msg->lm_size -= sizeof(uint32_t); 855 856 if (fcall->hdr.type == L9P_RREAD || 857 fcall->hdr.type == L9P_RREADDIR) 858 len += fcall->io.count; 859 860 l9p_pu32(msg, &len); 861 } 862 863 return (0); 864 } 865 866 /* 867 * Free any strings or other data malloc'ed in the process of 868 * packing or unpacking an fcall. 869 */ 870 void 871 l9p_freefcall(union l9p_fcall *fcall) 872 { 873 uint16_t i; 874 875 switch (fcall->hdr.type) { 876 877 case L9P_TVERSION: 878 case L9P_RVERSION: 879 free(fcall->version.version); 880 return; 881 882 case L9P_TATTACH: 883 free(fcall->tattach.aname); 884 free(fcall->tattach.uname); 885 return; 886 887 case L9P_TWALK: 888 for (i = 0; i < fcall->twalk.nwname; i++) 889 free(fcall->twalk.wname[i]); 890 return; 891 892 case L9P_TCREATE: 893 case L9P_TOPEN: 894 free(fcall->tcreate.name); 895 free(fcall->tcreate.extension); 896 return; 897 898 case L9P_RSTAT: 899 l9p_freestat(&fcall->rstat.stat); 900 return; 901 902 case L9P_TWSTAT: 903 l9p_freestat(&fcall->twstat.stat); 904 return; 905 906 case L9P_TLCREATE: 907 free(fcall->tlcreate.name); 908 return; 909 910 case L9P_TSYMLINK: 911 free(fcall->tsymlink.name); 912 free(fcall->tsymlink.symtgt); 913 return; 914 915 case L9P_TMKNOD: 916 free(fcall->tmknod.name); 917 return; 918 919 case L9P_TRENAME: 920 free(fcall->trename.name); 921 return; 922 923 case L9P_RREADLINK: 924 free(fcall->rreadlink.target); 925 return; 926 927 case L9P_TXATTRWALK: 928 free(fcall->txattrwalk.name); 929 return; 930 931 case L9P_TXATTRCREATE: 932 free(fcall->txattrcreate.name); 933 return; 934 935 case L9P_TLOCK: 936 free(fcall->tlock.client_id); 937 return; 938 939 case L9P_TGETLOCK: 940 case L9P_RGETLOCK: 941 free(fcall->getlock.client_id); 942 return; 943 944 case L9P_TLINK: 945 free(fcall->tlink.name); 946 return; 947 948 case L9P_TMKDIR: 949 free(fcall->tmkdir.name); 950 return; 951 952 case L9P_TRENAMEAT: 953 free(fcall->trenameat.oldname); 954 free(fcall->trenameat.newname); 955 return; 956 957 case L9P_TUNLINKAT: 958 free(fcall->tunlinkat.name); 959 return; 960 } 961 } 962 963 void 964 l9p_freestat(struct l9p_stat *stat) 965 { 966 free(stat->name); 967 free(stat->extension); 968 free(stat->uid); 969 free(stat->gid); 970 free(stat->muid); 971 } 972 973 uint16_t 974 l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version) 975 { 976 uint16_t size = L9P_WORD /* size */ 977 + L9P_WORD /* type */ 978 + L9P_DWORD /* dev */ 979 + QID_SIZE /* qid */ 980 + 3 * L9P_DWORD /* mode, atime, mtime */ 981 + L9P_QWORD /* length */ 982 + STRING_SIZE(stat->name) 983 + STRING_SIZE(stat->uid) 984 + STRING_SIZE(stat->gid) 985 + STRING_SIZE(stat->muid); 986 987 if (version >= L9P_2000U) { 988 size += STRING_SIZE(stat->extension) 989 + 3 * L9P_DWORD; 990 } 991 992 return (size); 993 } 994