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