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 #include <errno.h> 29 #include <stdbool.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <unistd.h> 34 #include <assert.h> 35 #include <inttypes.h> 36 #include <limits.h> 37 #include <sys/param.h> 38 #include <sys/stat.h> 39 #include <sys/uio.h> 40 #if defined(__FreeBSD__) 41 #include <sys/sbuf.h> 42 #else 43 #include "sbuf/sbuf.h" 44 #endif 45 #include "lib9p.h" 46 #include "fcall.h" 47 #include "linux_errno.h" 48 49 #ifdef __illumos__ 50 #include <sys/sysmacros.h> 51 #include <grp.h> 52 #endif 53 54 #ifdef __APPLE__ 55 #define GETGROUPS_GROUP_TYPE_IS_INT 56 #endif 57 58 #define N(ary) (sizeof(ary) / sizeof(*ary)) 59 60 /* See l9p_describe_bits() below. */ 61 struct descbits { 62 uint64_t db_mask; /* mask value */ 63 uint64_t db_match; /* match value */ 64 const char *db_name; /* name for matched value */ 65 }; 66 67 68 static bool l9p_describe_bits(const char *, uint64_t, const char *, 69 const struct descbits *, struct sbuf *); 70 static void l9p_describe_fid(const char *, uint32_t, struct sbuf *); 71 static void l9p_describe_mode(const char *, uint32_t, struct sbuf *); 72 static void l9p_describe_name(const char *, char *, struct sbuf *); 73 static void l9p_describe_perm(const char *, uint32_t, struct sbuf *); 74 static void l9p_describe_lperm(const char *, uint32_t, struct sbuf *); 75 static void l9p_describe_qid(const char *, struct l9p_qid *, struct sbuf *); 76 static void l9p_describe_l9stat(const char *, struct l9p_stat *, 77 enum l9p_version, struct sbuf *); 78 static void l9p_describe_statfs(const char *, struct l9p_statfs *, 79 struct sbuf *); 80 static void l9p_describe_time(struct sbuf *, const char *, uint64_t, uint64_t); 81 static void l9p_describe_readdir(struct sbuf *, struct l9p_f_io *); 82 static void l9p_describe_size(const char *, uint64_t, struct sbuf *); 83 static void l9p_describe_ugid(const char *, uint32_t, struct sbuf *); 84 static void l9p_describe_getattr_mask(uint64_t, struct sbuf *); 85 static void l9p_describe_unlinkat_flags(const char *, uint32_t, struct sbuf *); 86 static const char *lookup_linux_errno(uint32_t, char *, size_t); 87 88 /* 89 * Using indexed initializers, we can have these occur in any order. 90 * Using adjacent-string concatenation ("T" #name, "R" #name), we 91 * get both Tfoo and Rfoo strings with one copy of the name. 92 * Alas, there is no stupid cpp trick to lowercase-ify, so we 93 * have to write each name twice. In which case we might as well 94 * make the second one a string in the first place and not bother 95 * with the stringizing. 96 * 97 * This table should have entries for each enum value in fcall.h. 98 */ 99 #define X(NAME, name) [L9P_T##NAME - L9P__FIRST] = "T" name, \ 100 [L9P_R##NAME - L9P__FIRST] = "R" name 101 static const char *ftype_names[] = { 102 X(VERSION, "version"), 103 X(AUTH, "auth"), 104 X(ATTACH, "attach"), 105 X(ERROR, "error"), 106 X(LERROR, "lerror"), 107 X(FLUSH, "flush"), 108 X(WALK, "walk"), 109 X(OPEN, "open"), 110 X(CREATE, "create"), 111 X(READ, "read"), 112 X(WRITE, "write"), 113 X(CLUNK, "clunk"), 114 X(REMOVE, "remove"), 115 X(STAT, "stat"), 116 X(WSTAT, "wstat"), 117 X(STATFS, "statfs"), 118 X(LOPEN, "lopen"), 119 X(LCREATE, "lcreate"), 120 X(SYMLINK, "symlink"), 121 X(MKNOD, "mknod"), 122 X(RENAME, "rename"), 123 X(READLINK, "readlink"), 124 X(GETATTR, "getattr"), 125 X(SETATTR, "setattr"), 126 X(XATTRWALK, "xattrwalk"), 127 X(XATTRCREATE, "xattrcreate"), 128 X(READDIR, "readdir"), 129 X(FSYNC, "fsync"), 130 X(LOCK, "lock"), 131 X(GETLOCK, "getlock"), 132 X(LINK, "link"), 133 X(MKDIR, "mkdir"), 134 X(RENAMEAT, "renameat"), 135 X(UNLINKAT, "unlinkat"), 136 }; 137 #undef X 138 139 void 140 l9p_seek_iov(const struct iovec *iov1, size_t niov1, struct iovec *iov2, 141 size_t *niov2, size_t seek) 142 { 143 size_t remainder = 0; 144 size_t left = seek; 145 size_t i, j; 146 147 assert(niov1 <= L9P_MAX_IOV); 148 149 for (i = 0; i < niov1; i++) { 150 size_t toseek = MIN(left, iov1[i].iov_len); 151 left -= toseek; 152 153 if (toseek == iov1[i].iov_len) 154 continue; 155 156 if (left == 0) { 157 remainder = toseek; 158 break; 159 } 160 } 161 162 for (j = i; j < niov1; j++) { 163 iov2[j - i].iov_base = (char *)iov1[j].iov_base + remainder; 164 iov2[j - i].iov_len = iov1[j].iov_len - remainder; 165 remainder = 0; 166 } 167 168 *niov2 = j - i; 169 } 170 171 size_t 172 l9p_truncate_iov(struct iovec *iov, size_t niov, size_t length) 173 { 174 size_t i, done = 0; 175 176 for (i = 0; i < niov; i++) { 177 size_t toseek = MIN(length - done, iov[i].iov_len); 178 done += toseek; 179 180 if (toseek < iov[i].iov_len) { 181 iov[i].iov_len = toseek; 182 return (i + 1); 183 } 184 } 185 186 return (niov); 187 } 188 189 /* 190 * This wrapper for getgrouplist() that calloc'ed memory, and 191 * papers over FreeBSD vs Mac differences in the getgrouplist() 192 * argument types. 193 * 194 * Note that this function guarantees that *either*: 195 * return value != NULL and *angroups has been set 196 * or: return value == NULL and *angroups is 0 197 */ 198 gid_t * 199 l9p_getgrlist(const char *name, gid_t basegid, int *angroups) 200 { 201 #ifdef GETGROUPS_GROUP_TYPE_IS_INT 202 int i, *int_groups; 203 #endif 204 gid_t *groups; 205 int ngroups; 206 207 /* 208 * Todo, perhaps: while getgrouplist() returns -1, expand. 209 * For now just use NGROUPS_MAX. 210 */ 211 ngroups = NGROUPS_MAX; 212 groups = calloc((size_t)ngroups, sizeof(*groups)); 213 #ifdef GETGROUPS_GROUP_TYPE_IS_INT 214 int_groups = groups ? calloc((size_t)ngroups, sizeof(*int_groups)) : 215 NULL; 216 if (int_groups == NULL) { 217 free(groups); 218 groups = NULL; 219 } 220 #endif 221 if (groups == NULL) { 222 *angroups = 0; 223 return (NULL); 224 } 225 #ifdef GETGROUPS_GROUP_TYPE_IS_INT 226 if (getgrouplist(name, (int)basegid, int_groups, &ngroups) < 0) { 227 free(groups); 228 free(int_groups); 229 return (NULL); 230 } 231 for (i = 0; i < ngroups; i++) 232 groups[i] = (gid_t)int_groups[i]; 233 free(int_groups); 234 #else 235 if (getgrouplist(name, basegid, groups, &ngroups) < 0) { 236 free(groups); 237 return (NULL); 238 } 239 #endif 240 *angroups = ngroups; 241 return (groups); 242 } 243 244 /* 245 * For the various debug describe ops: decode bits in a bit-field-y 246 * value. For example, we might produce: 247 * value=0x3c[FOO,BAR,QUUX,?0x20] 248 * when FOO is bit 0x10, BAR is 0x08, and QUUX is 0x04 (as defined 249 * by the table). This leaves 0x20 (bit 5) as a mystery, while bits 250 * 4, 3, and 2 were decoded. (Bits 0 and 1 were 0 on input hence 251 * were not attempted here.) 252 * 253 * For general use we take a uint64_t <value>. The bit description 254 * table <db> is an array of {mask, match, str} values ending with 255 * {0, 0, NULL}. 256 * 257 * If <str> is non-NULL we'll print it and the mask as well (if 258 * str is NULL we'll print neither). The mask is always printed in 259 * hex at the moment. See undec description too. 260 * 261 * For convenience, you can use a mask-and-match value, e.g., to 262 * decode a 2-bit field in bits 0 and 1 you can mask against 3 and 263 * match the values 0, 1, 2, and 3. To handle this, make sure that 264 * all masks-with-same-match are sequential. 265 * 266 * If there are any nonzero undecoded bits, print them after 267 * all the decode-able bits have been handled. 268 * 269 * The <oc> argument defines the open and close bracket characters, 270 * typically "[]", that surround the entire string. If NULL, no 271 * brackets are added, else oc[0] goes in the front and oc[1] at 272 * the end, after printing any <str><value> part. 273 * 274 * Returns true if it printed anything (other than the implied 275 * str-and-value, that is). 276 */ 277 static bool 278 l9p_describe_bits(const char *str, uint64_t value, const char *oc, 279 const struct descbits *db, struct sbuf *sb) 280 { 281 const char *sep; 282 char bracketbuf[2] = ""; 283 bool printed = false; 284 285 if (str != NULL) 286 sbuf_printf(sb, "%s0x%" PRIx64, str, value); 287 288 if (oc != NULL) 289 bracketbuf[0] = oc[0]; 290 sep = bracketbuf; 291 for (; db->db_name != NULL; db++) { 292 if ((value & db->db_mask) == db->db_match) { 293 sbuf_printf(sb, "%s%s", sep, db->db_name); 294 sep = ","; 295 printed = true; 296 297 /* 298 * Clear the field, and make sure we 299 * won't match a zero-valued field with 300 * this same mask. 301 */ 302 value &= ~db->db_mask; 303 while (db[1].db_mask == db->db_mask && 304 db[1].db_name != NULL) 305 db++; 306 } 307 } 308 if (value != 0) { 309 sbuf_printf(sb, "%s?0x%" PRIx64, sep, value); 310 printed = true; 311 } 312 if (printed && oc != NULL) { 313 bracketbuf[0] = oc[1]; 314 sbuf_cat(sb, bracketbuf); 315 } 316 return (printed); 317 } 318 319 /* 320 * Show file ID. 321 */ 322 static void 323 l9p_describe_fid(const char *str, uint32_t fid, struct sbuf *sb) 324 { 325 326 sbuf_printf(sb, "%s%" PRIu32, str, fid); 327 } 328 329 /* 330 * Show user or group ID. 331 */ 332 static void 333 l9p_describe_ugid(const char *str, uint32_t ugid, struct sbuf *sb) 334 { 335 336 sbuf_printf(sb, "%s%" PRIu32, str, ugid); 337 } 338 339 /* 340 * Show file mode (O_RDWR, O_RDONLY, etc). The argument is 341 * an l9p_omode, not a Linux flags mode. Linux flags are 342 * decoded with l9p_describe_lflags. 343 */ 344 static void 345 l9p_describe_mode(const char *str, uint32_t mode, struct sbuf *sb) 346 { 347 static const struct descbits bits[] = { 348 { L9P_OACCMODE, L9P_OREAD, "OREAD" }, 349 { L9P_OACCMODE, L9P_OWRITE, "OWRITE" }, 350 { L9P_OACCMODE, L9P_ORDWR, "ORDWR" }, 351 { L9P_OACCMODE, L9P_OEXEC, "OEXEC" }, 352 353 { L9P_OCEXEC, L9P_OCEXEC, "OCEXEC" }, 354 { L9P_ODIRECT, L9P_ODIRECT, "ODIRECT" }, 355 { L9P_ORCLOSE, L9P_ORCLOSE, "ORCLOSE" }, 356 { L9P_OTRUNC, L9P_OTRUNC, "OTRUNC" }, 357 { 0, 0, NULL } 358 }; 359 360 (void) l9p_describe_bits(str, mode, "[]", bits, sb); 361 } 362 363 /* 364 * Show Linux mode/flags. 365 */ 366 static void 367 l9p_describe_lflags(const char *str, uint32_t flags, struct sbuf *sb) 368 { 369 static const struct descbits bits[] = { 370 { L9P_OACCMODE, L9P_OREAD, "O_READ" }, 371 { L9P_OACCMODE, L9P_OWRITE, "O_WRITE" }, 372 { L9P_OACCMODE, L9P_ORDWR, "O_RDWR" }, 373 { L9P_OACCMODE, L9P_OEXEC, "O_EXEC" }, 374 375 { L9P_L_O_APPEND, L9P_L_O_APPEND, "O_APPEND" }, 376 { L9P_L_O_CLOEXEC, L9P_L_O_CLOEXEC, "O_CLOEXEC" }, 377 { L9P_L_O_CREAT, L9P_L_O_CREAT, "O_CREAT" }, 378 { L9P_L_O_DIRECT, L9P_L_O_DIRECT, "O_DIRECT" }, 379 { L9P_L_O_DIRECTORY, L9P_L_O_DIRECTORY, "O_DIRECTORY" }, 380 { L9P_L_O_DSYNC, L9P_L_O_DSYNC, "O_DSYNC" }, 381 { L9P_L_O_EXCL, L9P_L_O_EXCL, "O_EXCL" }, 382 { L9P_L_O_FASYNC, L9P_L_O_FASYNC, "O_FASYNC" }, 383 { L9P_L_O_LARGEFILE, L9P_L_O_LARGEFILE, "O_LARGEFILE" }, 384 { L9P_L_O_NOATIME, L9P_L_O_NOATIME, "O_NOATIME" }, 385 { L9P_L_O_NOCTTY, L9P_L_O_NOCTTY, "O_NOCTTY" }, 386 { L9P_L_O_NOFOLLOW, L9P_L_O_NOFOLLOW, "O_NOFOLLOW" }, 387 { L9P_L_O_NONBLOCK, L9P_L_O_NONBLOCK, "O_NONBLOCK" }, 388 { L9P_L_O_PATH, L9P_L_O_PATH, "O_PATH" }, 389 { L9P_L_O_SYNC, L9P_L_O_SYNC, "O_SYNC" }, 390 { L9P_L_O_TMPFILE, L9P_L_O_TMPFILE, "O_TMPFILE" }, 391 { L9P_L_O_TMPFILE, L9P_L_O_TMPFILE, "O_TMPFILE" }, 392 { L9P_L_O_TRUNC, L9P_L_O_TRUNC, "O_TRUNC" }, 393 { 0, 0, NULL } 394 }; 395 396 (void) l9p_describe_bits(str, flags, "[]", bits, sb); 397 } 398 399 /* 400 * Show file name or other similar, potentially-very-long string. 401 * Actual strings get quotes, a NULL name (if it occurs) gets 402 * <null> (no quotes), so you can tell the difference. 403 */ 404 static void 405 l9p_describe_name(const char *str, char *name, struct sbuf *sb) 406 { 407 size_t len; 408 409 if (name == NULL) { 410 sbuf_printf(sb, "%s<null>", str); 411 return; 412 } 413 414 len = strlen(name); 415 416 if (len > 32) 417 sbuf_printf(sb, "%s\"%.*s...\"", str, 32 - 3, name); 418 else 419 sbuf_printf(sb, "%s\"%.*s\"", str, (int)len, name); 420 } 421 422 #define STRMODE_SIZE 12 423 424 #ifdef __illumos__ 425 static void 426 strmode(mode_t mode, char *bp) 427 { 428 char *const sbp = bp; 429 430 /* 431 * The single caller does not pass in the file type as part of 'mode', 432 * and ignores the first character in the returned buffer anyway. 433 */ 434 *bp++ = '?'; 435 436 #define ONE(_cmp, _ch) ((mode & (_cmp)) != 0) ? (_ch) : '-' 437 *bp++ = ONE(S_IRUSR, 'r'); 438 *bp++ = ONE(S_IWUSR, 'w'); 439 switch (mode & (S_ISUID|S_IXUSR)) { 440 case S_ISUID|S_IXUSR: 441 *bp++ = 's'; 442 break; 443 case S_ISUID: 444 *bp++ = 'S'; 445 break; 446 case S_IXUSR: 447 *bp++ = 'x'; 448 break; 449 case 0: 450 *bp++ = '-'; 451 } 452 453 *bp++ = ONE(S_IRGRP, 'r'); 454 *bp++ = ONE(S_IWGRP, 'w'); 455 switch (mode & (S_ISGID|S_IXGRP|S_IFREG)) { 456 case S_ISGID|S_IXGRP: 457 *bp++ = 's'; 458 break; 459 case S_ISGID|S_IFREG: 460 *bp++ = 'L'; 461 break; 462 case S_ISGID: 463 *bp++ = 'S'; 464 break; 465 case S_IXGRP: 466 *bp++ = 'x'; 467 break; 468 default: 469 *bp++ = '-'; 470 } 471 472 *bp++ = ONE(S_IROTH, 'r'); 473 *bp++ = ONE(S_IWOTH, 'w'); 474 switch (mode & (S_ISVTX|S_IXOTH)) { 475 case S_ISVTX|S_IXOTH: 476 *bp++ = 't'; 477 break; 478 case S_ISVTX: 479 *bp++ = 'T'; 480 break; 481 case S_IXOTH: 482 *bp++ = 'x'; 483 break; 484 default: 485 *bp++ = '-'; 486 } 487 488 *bp++ = ' '; 489 *bp = '\0'; 490 491 assert(bp - sbp <= STRMODE_SIZE); 492 #undef ONE 493 } 494 #endif /* __illumos__ */ 495 496 /* 497 * Show permissions (rwx etc). Prints the value in hex only if 498 * the rwx bits do not cover the entire value. 499 */ 500 static void 501 l9p_describe_perm(const char *str, uint32_t mode, struct sbuf *sb) 502 { 503 char pbuf[STRMODE_SIZE]; 504 505 strmode(mode & 0777, pbuf); 506 if ((mode & ~(uint32_t)0777) != 0) 507 sbuf_printf(sb, "%s0x%" PRIx32 "<%.9s>", str, mode, pbuf + 1); 508 else 509 sbuf_printf(sb, "%s<%.9s>", str, pbuf + 1); 510 } 511 512 /* 513 * Show "extended" permissions: regular permissions, but also the 514 * various DM* extension bits from 9P2000.u. 515 */ 516 static void 517 l9p_describe_ext_perm(const char *str, uint32_t mode, struct sbuf *sb) 518 { 519 static const struct descbits bits[] = { 520 { L9P_DMDIR, L9P_DMDIR, "DMDIR" }, 521 { L9P_DMAPPEND, L9P_DMAPPEND, "DMAPPEND" }, 522 { L9P_DMEXCL, L9P_DMEXCL, "DMEXCL" }, 523 { L9P_DMMOUNT, L9P_DMMOUNT, "DMMOUNT" }, 524 { L9P_DMAUTH, L9P_DMAUTH, "DMAUTH" }, 525 { L9P_DMTMP, L9P_DMTMP, "DMTMP" }, 526 { L9P_DMSYMLINK, L9P_DMSYMLINK, "DMSYMLINK" }, 527 { L9P_DMDEVICE, L9P_DMDEVICE, "DMDEVICE" }, 528 { L9P_DMNAMEDPIPE, L9P_DMNAMEDPIPE, "DMNAMEDPIPE" }, 529 { L9P_DMSOCKET, L9P_DMSOCKET, "DMSOCKET" }, 530 { L9P_DMSETUID, L9P_DMSETUID, "DMSETUID" }, 531 { L9P_DMSETGID, L9P_DMSETGID, "DMSETGID" }, 532 { 0, 0, NULL } 533 }; 534 bool need_sep; 535 536 sbuf_printf(sb, "%s[", str); 537 need_sep = l9p_describe_bits(NULL, mode & ~(uint32_t)0777, NULL, 538 bits, sb); 539 l9p_describe_perm(need_sep ? "," : "", mode & 0777, sb); 540 sbuf_cat(sb, "]"); 541 } 542 543 /* 544 * Show Linux-specific permissions: regular permissions, but also 545 * the S_IFMT field. 546 */ 547 static void 548 l9p_describe_lperm(const char *str, uint32_t mode, struct sbuf *sb) 549 { 550 static const struct descbits bits[] = { 551 { S_IFMT, S_IFIFO, "S_IFIFO" }, 552 { S_IFMT, S_IFCHR, "S_IFCHR" }, 553 { S_IFMT, S_IFDIR, "S_IFDIR" }, 554 { S_IFMT, S_IFBLK, "S_IFBLK" }, 555 { S_IFMT, S_IFREG, "S_IFREG" }, 556 { S_IFMT, S_IFLNK, "S_IFLNK" }, 557 { S_IFMT, S_IFSOCK, "S_IFSOCK" }, 558 #ifdef __illumos__ 559 { S_IFMT, S_IFDOOR, "S_IFDOOR" }, 560 { S_IFMT, S_IFPORT, "S_IFPORT" }, 561 #endif 562 { 0, 0, NULL } 563 }; 564 bool need_sep; 565 566 sbuf_printf(sb, "%s[", str); 567 need_sep = l9p_describe_bits(NULL, mode & ~(uint32_t)0777, NULL, 568 bits, sb); 569 l9p_describe_perm(need_sep ? "," : "", mode & 0777, sb); 570 sbuf_cat(sb, "]"); 571 } 572 573 /* 574 * Show qid (<type, version, path> tuple). 575 */ 576 static void 577 l9p_describe_qid(const char *str, struct l9p_qid *qid, struct sbuf *sb) 578 { 579 static const struct descbits bits[] = { 580 /* 581 * NB: L9P_QTFILE is 0, i.e., is implied by no 582 * other bits being set. We get this produced 583 * when we mask against 0xff and compare for 584 * L9P_QTFILE, but we must do it first so that 585 * we mask against the original (not-adjusted) 586 * value. 587 */ 588 { 0xff, L9P_QTFILE, "FILE" }, 589 { L9P_QTDIR, L9P_QTDIR, "DIR" }, 590 { L9P_QTAPPEND, L9P_QTAPPEND, "APPEND" }, 591 { L9P_QTEXCL, L9P_QTEXCL, "EXCL" }, 592 { L9P_QTMOUNT, L9P_QTMOUNT, "MOUNT" }, 593 { L9P_QTAUTH, L9P_QTAUTH, "AUTH" }, 594 { L9P_QTTMP, L9P_QTTMP, "TMP" }, 595 { L9P_QTSYMLINK, L9P_QTSYMLINK, "SYMLINK" }, 596 { 0, 0, NULL } 597 }; 598 599 assert(qid != NULL); 600 601 sbuf_cat(sb, str); 602 (void) l9p_describe_bits("<", qid->type, "[]", bits, sb); 603 sbuf_printf(sb, ",%" PRIu32 ",0x%016" PRIx64 ">", 604 qid->version, qid->path); 605 } 606 607 /* 608 * Show size. 609 */ 610 static void 611 l9p_describe_size(const char *str, uint64_t size, struct sbuf *sb) 612 { 613 614 sbuf_printf(sb, "%s%" PRIu64, str, size); 615 } 616 617 /* 618 * Show l9stat (including 9P2000.u extensions if appropriate). 619 */ 620 static void 621 l9p_describe_l9stat(const char *str, struct l9p_stat *st, 622 enum l9p_version version, struct sbuf *sb) 623 { 624 bool dotu = version >= L9P_2000U; 625 626 assert(st != NULL); 627 628 sbuf_printf(sb, "%stype=0x%04" PRIx32 " dev=0x%08" PRIx32, str, 629 st->type, st->dev); 630 l9p_describe_qid(" qid=", &st->qid, sb); 631 l9p_describe_ext_perm(" mode=", st->mode, sb); 632 if (st->atime != (uint32_t)-1) 633 sbuf_printf(sb, " atime=%" PRIu32, st->atime); 634 if (st->mtime != (uint32_t)-1) 635 sbuf_printf(sb, " mtime=%" PRIu32, st->mtime); 636 if (st->length != (uint64_t)-1) 637 sbuf_printf(sb, " length=%" PRIu64, st->length); 638 l9p_describe_name(" name=", st->name, sb); 639 /* 640 * It's pretty common to have NULL name+gid+muid. They're 641 * just noise if NULL *and* dot-u; decode only if non-null 642 * or not-dot-u. 643 */ 644 if (st->uid != NULL || !dotu) 645 l9p_describe_name(" uid=", st->uid, sb); 646 if (st->gid != NULL || !dotu) 647 l9p_describe_name(" gid=", st->gid, sb); 648 if (st->muid != NULL || !dotu) 649 l9p_describe_name(" muid=", st->muid, sb); 650 if (dotu) { 651 if (st->extension != NULL) 652 l9p_describe_name(" extension=", st->extension, sb); 653 sbuf_printf(sb, 654 " n_uid=%" PRIu32 " n_gid=%" PRIu32 " n_muid=%" PRIu32, 655 st->n_uid, st->n_gid, st->n_muid); 656 } 657 } 658 659 static void 660 l9p_describe_statfs(const char *str, struct l9p_statfs *st, struct sbuf *sb) 661 { 662 663 assert(st != NULL); 664 665 sbuf_printf(sb, "%stype=0x%04lx bsize=%lu blocks=%" PRIu64 666 " bfree=%" PRIu64 " bavail=%" PRIu64 " files=%" PRIu64 667 " ffree=%" PRIu64 " fsid=0x%" PRIx64 " namelen=%" PRIu32 ">", 668 str, (u_long)st->type, (u_long)st->bsize, st->blocks, 669 st->bfree, st->bavail, st->files, 670 st->ffree, st->fsid, st->namelen); 671 } 672 673 /* 674 * Decode a <seconds,nsec> timestamp. 675 * 676 * Perhaps should use asctime_r. For now, raw values. 677 */ 678 static void 679 l9p_describe_time(struct sbuf *sb, const char *s, uint64_t sec, uint64_t nsec) 680 { 681 682 sbuf_cat(sb, s); 683 if (nsec > 999999999) 684 sbuf_printf(sb, "%" PRIu64 ".<invalid nsec %" PRIu64 ">)", 685 sec, nsec); 686 else 687 sbuf_printf(sb, "%" PRIu64 ".%09" PRIu64, sec, nsec); 688 } 689 690 /* 691 * Decode readdir data (.L format, variable length names). 692 */ 693 static void 694 l9p_describe_readdir(struct sbuf *sb, struct l9p_f_io *io) 695 { 696 uint32_t count; 697 #ifdef notyet 698 int i; 699 struct l9p_message msg; 700 struct l9p_dirent de; 701 #endif 702 703 if ((count = io->count) == 0) { 704 sbuf_printf(sb, " EOF (count=0)"); 705 return; 706 } 707 708 /* 709 * Can't do this yet because we do not have the original 710 * req. 711 */ 712 #ifdef notyet 713 sbuf_printf(sb, " count=%" PRIu32 " [", count); 714 715 l9p_init_msg(&msg, req, L9P_UNPACK); 716 for (i = 0; msg.lm_size < count; i++) { 717 if (l9p_pudirent(&msg, &de) < 0) { 718 sbuf_printf(sb, " bad count"); 719 break; 720 } 721 722 sbuf_printf(sb, i ? ", " : " "); 723 l9p_describe_qid(" qid=", &de.qid, sb); 724 sbuf_printf(sb, " offset=%" PRIu64 " type=%d", 725 de.offset, de.type); 726 l9p_describe_name(" name=", de.name); 727 free(de.name); 728 } 729 sbuf_printf(sb, "]=%d dir entries", i); 730 #else /* notyet */ 731 sbuf_printf(sb, " count=%" PRIu32, count); 732 #endif 733 } 734 735 /* 736 * Decode Tgetattr request_mask field. 737 */ 738 static void 739 l9p_describe_getattr_mask(uint64_t request_mask, struct sbuf *sb) 740 { 741 static const struct descbits bits[] = { 742 /* 743 * Note: ALL and BASIC must occur first and second. 744 * This is a little dirty: it depends on the way the 745 * describe_bits code clears the values. If we 746 * match ALL, we clear all those bits and do not 747 * match BASIC; if we match BASIC, we clear all 748 * those bits and do not match individual bits. Thus 749 * if we have BASIC but not all the additional bits, 750 * we'll see, e.g., [BASIC,BTIME,GEN]; if we have 751 * all the additional bits too, we'll see [ALL]. 752 * 753 * Since <undec> is true below, we'll also spot any 754 * bits added to the protocol since we made this table. 755 */ 756 { L9PL_GETATTR_ALL, L9PL_GETATTR_ALL, "ALL" }, 757 { L9PL_GETATTR_BASIC, L9PL_GETATTR_BASIC, "BASIC" }, 758 759 /* individual bits in BASIC */ 760 { L9PL_GETATTR_MODE, L9PL_GETATTR_MODE, "MODE" }, 761 { L9PL_GETATTR_NLINK, L9PL_GETATTR_NLINK, "NLINK" }, 762 { L9PL_GETATTR_UID, L9PL_GETATTR_UID, "UID" }, 763 { L9PL_GETATTR_GID, L9PL_GETATTR_GID, "GID" }, 764 { L9PL_GETATTR_RDEV, L9PL_GETATTR_RDEV, "RDEV" }, 765 { L9PL_GETATTR_ATIME, L9PL_GETATTR_ATIME, "ATIME" }, 766 { L9PL_GETATTR_MTIME, L9PL_GETATTR_MTIME, "MTIME" }, 767 { L9PL_GETATTR_CTIME, L9PL_GETATTR_CTIME, "CTIME" }, 768 { L9PL_GETATTR_INO, L9PL_GETATTR_INO, "INO" }, 769 { L9PL_GETATTR_SIZE, L9PL_GETATTR_SIZE, "SIZE" }, 770 { L9PL_GETATTR_BLOCKS, L9PL_GETATTR_BLOCKS, "BLOCKS" }, 771 772 /* additional bits in ALL */ 773 { L9PL_GETATTR_BTIME, L9PL_GETATTR_BTIME, "BTIME" }, 774 { L9PL_GETATTR_GEN, L9PL_GETATTR_GEN, "GEN" }, 775 { L9PL_GETATTR_DATA_VERSION, L9PL_GETATTR_DATA_VERSION, 776 "DATA_VERSION" }, 777 { 0, 0, NULL } 778 }; 779 780 (void) l9p_describe_bits(" request_mask=", request_mask, "[]", bits, 781 sb); 782 } 783 784 /* 785 * Decode Tunlinkat flags. 786 */ 787 static void 788 l9p_describe_unlinkat_flags(const char *str, uint32_t flags, struct sbuf *sb) 789 { 790 static const struct descbits bits[] = { 791 { L9PL_AT_REMOVEDIR, L9PL_AT_REMOVEDIR, "AT_REMOVEDIR" }, 792 { 0, 0, NULL } 793 }; 794 795 (void) l9p_describe_bits(str, flags, "[]", bits, sb); 796 } 797 798 static const char * 799 lookup_linux_errno(uint32_t linux_errno, char *buf, size_t len) 800 { 801 /* 802 * Error numbers in the "base" range (1..ERANGE) are common 803 * across BSD, MacOS, Linux, and Plan 9. 804 * 805 * Error numbers outside that range require translation. 806 */ 807 const char *const table[] = { 808 #define X0(name) [name] = name ## _STR 809 #define X(name) [name] = name ## _STR 810 X(LINUX_EAGAIN), 811 X(LINUX_EDEADLK), 812 X(LINUX_ENAMETOOLONG), 813 X(LINUX_ENOLCK), 814 X(LINUX_ENOSYS), 815 X(LINUX_ENOTEMPTY), 816 X(LINUX_ELOOP), 817 X(LINUX_ENOMSG), 818 X(LINUX_EIDRM), 819 X(LINUX_ECHRNG), 820 X(LINUX_EL2NSYNC), 821 X(LINUX_EL3HLT), 822 X(LINUX_EL3RST), 823 X(LINUX_ELNRNG), 824 X(LINUX_EUNATCH), 825 X(LINUX_ENOCSI), 826 X(LINUX_EL2HLT), 827 X(LINUX_EBADE), 828 X(LINUX_EBADR), 829 X(LINUX_EXFULL), 830 X(LINUX_ENOANO), 831 X(LINUX_EBADRQC), 832 X(LINUX_EBADSLT), 833 X(LINUX_EBFONT), 834 X(LINUX_ENOSTR), 835 X(LINUX_ENODATA), 836 X(LINUX_ETIME), 837 X(LINUX_ENOSR), 838 X(LINUX_ENONET), 839 X(LINUX_ENOPKG), 840 X(LINUX_EREMOTE), 841 X(LINUX_ENOLINK), 842 X(LINUX_EADV), 843 X(LINUX_ESRMNT), 844 X(LINUX_ECOMM), 845 X(LINUX_EPROTO), 846 X(LINUX_EMULTIHOP), 847 X(LINUX_EDOTDOT), 848 X(LINUX_EBADMSG), 849 X(LINUX_EOVERFLOW), 850 X(LINUX_ENOTUNIQ), 851 X(LINUX_EBADFD), 852 X(LINUX_EREMCHG), 853 X(LINUX_ELIBACC), 854 X(LINUX_ELIBBAD), 855 X(LINUX_ELIBSCN), 856 X(LINUX_ELIBMAX), 857 X(LINUX_ELIBEXEC), 858 X(LINUX_EILSEQ), 859 X(LINUX_ERESTART), 860 X(LINUX_ESTRPIPE), 861 X(LINUX_EUSERS), 862 X(LINUX_ENOTSOCK), 863 X(LINUX_EDESTADDRREQ), 864 X(LINUX_EMSGSIZE), 865 X(LINUX_EPROTOTYPE), 866 X(LINUX_ENOPROTOOPT), 867 X(LINUX_EPROTONOSUPPORT), 868 X(LINUX_ESOCKTNOSUPPORT), 869 X(LINUX_EOPNOTSUPP), 870 X(LINUX_EPFNOSUPPORT), 871 X(LINUX_EAFNOSUPPORT), 872 X(LINUX_EADDRINUSE), 873 X(LINUX_EADDRNOTAVAIL), 874 X(LINUX_ENETDOWN), 875 X(LINUX_ENETUNREACH), 876 X(LINUX_ENETRESET), 877 X(LINUX_ECONNABORTED), 878 X(LINUX_ECONNRESET), 879 X(LINUX_ENOBUFS), 880 X(LINUX_EISCONN), 881 X(LINUX_ENOTCONN), 882 X(LINUX_ESHUTDOWN), 883 X(LINUX_ETOOMANYREFS), 884 X(LINUX_ETIMEDOUT), 885 X(LINUX_ECONNREFUSED), 886 X(LINUX_EHOSTDOWN), 887 X(LINUX_EHOSTUNREACH), 888 X(LINUX_EALREADY), 889 X(LINUX_EINPROGRESS), 890 X(LINUX_ESTALE), 891 X(LINUX_EUCLEAN), 892 X(LINUX_ENOTNAM), 893 X(LINUX_ENAVAIL), 894 X(LINUX_EISNAM), 895 X(LINUX_EREMOTEIO), 896 X(LINUX_EDQUOT), 897 X(LINUX_ENOMEDIUM), 898 X(LINUX_EMEDIUMTYPE), 899 X(LINUX_ECANCELED), 900 X(LINUX_ENOKEY), 901 X(LINUX_EKEYEXPIRED), 902 X(LINUX_EKEYREVOKED), 903 X(LINUX_EKEYREJECTED), 904 X(LINUX_EOWNERDEAD), 905 X(LINUX_ENOTRECOVERABLE), 906 X(LINUX_ERFKILL), 907 X(LINUX_EHWPOISON), 908 #undef X0 909 #undef X 910 }; 911 if ((size_t)linux_errno < N(table) && table[linux_errno] != NULL) 912 return (table[linux_errno]); 913 if (linux_errno <= ERANGE) 914 return (strerror((int)linux_errno)); 915 (void) snprintf(buf, len, "Unknown error %d", linux_errno); 916 return (buf); 917 } 918 919 void 920 l9p_describe_fcall(union l9p_fcall *fcall, enum l9p_version version, 921 struct sbuf *sb) 922 { 923 uint64_t mask; 924 uint8_t type; 925 int i; 926 927 assert(fcall != NULL); 928 assert(sb != NULL); 929 assert(version <= L9P_2000L); 930 931 type = fcall->hdr.type; 932 933 if (type < L9P__FIRST || type >= L9P__LAST_PLUS_1 || 934 ftype_names[type - L9P__FIRST] == NULL) { 935 const char *rr; 936 937 /* 938 * Can't say for sure that this distinction -- 939 * an even number is a request, an odd one is 940 * a response -- will be maintained forever, 941 * but it's good enough for now. 942 */ 943 rr = (type & 1) != 0 ? "response" : "request"; 944 sbuf_printf(sb, "<unknown %s %d> tag=%d", rr, type, 945 fcall->hdr.tag); 946 } else { 947 sbuf_printf(sb, "%s tag=%d", ftype_names[type - L9P__FIRST], 948 fcall->hdr.tag); 949 } 950 951 switch (type) { 952 case L9P_TVERSION: 953 case L9P_RVERSION: 954 sbuf_printf(sb, " version=\"%s\" msize=%d", fcall->version.version, 955 fcall->version.msize); 956 return; 957 958 case L9P_TAUTH: 959 l9p_describe_fid(" afid=", fcall->hdr.fid, sb); 960 sbuf_printf(sb, " uname=\"%s\" aname=\"%s\"", 961 fcall->tauth.uname, fcall->tauth.aname); 962 return; 963 964 case L9P_TATTACH: 965 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 966 l9p_describe_fid(" afid=", fcall->tattach.afid, sb); 967 sbuf_printf(sb, " uname=\"%s\" aname=\"%s\"", 968 fcall->tattach.uname, fcall->tattach.aname); 969 if (version >= L9P_2000U) 970 sbuf_printf(sb, " n_uname=%d", fcall->tattach.n_uname); 971 return; 972 973 case L9P_RATTACH: 974 l9p_describe_qid(" ", &fcall->rattach.qid, sb); 975 return; 976 977 case L9P_RERROR: 978 sbuf_printf(sb, " ename=\"%s\" errnum=%d", fcall->error.ename, 979 fcall->error.errnum); 980 return; 981 982 case L9P_RLERROR: { 983 char unknown[50]; 984 985 sbuf_printf(sb, " errnum=%d (%s)", fcall->error.errnum, 986 lookup_linux_errno(fcall->error.errnum, 987 unknown, sizeof(unknown))); 988 return; 989 } 990 991 case L9P_TFLUSH: 992 sbuf_printf(sb, " oldtag=%d", fcall->tflush.oldtag); 993 return; 994 995 case L9P_RFLUSH: 996 return; 997 998 case L9P_TWALK: 999 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1000 l9p_describe_fid(" newfid=", fcall->twalk.newfid, sb); 1001 if (fcall->twalk.nwname) { 1002 sbuf_cat(sb, " wname=\""); 1003 for (i = 0; i < fcall->twalk.nwname; i++) 1004 sbuf_printf(sb, "%s%s", i == 0 ? "" : "/", 1005 fcall->twalk.wname[i]); 1006 sbuf_cat(sb, "\""); 1007 } 1008 return; 1009 1010 case L9P_RWALK: 1011 sbuf_printf(sb, " wqid=["); 1012 for (i = 0; i < fcall->rwalk.nwqid; i++) 1013 l9p_describe_qid(i == 0 ? "" : ",", 1014 &fcall->rwalk.wqid[i], sb); 1015 sbuf_cat(sb, "]"); 1016 return; 1017 1018 case L9P_TOPEN: 1019 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1020 l9p_describe_mode(" mode=", fcall->tcreate.mode, sb); 1021 return; 1022 1023 case L9P_ROPEN: 1024 l9p_describe_qid(" qid=", &fcall->ropen.qid, sb); 1025 sbuf_printf(sb, " iounit=%d", fcall->ropen.iounit); 1026 return; 1027 1028 case L9P_TCREATE: 1029 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1030 l9p_describe_name(" name=", fcall->tcreate.name, sb); 1031 l9p_describe_ext_perm(" perm=", fcall->tcreate.perm, sb); 1032 l9p_describe_mode(" mode=", fcall->tcreate.mode, sb); 1033 if (version >= L9P_2000U && fcall->tcreate.extension != NULL) 1034 l9p_describe_name(" extension=", 1035 fcall->tcreate.extension, sb); 1036 return; 1037 1038 case L9P_RCREATE: 1039 l9p_describe_qid(" qid=", &fcall->rcreate.qid, sb); 1040 sbuf_printf(sb, " iounit=%d", fcall->rcreate.iounit); 1041 return; 1042 1043 case L9P_TREAD: 1044 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1045 sbuf_printf(sb, " offset=%" PRIu64 " count=%" PRIu32, 1046 fcall->io.offset, fcall->io.count); 1047 return; 1048 1049 case L9P_RREAD: 1050 case L9P_RWRITE: 1051 sbuf_printf(sb, " count=%" PRIu32, fcall->io.count); 1052 return; 1053 1054 case L9P_TWRITE: 1055 case L9P_TREADDIR: 1056 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1057 sbuf_printf(sb, " offset=%" PRIu64 " count=%" PRIu32, 1058 fcall->io.offset, fcall->io.count); 1059 return; 1060 1061 case L9P_TCLUNK: 1062 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1063 return; 1064 1065 case L9P_RCLUNK: 1066 return; 1067 1068 case L9P_TREMOVE: 1069 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1070 return; 1071 1072 case L9P_RREMOVE: 1073 return; 1074 1075 case L9P_TSTAT: 1076 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1077 return; 1078 1079 case L9P_RSTAT: 1080 l9p_describe_l9stat(" ", &fcall->rstat.stat, version, sb); 1081 return; 1082 1083 case L9P_TWSTAT: 1084 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1085 l9p_describe_l9stat(" ", &fcall->twstat.stat, version, sb); 1086 return; 1087 1088 case L9P_RWSTAT: 1089 return; 1090 1091 case L9P_TSTATFS: 1092 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1093 return; 1094 1095 case L9P_RSTATFS: 1096 l9p_describe_statfs(" ", &fcall->rstatfs.statfs, sb); 1097 return; 1098 1099 case L9P_TLOPEN: 1100 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1101 l9p_describe_lflags(" flags=", fcall->tlcreate.flags, sb); 1102 return; 1103 1104 case L9P_RLOPEN: 1105 l9p_describe_qid(" qid=", &fcall->rlopen.qid, sb); 1106 sbuf_printf(sb, " iounit=%d", fcall->rlopen.iounit); 1107 return; 1108 1109 case L9P_TLCREATE: 1110 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1111 l9p_describe_name(" name=", fcall->tlcreate.name, sb); 1112 /* confusing: "flags" is open-mode, "mode" is permissions */ 1113 l9p_describe_lflags(" flags=", fcall->tlcreate.flags, sb); 1114 /* TLCREATE mode/permissions have S_IFREG (0x8000) set */ 1115 l9p_describe_lperm(" mode=", fcall->tlcreate.mode, sb); 1116 l9p_describe_ugid(" gid=", fcall->tlcreate.gid, sb); 1117 return; 1118 1119 case L9P_RLCREATE: 1120 l9p_describe_qid(" qid=", &fcall->rlcreate.qid, sb); 1121 sbuf_printf(sb, " iounit=%d", fcall->rlcreate.iounit); 1122 return; 1123 1124 case L9P_TSYMLINK: 1125 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1126 l9p_describe_name(" name=", fcall->tsymlink.name, sb); 1127 l9p_describe_name(" symtgt=", fcall->tsymlink.symtgt, sb); 1128 l9p_describe_ugid(" gid=", fcall->tsymlink.gid, sb); 1129 return; 1130 1131 case L9P_RSYMLINK: 1132 l9p_describe_qid(" qid=", &fcall->ropen.qid, sb); 1133 return; 1134 1135 case L9P_TMKNOD: 1136 l9p_describe_fid(" dfid=", fcall->hdr.fid, sb); 1137 l9p_describe_name(" name=", fcall->tmknod.name, sb); 1138 /* 1139 * TMKNOD mode/permissions have S_IFBLK/S_IFCHR/S_IFIFO 1140 * bits. The major and minor values are only meaningful 1141 * for S_IFBLK and S_IFCHR, but just decode always here. 1142 */ 1143 l9p_describe_lperm(" mode=", fcall->tmknod.mode, sb); 1144 sbuf_printf(sb, " major=%u minor=%u", 1145 fcall->tmknod.major, fcall->tmknod.minor); 1146 l9p_describe_ugid(" gid=", fcall->tmknod.gid, sb); 1147 return; 1148 1149 case L9P_RMKNOD: 1150 l9p_describe_qid(" qid=", &fcall->rmknod.qid, sb); 1151 return; 1152 1153 case L9P_TRENAME: 1154 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1155 l9p_describe_fid(" dfid=", fcall->trename.dfid, sb); 1156 l9p_describe_name(" name=", fcall->trename.name, sb); 1157 return; 1158 1159 case L9P_RRENAME: 1160 return; 1161 1162 case L9P_TREADLINK: 1163 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1164 return; 1165 1166 case L9P_RREADLINK: 1167 l9p_describe_name(" target=", fcall->rreadlink.target, sb); 1168 return; 1169 1170 case L9P_TGETATTR: 1171 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1172 l9p_describe_getattr_mask(fcall->tgetattr.request_mask, sb); 1173 return; 1174 1175 case L9P_RGETATTR: 1176 /* Don't need to decode bits: they're implied by the output */ 1177 mask = fcall->rgetattr.valid; 1178 sbuf_printf(sb, " valid=0x%016" PRIx64, mask); 1179 l9p_describe_qid(" qid=", &fcall->rgetattr.qid, sb); 1180 if (mask & L9PL_GETATTR_MODE) 1181 l9p_describe_lperm(" mode=", fcall->rgetattr.mode, sb); 1182 if (mask & L9PL_GETATTR_UID) 1183 l9p_describe_ugid(" uid=", fcall->rgetattr.uid, sb); 1184 if (mask & L9PL_GETATTR_GID) 1185 l9p_describe_ugid(" gid=", fcall->rgetattr.gid, sb); 1186 if (mask & L9PL_GETATTR_NLINK) 1187 sbuf_printf(sb, " nlink=%" PRIu64, 1188 fcall->rgetattr.nlink); 1189 if (mask & L9PL_GETATTR_RDEV) 1190 sbuf_printf(sb, " rdev=0x%" PRIx64, 1191 fcall->rgetattr.rdev); 1192 if (mask & L9PL_GETATTR_SIZE) 1193 l9p_describe_size(" size=", fcall->rgetattr.size, sb); 1194 if (mask & L9PL_GETATTR_BLOCKS) 1195 sbuf_printf(sb, " blksize=%" PRIu64 " blocks=%" PRIu64, 1196 fcall->rgetattr.blksize, fcall->rgetattr.blocks); 1197 if (mask & L9PL_GETATTR_ATIME) 1198 l9p_describe_time(sb, " atime=", 1199 fcall->rgetattr.atime_sec, 1200 fcall->rgetattr.atime_nsec); 1201 if (mask & L9PL_GETATTR_MTIME) 1202 l9p_describe_time(sb, " mtime=", 1203 fcall->rgetattr.mtime_sec, 1204 fcall->rgetattr.mtime_nsec); 1205 if (mask & L9PL_GETATTR_CTIME) 1206 l9p_describe_time(sb, " ctime=", 1207 fcall->rgetattr.ctime_sec, 1208 fcall->rgetattr.ctime_nsec); 1209 if (mask & L9PL_GETATTR_BTIME) 1210 l9p_describe_time(sb, " btime=", 1211 fcall->rgetattr.btime_sec, 1212 fcall->rgetattr.btime_nsec); 1213 if (mask & L9PL_GETATTR_GEN) 1214 sbuf_printf(sb, " gen=0x%" PRIx64, fcall->rgetattr.gen); 1215 if (mask & L9PL_GETATTR_DATA_VERSION) 1216 sbuf_printf(sb, " data_version=0x%" PRIx64, 1217 fcall->rgetattr.data_version); 1218 return; 1219 1220 case L9P_TSETATTR: 1221 /* As with RGETATTR, we'll imply decode via output. */ 1222 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1223 mask = fcall->tsetattr.valid; 1224 /* NB: tsetattr valid mask is only 32 bits, hence %08x */ 1225 sbuf_printf(sb, " valid=0x%08" PRIx64, mask); 1226 if (mask & L9PL_SETATTR_MODE) 1227 l9p_describe_lperm(" mode=", fcall->tsetattr.mode, sb); 1228 if (mask & L9PL_SETATTR_UID) 1229 l9p_describe_ugid(" uid=", fcall->tsetattr.uid, sb); 1230 if (mask & L9PL_SETATTR_GID) 1231 l9p_describe_ugid(" uid=", fcall->tsetattr.gid, sb); 1232 if (mask & L9PL_SETATTR_SIZE) 1233 l9p_describe_size(" size=", fcall->tsetattr.size, sb); 1234 if (mask & L9PL_SETATTR_ATIME) { 1235 if (mask & L9PL_SETATTR_ATIME_SET) 1236 l9p_describe_time(sb, " atime=", 1237 fcall->tsetattr.atime_sec, 1238 fcall->tsetattr.atime_nsec); 1239 else 1240 sbuf_cat(sb, " atime=now"); 1241 } 1242 if (mask & L9PL_SETATTR_MTIME) { 1243 if (mask & L9PL_SETATTR_MTIME_SET) 1244 l9p_describe_time(sb, " mtime=", 1245 fcall->tsetattr.mtime_sec, 1246 fcall->tsetattr.mtime_nsec); 1247 else 1248 sbuf_cat(sb, " mtime=now"); 1249 } 1250 if (mask & L9PL_SETATTR_CTIME) 1251 sbuf_cat(sb, " ctime=now"); 1252 return; 1253 1254 case L9P_RSETATTR: 1255 return; 1256 1257 case L9P_TXATTRWALK: 1258 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1259 l9p_describe_fid(" newfid=", fcall->txattrwalk.newfid, sb); 1260 l9p_describe_name(" name=", fcall->txattrwalk.name, sb); 1261 return; 1262 1263 case L9P_RXATTRWALK: 1264 l9p_describe_size(" size=", fcall->rxattrwalk.size, sb); 1265 return; 1266 1267 case L9P_TXATTRCREATE: 1268 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1269 l9p_describe_name(" name=", fcall->txattrcreate.name, sb); 1270 l9p_describe_size(" size=", fcall->txattrcreate.attr_size, sb); 1271 sbuf_printf(sb, " flags=%" PRIu32, fcall->txattrcreate.flags); 1272 return; 1273 1274 case L9P_RXATTRCREATE: 1275 return; 1276 1277 case L9P_RREADDIR: 1278 l9p_describe_readdir(sb, &fcall->io); 1279 return; 1280 1281 case L9P_TFSYNC: 1282 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1283 return; 1284 1285 case L9P_RFSYNC: 1286 return; 1287 1288 case L9P_TLOCK: 1289 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1290 /* decode better later */ 1291 sbuf_printf(sb, " type=%d flags=0x%" PRIx32 1292 " start=%" PRIu64 " length=%" PRIu64 1293 " proc_id=0x%" PRIx32 " client_id=\"%s\"", 1294 fcall->tlock.type, fcall->tlock.flags, 1295 fcall->tlock.start, fcall->tlock.length, 1296 fcall->tlock.proc_id, fcall->tlock.client_id); 1297 return; 1298 1299 case L9P_RLOCK: 1300 sbuf_printf(sb, " status=%d", fcall->rlock.status); 1301 return; 1302 1303 case L9P_TGETLOCK: 1304 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1305 /* FALLTHROUGH */ 1306 1307 case L9P_RGETLOCK: 1308 /* decode better later */ 1309 sbuf_printf(sb, " type=%d " 1310 " start=%" PRIu64 " length=%" PRIu64 1311 " proc_id=0x%" PRIx32 " client_id=\"%s\"", 1312 fcall->getlock.type, 1313 fcall->getlock.start, fcall->getlock.length, 1314 fcall->getlock.proc_id, fcall->getlock.client_id); 1315 return; 1316 1317 case L9P_TLINK: 1318 l9p_describe_fid(" dfid=", fcall->tlink.dfid, sb); 1319 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1320 l9p_describe_name(" name=", fcall->tlink.name, sb); 1321 return; 1322 1323 case L9P_RLINK: 1324 return; 1325 1326 case L9P_TMKDIR: 1327 l9p_describe_fid(" fid=", fcall->hdr.fid, sb); 1328 l9p_describe_name(" name=", fcall->tmkdir.name, sb); 1329 /* TMKDIR mode/permissions have S_IFDIR set */ 1330 l9p_describe_lperm(" mode=", fcall->tmkdir.mode, sb); 1331 l9p_describe_ugid(" gid=", fcall->tmkdir.gid, sb); 1332 return; 1333 1334 case L9P_RMKDIR: 1335 l9p_describe_qid(" qid=", &fcall->rmkdir.qid, sb); 1336 return; 1337 1338 case L9P_TRENAMEAT: 1339 l9p_describe_fid(" olddirfid=", fcall->hdr.fid, sb); 1340 l9p_describe_name(" oldname=", fcall->trenameat.oldname, 1341 sb); 1342 l9p_describe_fid(" newdirfid=", fcall->trenameat.newdirfid, sb); 1343 l9p_describe_name(" newname=", fcall->trenameat.newname, 1344 sb); 1345 return; 1346 1347 case L9P_RRENAMEAT: 1348 return; 1349 1350 case L9P_TUNLINKAT: 1351 l9p_describe_fid(" dirfd=", fcall->hdr.fid, sb); 1352 l9p_describe_name(" name=", fcall->tunlinkat.name, sb); 1353 l9p_describe_unlinkat_flags(" flags=", 1354 fcall->tunlinkat.flags, sb); 1355 return; 1356 1357 case L9P_RUNLINKAT: 1358 return; 1359 1360 default: 1361 sbuf_printf(sb, " <missing case in %s()>", __func__); 1362 } 1363 } 1364