1/*- 2 * Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided 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 AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY 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, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29#include <sys/param.h> 30#include <sys/types.h> 31#include <sys/stat.h> 32#include <sys/socket.h> 33#include <sys/un.h> 34#ifndef makedev 35#include <sys/mkdev.h> 36#endif 37 38#include <assert.h> 39#include <ctype.h> 40#include <errno.h> 41#include <fcntl.h> 42#include <grp.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <string.h> 46#include <unistd.h> 47 48#ifndef HAS_TRUNCATE64 49#define truncate64 truncate 50#define ftruncate64 ftruncate 51#endif 52#ifndef HAS_STAT64 53#define stat64 stat 54#define fstat64 fstat 55#define lstat64 lstat 56#endif 57#ifdef HAS_FREEBSD_ACL 58#include <sys/acl.h> 59#endif 60 61#ifndef ALLPERMS 62#define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) 63#endif 64 65enum action { 66 ACTION_OPEN, 67 ACTION_OPENAT, 68 ACTION_CREATE, 69 ACTION_UNLINK, 70 ACTION_UNLINKAT, 71 ACTION_MKDIR, 72 ACTION_MKDIRAT, 73 ACTION_RMDIR, 74 ACTION_LINK, 75 ACTION_LINKAT, 76 ACTION_SYMLINK, 77 ACTION_SYMLINKAT, 78 ACTION_RENAME, 79 ACTION_RENAMEAT, 80 ACTION_MKFIFO, 81 ACTION_MKFIFOAT, 82 ACTION_MKNOD, 83 ACTION_MKNODAT, 84 ACTION_BIND, 85#ifdef HAS_BINDAT 86 ACTION_BINDAT, 87#endif 88 ACTION_CONNECT, 89#ifdef HAS_CONNECTAT 90 ACTION_CONNECTAT, 91#endif 92 ACTION_CHMOD, 93 ACTION_FCHMOD, 94#ifdef HAS_LCHMOD 95 ACTION_LCHMOD, 96#endif 97 ACTION_FCHMODAT, 98 ACTION_CHOWN, 99 ACTION_FCHOWN, 100 ACTION_LCHOWN, 101 ACTION_FCHOWNAT, 102#ifdef HAS_CHFLAGS 103 ACTION_CHFLAGS, 104#endif 105#ifdef HAS_FCHFLAGS 106 ACTION_FCHFLAGS, 107#endif 108#ifdef HAS_CHFLAGSAT 109 ACTION_CHFLAGSAT, 110#endif 111#ifdef HAS_LCHFLAGS 112 ACTION_LCHFLAGS, 113#endif 114 ACTION_TRUNCATE, 115 ACTION_FTRUNCATE, 116 ACTION_STAT, 117 ACTION_FSTAT, 118 ACTION_LSTAT, 119 ACTION_FSTATAT, 120 ACTION_PATHCONF, 121 ACTION_FPATHCONF, 122 ACTION_LPATHCONF, 123#ifdef HAS_FREEBSD_ACL 124 ACTION_PREPENDACL, 125 ACTION_READACL, 126#endif 127 ACTION_WRITE, 128}; 129 130#define TYPE_NONE 0x0000 131#define TYPE_STRING 0x0001 132#define TYPE_NUMBER 0x0002 133#define TYPE_DESCRIPTOR 0x0003 134#define TYPE_MASK 0x000f 135 136#define TYPE_OPTIONAL 0x0100 137 138#define MAX_ARGS 8 139 140struct syscall_desc { 141 const char *sd_name; 142 enum action sd_action; 143 int sd_args[MAX_ARGS]; 144}; 145 146static struct syscall_desc syscalls[] = { 147 { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } }, 148 { "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } }, 149 { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 150 { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } }, 151 { "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 152 { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 153 { "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 154 { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } }, 155 { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 156 { "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 157 { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 158 { "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 159 { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 160 { "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 161 { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 162 { "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 163 { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, 164 { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, 165 { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } }, 166#ifdef HAS_BINDAT 167 { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 168#endif 169 { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } }, 170#ifdef HAS_CONNECTAT 171 { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 172#endif 173 { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 174 { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } }, 175#ifdef HAS_LCHMOD 176 { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 177#endif 178 { "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } }, 179 { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } }, 180 { "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } }, 181 { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } }, 182 { "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } }, 183#ifdef HAS_CHFLAGS 184 { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 185#endif 186#ifdef HAS_FCHFLAGS 187 { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 188#endif 189#ifdef HAS_CHFLAGSAT 190 { "chflagsat", ACTION_CHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 191#endif 192#ifdef HAS_LCHFLAGS 193 { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 194#endif 195 { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 196 { "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } }, 197 { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 198 { "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 199 { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 200 { "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 201 { "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 202 { "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 203 { "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 204#ifdef HAS_FREEBSD_ACL 205 { "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 206 { "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } }, 207#endif 208 { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 209 { NULL, -1, { TYPE_NONE } } 210}; 211 212struct flag { 213 long long f_flag; 214 const char *f_str; 215}; 216 217static struct flag open_flags[] = { 218#ifdef O_RDONLY 219 { O_RDONLY, "O_RDONLY" }, 220#endif 221#ifdef O_WRONLY 222 { O_WRONLY, "O_WRONLY" }, 223#endif 224#ifdef O_RDWR 225 { O_RDWR, "O_RDWR" }, 226#endif 227#ifdef O_NONBLOCK 228 { O_NONBLOCK, "O_NONBLOCK" }, 229#endif 230#ifdef O_APPEND 231 { O_APPEND, "O_APPEND" }, 232#endif 233#ifdef O_CREAT 234 { O_CREAT, "O_CREAT" }, 235#endif 236#ifdef O_TRUNC 237 { O_TRUNC, "O_TRUNC" }, 238#endif 239#ifdef O_EXCL 240 { O_EXCL, "O_EXCL" }, 241#endif 242#ifdef O_SHLOCK 243 { O_SHLOCK, "O_SHLOCK" }, 244#endif 245#ifdef O_EXLOCK 246 { O_EXLOCK, "O_EXLOCK" }, 247#endif 248#ifdef O_DIRECT 249 { O_DIRECT, "O_DIRECT" }, 250#endif 251#ifdef O_FSYNC 252 { O_FSYNC, "O_FSYNC" }, 253#endif 254#ifdef O_SYNC 255 { O_SYNC, "O_SYNC" }, 256#endif 257#ifdef O_NOFOLLOW 258 { O_NOFOLLOW, "O_NOFOLLOW" }, 259#endif 260#ifdef O_NOCTTY 261 { O_NOCTTY, "O_NOCTTY" }, 262#endif 263#ifdef O_DIRECTORY 264 { O_DIRECTORY, "O_DIRECTORY" }, 265#endif 266 { 0, NULL } 267}; 268 269#ifdef HAS_CHFLAGS 270static struct flag chflags_flags[] = { 271#ifdef UF_NODUMP 272 { UF_NODUMP, "UF_NODUMP" }, 273#endif 274#ifdef UF_IMMUTABLE 275 { UF_IMMUTABLE, "UF_IMMUTABLE" }, 276#endif 277#ifdef UF_APPEND 278 { UF_APPEND, "UF_APPEND" }, 279#endif 280#ifdef UF_NOUNLINK 281 { UF_NOUNLINK, "UF_NOUNLINK" }, 282#endif 283#ifdef UF_OPAQUE 284 { UF_OPAQUE, "UF_OPAQUE" }, 285#endif 286#ifdef SF_ARCHIVED 287 { SF_ARCHIVED, "SF_ARCHIVED" }, 288#endif 289#ifdef SF_IMMUTABLE 290 { SF_IMMUTABLE, "SF_IMMUTABLE" }, 291#endif 292#ifdef SF_APPEND 293 { SF_APPEND, "SF_APPEND" }, 294#endif 295#ifdef SF_NOUNLINK 296 { SF_NOUNLINK, "SF_NOUNLINK" }, 297#endif 298#ifdef SF_SNAPSHOT 299 { SF_SNAPSHOT, "SF_SNAPSHOT" }, 300#endif 301 { 0, NULL } 302}; 303#endif 304 305static struct flag unlinkat_flags[] = { 306 { AT_REMOVEDIR, "AT_REMOVEDIR" }, 307 { 0, NULL } 308}; 309 310static struct flag linkat_flags[] = { 311 { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" }, 312 { 0, NULL } 313}; 314 315static struct flag chflagsat_flags[] = { 316 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 317 { 0, NULL } 318}; 319 320static struct flag fchmodat_flags[] = { 321 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 322 { 0, NULL } 323}; 324 325static struct flag fchownat_flags[] = { 326 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 327 { 0, NULL } 328}; 329 330static struct flag fstatat_flags[] = { 331 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 332 { 0, NULL } 333}; 334 335struct name { 336 int n_name; 337 const char *n_str; 338}; 339 340static struct name pathconf_names[] = { 341#ifdef _PC_LINK_MAX 342 { _PC_LINK_MAX, "_PC_LINK_MAX" }, 343#endif 344#ifdef _PC_NAME_MAX 345 { _PC_NAME_MAX, "_PC_NAME_MAX" }, 346#endif 347#ifdef _PC_PATH_MAX 348 { _PC_PATH_MAX, "_PC_PATH_MAX" }, 349#endif 350#ifdef _PC_SYMLINK_MAX 351 { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" }, 352#endif 353 { 0, NULL } 354}; 355 356static const char *err2str(int error); 357 358static int *descriptors; 359static int ndescriptors; 360 361static void 362usage(void) 363{ 364 365 fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n"); 366 exit(1); 367} 368 369static long long 370str2flags(struct flag *tflags, char *sflags) 371{ 372 long long flags = 0; 373 unsigned int i; 374 char *f; 375 376 /* 'none' or '0' means no flags */ 377 if (strcmp(sflags, "none") == 0 || strcmp(sflags, "0") == 0) 378 return (0); 379 for (f = strtok(sflags, ",|"); f != NULL; f = strtok(NULL, ",|")) { 380 for (i = 0; tflags[i].f_str != NULL; i++) { 381 if (strcmp(tflags[i].f_str, f) == 0) 382 break; 383 } 384 if (tflags[i].f_str == NULL) { 385 fprintf(stderr, "unknown flag '%s'\n", f); 386 exit(1); 387 } 388 flags |= tflags[i].f_flag; 389 } 390 return (flags); 391} 392 393#ifdef HAS_CHFLAGS 394static char * 395flags2str(struct flag *tflags, long long flags) 396{ 397 static char sflags[1024]; 398 unsigned int i; 399 400 sflags[0] = '\0'; 401 for (i = 0; tflags[i].f_str != NULL; i++) { 402 if (flags & tflags[i].f_flag) { 403 if (sflags[0] != '\0') 404 strlcat(sflags, ",", sizeof(sflags)); 405 strlcat(sflags, tflags[i].f_str, sizeof(sflags)); 406 } 407 } 408 if (sflags[0] == '\0') 409 strlcpy(sflags, "none", sizeof(sflags)); 410 return (sflags); 411} 412#endif 413 414static int 415str2name(struct name *names, char *name) 416{ 417 unsigned int i; 418 419 for (i = 0; names[i].n_str != NULL; i++) { 420 if (strcmp(names[i].n_str, name) == 0) 421 return (names[i].n_name); 422 } 423 return (-1); 424} 425 426static struct syscall_desc * 427find_syscall(const char *name) 428{ 429 int i; 430 431 for (i = 0; syscalls[i].sd_name != NULL; i++) { 432 if (strcmp(syscalls[i].sd_name, name) == 0) 433 return (&syscalls[i]); 434 } 435 return (NULL); 436} 437 438static void 439show_stat(struct stat64 *sp, const char *what) 440{ 441 442 if (strcmp(what, "mode") == 0) 443 printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS)); 444 else if (strcmp(what, "inode") == 0) 445 printf("%lld", (long long)sp->st_ino); 446 else if (strcmp(what, "nlink") == 0) 447 printf("%lld", (long long)sp->st_nlink); 448 else if (strcmp(what, "uid") == 0) 449 printf("%d", (int)sp->st_uid); 450 else if (strcmp(what, "gid") == 0) 451 printf("%d", (int)sp->st_gid); 452 else if (strcmp(what, "size") == 0) 453 printf("%lld", (long long)sp->st_size); 454 else if (strcmp(what, "blocks") == 0) 455 printf("%lld", (long long)sp->st_blocks); 456 else if (strcmp(what, "atime") == 0) 457 printf("%lld", (long long)sp->st_atime); 458 else if (strcmp(what, "mtime") == 0) 459 printf("%lld", (long long)sp->st_mtime); 460 else if (strcmp(what, "ctime") == 0) 461 printf("%lld", (long long)sp->st_ctime); 462#ifdef HAS_CHFLAGS 463 else if (strcmp(what, "flags") == 0) 464 printf("%s", flags2str(chflags_flags, (long long)sp->st_flags)); 465#endif 466 else if (strcmp(what, "major") == 0) 467 printf("%u", (unsigned int)major(sp->st_rdev)); 468 else if (strcmp(what, "minor") == 0) 469 printf("%u", (unsigned int)minor(sp->st_rdev)); 470 else if (strcmp(what, "type") == 0) { 471 switch (sp->st_mode & S_IFMT) { 472 case S_IFIFO: 473 printf("fifo"); 474 break; 475 case S_IFCHR: 476 printf("char"); 477 break; 478 case S_IFDIR: 479 printf("dir"); 480 break; 481 case S_IFBLK: 482 printf("block"); 483 break; 484 case S_IFREG: 485 printf("regular"); 486 break; 487 case S_IFLNK: 488 printf("symlink"); 489 break; 490 case S_IFSOCK: 491 printf("socket"); 492 break; 493 default: 494 printf("unknown"); 495 break; 496 } 497 } else { 498 printf("unknown"); 499 } 500} 501 502static void 503show_stats(struct stat64 *sp, char *what) 504{ 505 const char *s = ""; 506 char *w; 507 508 for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) { 509 printf("%s", s); 510 show_stat(sp, w); 511 s = ","; 512 } 513 printf("\n"); 514} 515 516static void 517descriptor_add(int fd) 518{ 519 520 ndescriptors++; 521 if (descriptors == NULL) { 522 descriptors = malloc(sizeof(descriptors[0]) * ndescriptors); 523 } else { 524 descriptors = realloc(descriptors, 525 sizeof(descriptors[0]) * ndescriptors); 526 } 527 assert(descriptors != NULL); 528 descriptors[ndescriptors - 1] = fd; 529} 530 531static int 532descriptor_get(int pos) 533{ 534 535 if (pos < 0 || pos >= ndescriptors) { 536 fprintf(stderr, "invalid descriptor %d\n", pos); 537 exit(1); 538 } 539 540 return (descriptors[pos]); 541} 542 543static unsigned int 544call_syscall(struct syscall_desc *scall, char *argv[]) 545{ 546 struct stat64 sb; 547 long long flags; 548 unsigned int i; 549 char *endp; 550 int name, rval; 551 union { 552 char *str; 553 long long num; 554 } args[MAX_ARGS]; 555#ifdef HAS_FREEBSD_ACL 556 int entry_id = ACL_FIRST_ENTRY; 557 acl_t acl, newacl; 558 acl_entry_t entry, newentry; 559#endif 560 561 /* 562 * Verify correctness of the arguments. 563 */ 564 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) { 565 if (scall->sd_args[i] == TYPE_NONE) { 566 if (argv[i] == NULL || strcmp(argv[i], ":") == 0) 567 break; 568 fprintf(stderr, "too many arguments [%s]\n", argv[i]); 569 exit(1); 570 } else { 571 if (argv[i] == NULL || strcmp(argv[i], ":") == 0) { 572 if (scall->sd_args[i] & TYPE_OPTIONAL) 573 break; 574 fprintf(stderr, "too few arguments\n"); 575 exit(1); 576 } 577 if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) { 578 if (strcmp(argv[i], "NULL") == 0) 579 args[i].str = NULL; 580 else if (strcmp(argv[i], "DEADCODE") == 0) 581 args[i].str = (void *)0xdeadc0de; 582 else 583 args[i].str = argv[i]; 584 } else if ((scall->sd_args[i] & TYPE_MASK) == 585 TYPE_NUMBER) { 586 args[i].num = strtoll(argv[i], &endp, 0); 587 if (*endp != '\0' && 588 !isspace((unsigned char)*endp)) { 589 fprintf(stderr, 590 "invalid argument %u, number expected [%s]\n", 591 i, endp); 592 exit(1); 593 } 594 } else if ((scall->sd_args[i] & TYPE_MASK) == 595 TYPE_DESCRIPTOR) { 596 if (strcmp(argv[i], "AT_FDCWD") == 0) { 597 args[i].num = AT_FDCWD; 598 } else if (strcmp(argv[i], "BADFD") == 0) { 599 /* In case AT_FDCWD is -1 on some systems... */ 600 if (AT_FDCWD == -1) 601 args[i].num = -2; 602 else 603 args[i].num = -1; 604 } else { 605 int pos; 606 607 pos = strtoll(argv[i], &endp, 0); 608 if (*endp != '\0' && 609 !isspace((unsigned char)*endp)) { 610 fprintf(stderr, 611 "invalid argument %u, number expected [%s]\n", 612 i, endp); 613 exit(1); 614 } 615 args[i].num = descriptor_get(pos); 616 } 617 } 618 } 619 } 620 /* 621 * Call the given syscall. 622 */ 623#define NUM(n) (args[(n)].num) 624#define STR(n) (args[(n)].str) 625 switch (scall->sd_action) { 626 case ACTION_OPEN: 627 flags = str2flags(open_flags, STR(1)); 628 if (flags & O_CREAT) { 629 if (i == 2) { 630 fprintf(stderr, "too few arguments\n"); 631 exit(1); 632 } 633 rval = open(STR(0), (int)flags, (mode_t)NUM(2)); 634 } else { 635 if (i == 3) { 636 fprintf(stderr, "too many arguments\n"); 637 exit(1); 638 } 639 rval = open(STR(0), (int)flags); 640 } 641 if (rval >= 0) 642 descriptor_add(rval); 643 break; 644 case ACTION_OPENAT: 645 flags = str2flags(open_flags, STR(2)); 646 if (flags & O_CREAT) { 647 if (i == 3) { 648 fprintf(stderr, "too few arguments\n"); 649 exit(1); 650 } 651 rval = openat(NUM(0), STR(1), (int)flags, 652 (mode_t)NUM(3)); 653 } else { 654 if (i == 4) { 655 fprintf(stderr, "too many arguments\n"); 656 exit(1); 657 } 658 rval = openat(NUM(0), STR(1), (int)flags); 659 } 660 if (rval >= 0) 661 descriptor_add(rval); 662 break; 663 case ACTION_CREATE: 664 rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1)); 665 if (rval >= 0) 666 close(rval); 667 break; 668 case ACTION_UNLINK: 669 rval = unlink(STR(0)); 670 break; 671 case ACTION_UNLINKAT: 672 rval = unlinkat(NUM(0), STR(1), 673 (int)str2flags(unlinkat_flags, STR(2))); 674 break; 675 case ACTION_MKDIR: 676 rval = mkdir(STR(0), (mode_t)NUM(1)); 677 break; 678 case ACTION_MKDIRAT: 679 rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2)); 680 break; 681 case ACTION_RMDIR: 682 rval = rmdir(STR(0)); 683 break; 684 case ACTION_LINK: 685 rval = link(STR(0), STR(1)); 686 break; 687 case ACTION_LINKAT: 688 rval = linkat(NUM(0), STR(1), NUM(2), STR(3), 689 (int)str2flags(linkat_flags, STR(4))); 690 break; 691 case ACTION_SYMLINK: 692 rval = symlink(STR(0), STR(1)); 693 break; 694 case ACTION_SYMLINKAT: 695 rval = symlinkat(STR(0), NUM(1), STR(2)); 696 break; 697 case ACTION_RENAME: 698 rval = rename(STR(0), STR(1)); 699 break; 700 case ACTION_RENAMEAT: 701 rval = renameat(NUM(0), STR(1), NUM(2), STR(3)); 702 break; 703 case ACTION_MKFIFO: 704 rval = mkfifo(STR(0), (mode_t)NUM(1)); 705 break; 706 case ACTION_MKFIFOAT: 707 rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2)); 708 break; 709 case ACTION_MKNOD: 710 case ACTION_MKNODAT: 711 { 712 mode_t ntype; 713 dev_t dev; 714 int fa; 715 716 switch (scall->sd_action) { 717 case ACTION_MKNOD: 718 fa = 0; 719 break; 720 case ACTION_MKNODAT: 721 fa = 1; 722 break; 723 default: 724 abort(); 725 } 726 727 dev = makedev(NUM(fa + 3), NUM(fa + 4)); 728 if (strcmp(STR(fa + 1), "c") == 0) /* character device */ 729 ntype = S_IFCHR; 730 else if (strcmp(STR(fa + 1), "b") == 0) /* block device */ 731 ntype = S_IFBLK; 732 else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */ 733 ntype = S_IFIFO; 734 else if (strcmp(STR(fa + 1), "d") == 0) /* directory */ 735 ntype = S_IFDIR; 736 else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */ 737 ntype = S_IFREG; 738 else { 739 fprintf(stderr, "wrong argument 1\n"); 740 exit(1); 741 } 742 switch (scall->sd_action) { 743 case ACTION_MKNOD: 744 rval = mknod(STR(0), ntype | NUM(2), dev); 745 break; 746 case ACTION_MKNODAT: 747 rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev); 748 break; 749 default: 750 abort(); 751 } 752 break; 753 } 754 case ACTION_BIND: 755 { 756 struct sockaddr_un sunx; 757 758 sunx.sun_family = AF_UNIX; 759 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); 760 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 761 rval = socket(AF_UNIX, SOCK_STREAM, 0); 762 if (rval < 0) 763 break; 764 rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx)); 765 break; 766 } 767#ifdef HAS_BINDAT 768 case ACTION_BINDAT: 769 { 770 struct sockaddr_un sunx; 771 772 sunx.sun_family = AF_UNIX; 773 strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); 774 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 775 rval = socket(AF_UNIX, SOCK_STREAM, 0); 776 if (rval < 0) 777 break; 778 rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx, 779 sizeof(sunx)); 780 break; 781 } 782#endif 783 case ACTION_CONNECT: 784 { 785 struct sockaddr_un sunx; 786 787 sunx.sun_family = AF_UNIX; 788 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); 789 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 790 rval = socket(AF_UNIX, SOCK_STREAM, 0); 791 if (rval < 0) 792 break; 793 rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx)); 794 break; 795 } 796#ifdef HAS_CONNECTAT 797 case ACTION_CONNECTAT: 798 { 799 struct sockaddr_un sunx; 800 801 sunx.sun_family = AF_UNIX; 802 strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); 803 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 804 rval = socket(AF_UNIX, SOCK_STREAM, 0); 805 if (rval < 0) 806 break; 807 rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx, 808 sizeof(sunx)); 809 break; 810 } 811#endif 812 case ACTION_CHMOD: 813 rval = chmod(STR(0), (mode_t)NUM(1)); 814 break; 815 case ACTION_FCHMOD: 816 rval = fchmod(NUM(0), (mode_t)NUM(1)); 817 break; 818#ifdef HAS_LCHMOD 819 case ACTION_LCHMOD: 820 rval = lchmod(STR(0), (mode_t)NUM(1)); 821 break; 822#endif 823 case ACTION_FCHMODAT: 824 rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2), 825 str2flags(fchmodat_flags, STR(3))); 826 break; 827 case ACTION_CHOWN: 828 rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); 829 break; 830 case ACTION_FCHOWN: 831 rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2)); 832 break; 833 case ACTION_LCHOWN: 834 rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); 835 break; 836 case ACTION_FCHOWNAT: 837 rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3), 838 (int)str2flags(fchownat_flags, STR(4))); 839 break; 840#ifdef HAS_CHFLAGS 841 case ACTION_CHFLAGS: 842 rval = chflags(STR(0), 843 (unsigned long)str2flags(chflags_flags, STR(1))); 844 break; 845#endif 846#ifdef HAS_FCHFLAGS 847 case ACTION_FCHFLAGS: 848 rval = fchflags(NUM(0), 849 (unsigned long)str2flags(chflags_flags, STR(1))); 850 break; 851#endif 852#ifdef HAS_CHFLAGSAT 853 case ACTION_CHFLAGSAT: 854 rval = chflagsat(NUM(0), STR(1), 855 (unsigned long)str2flags(chflags_flags, STR(2)), 856 (int)str2flags(chflagsat_flags, STR(3))); 857 break; 858#endif 859#ifdef HAS_LCHFLAGS 860 case ACTION_LCHFLAGS: 861 rval = lchflags(STR(0), 862 (unsigned long)str2flags(chflags_flags, STR(1))); 863 break; 864#endif 865 case ACTION_TRUNCATE: 866 rval = truncate64(STR(0), NUM(1)); 867 break; 868 case ACTION_FTRUNCATE: 869 rval = ftruncate64(NUM(0), NUM(1)); 870 break; 871 case ACTION_STAT: 872 rval = stat64(STR(0), &sb); 873 if (rval == 0) { 874 show_stats(&sb, STR(1)); 875 return (i); 876 } 877 break; 878 case ACTION_FSTAT: 879 rval = fstat64(NUM(0), &sb); 880 if (rval == 0) { 881 show_stats(&sb, STR(1)); 882 return (i); 883 } 884 break; 885 case ACTION_LSTAT: 886 rval = lstat64(STR(0), &sb); 887 if (rval == 0) { 888 show_stats(&sb, STR(1)); 889 return (i); 890 } 891 break; 892 case ACTION_FSTATAT: 893 rval = fstatat(NUM(0), STR(1), &sb, 894 (int)str2flags(fstatat_flags, STR(2))); 895 if (rval == 0) { 896 show_stats(&sb, STR(3)); 897 return (i); 898 } 899 break; 900 case ACTION_PATHCONF: 901 case ACTION_FPATHCONF: 902 case ACTION_LPATHCONF: 903 { 904 long lrval; 905 906 name = str2name(pathconf_names, STR(1)); 907 if (name == -1) { 908 fprintf(stderr, "unknown name %s", STR(1)); 909 exit(1); 910 } 911 errno = 0; 912 switch (scall->sd_action) { 913 case ACTION_PATHCONF: 914 lrval = pathconf(STR(0), name); 915 break; 916 case ACTION_FPATHCONF: 917 lrval = fpathconf(NUM(0), name); 918 break; 919 case ACTION_LPATHCONF: 920 lrval = lpathconf(STR(0), name); 921 break; 922 default: 923 abort(); 924 } 925 if (lrval == -1 && errno == 0) { 926 printf("unlimited\n"); 927 return (i); 928 } else if (lrval >= 0) { 929 printf("%ld\n", lrval); 930 return (i); 931 } 932 rval = -1; 933 break; 934 } 935#ifdef HAS_FREEBSD_ACL 936 case ACTION_PREPENDACL: 937 rval = -1; 938 939 acl = acl_get_file(STR(0), ACL_TYPE_NFS4); 940 if (acl == NULL) 941 break; 942 943 newacl = acl_from_text(STR(1)); 944 if (acl == NULL) 945 break; 946 947 while (acl_get_entry(newacl, entry_id, &newentry) == 1) { 948 entry_id = ACL_NEXT_ENTRY; 949 950 if (acl_create_entry_np(&acl, &entry, 0)) 951 break; 952 953 if (acl_copy_entry(entry, newentry)) 954 break; 955 } 956 957 rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl); 958 break; 959 case ACTION_READACL: 960 acl = acl_get_file(STR(0), ACL_TYPE_NFS4); 961 if (acl == NULL) 962 rval = -1; 963 else 964 rval = 0; 965 break; 966#endif 967 case ACTION_WRITE: 968 rval = write(NUM(0), STR(1), strlen(STR(1))); 969 break; 970 default: 971 fprintf(stderr, "unsupported syscall\n"); 972 exit(1); 973 } 974#undef STR 975#undef NUM 976 if (rval < 0) { 977 const char *serrno; 978 979 serrno = err2str(errno); 980 fprintf(stderr, "%s returned %d\n", scall->sd_name, rval); 981 printf("%s\n", serrno); 982 exit(1); 983 } 984 printf("0\n"); 985 return (i); 986} 987 988static void 989set_gids(char *gids) 990{ 991 gid_t *gidset; 992 long ngroups; 993 char *g, *endp; 994 unsigned i; 995 996 ngroups = sysconf(_SC_NGROUPS_MAX); 997 assert(ngroups > 0); 998 gidset = malloc(sizeof(*gidset) * ngroups); 999 assert(gidset != NULL); 1000 for (i = 0, g = strtok(gids, ","); g != NULL; 1001 g = strtok(NULL, ","), i++) { 1002 if (i >= ngroups) { 1003 fprintf(stderr, "too many gids\n"); 1004 exit(1); 1005 } 1006 gidset[i] = strtol(g, &endp, 0); 1007 if (*endp != '\0' && !isspace((unsigned char)*endp)) { 1008 fprintf(stderr, "invalid gid '%s' - number expected\n", 1009 g); 1010 exit(1); 1011 } 1012 } 1013 if (setgroups(i, gidset) < 0) { 1014 fprintf(stderr, "cannot change groups: %s\n", strerror(errno)); 1015 exit(1); 1016 } 1017 if (setegid(gidset[0]) < 0) { 1018 fprintf(stderr, "cannot change effective gid: %s\n", 1019 strerror(errno)); 1020 exit(1); 1021 } 1022 free(gidset); 1023} 1024 1025int 1026main(int argc, char *argv[]) 1027{ 1028 struct syscall_desc *scall; 1029 unsigned int n; 1030 char *gids, *endp; 1031 int uid, umsk, ch; 1032 1033 uid = -1; 1034 gids = NULL; 1035 umsk = 0; 1036 1037 while ((ch = getopt(argc, argv, "g:u:U:")) != -1) { 1038 switch(ch) { 1039 case 'g': 1040 gids = optarg; 1041 break; 1042 case 'u': 1043 uid = (int)strtol(optarg, &endp, 0); 1044 if (*endp != '\0' && !isspace((unsigned char)*endp)) { 1045 fprintf(stderr, "invalid uid '%s' - number " 1046 "expected\n", optarg); 1047 exit(1); 1048 } 1049 break; 1050 case 'U': 1051 umsk = (int)strtol(optarg, &endp, 0); 1052 if (*endp != '\0' && !isspace((unsigned char)*endp)) { 1053 fprintf(stderr, "invalid umask '%s' - number " 1054 "expected\n", optarg); 1055 exit(1); 1056 } 1057 break; 1058 default: 1059 usage(); 1060 } 1061 } 1062 argc -= optind; 1063 argv += optind; 1064 1065 if (argc < 1) { 1066 fprintf(stderr, "too few arguments\n"); 1067 usage(); 1068 } 1069 1070 if (gids != NULL) { 1071 fprintf(stderr, "changing groups to %s\n", gids); 1072 set_gids(gids); 1073 } 1074 if (uid != -1) { 1075 fprintf(stderr, "changing uid to %d\n", uid); 1076 if (setuid(uid) < 0) { 1077 fprintf(stderr, "cannot change uid: %s\n", 1078 strerror(errno)); 1079 exit(1); 1080 } 1081 } 1082 1083 /* Change umask to requested value or to 0, if not requested. */ 1084 umask(umsk); 1085 1086 for (;;) { 1087 scall = find_syscall(argv[0]); 1088 if (scall == NULL) { 1089 fprintf(stderr, "syscall '%s' not supported\n", 1090 argv[0]); 1091 exit(1); 1092 } 1093 argc++; 1094 argv++; 1095 n = call_syscall(scall, argv); 1096 argc += n; 1097 argv += n; 1098 if (argv[0] == NULL) 1099 break; 1100 argc++; 1101 argv++; 1102 } 1103 1104 exit(0); 1105} 1106 1107static const char * 1108err2str(int error) 1109{ 1110 static char errnum[8]; 1111 1112 switch (error) { 1113#ifdef EPERM 1114 case EPERM: 1115 return ("EPERM"); 1116#endif 1117#ifdef ENOENT 1118 case ENOENT: 1119 return ("ENOENT"); 1120#endif 1121#ifdef ESRCH 1122 case ESRCH: 1123 return ("ESRCH"); 1124#endif 1125#ifdef EINTR 1126 case EINTR: 1127 return ("EINTR"); 1128#endif 1129#ifdef EIO 1130 case EIO: 1131 return ("EIO"); 1132#endif 1133#ifdef ENXIO 1134 case ENXIO: 1135 return ("ENXIO"); 1136#endif 1137#ifdef E2BIG 1138 case E2BIG: 1139 return ("E2BIG"); 1140#endif 1141#ifdef ENOEXEC 1142 case ENOEXEC: 1143 return ("ENOEXEC"); 1144#endif 1145#ifdef EBADF 1146 case EBADF: 1147 return ("EBADF"); 1148#endif 1149#ifdef ECHILD 1150 case ECHILD: 1151 return ("ECHILD"); 1152#endif 1153#ifdef EDEADLK 1154 case EDEADLK: 1155 return ("EDEADLK"); 1156#endif 1157#ifdef ENOMEM 1158 case ENOMEM: 1159 return ("ENOMEM"); 1160#endif 1161#ifdef EACCES 1162 case EACCES: 1163 return ("EACCES"); 1164#endif 1165#ifdef EFAULT 1166 case EFAULT: 1167 return ("EFAULT"); 1168#endif 1169#ifdef ENOTBLK 1170 case ENOTBLK: 1171 return ("ENOTBLK"); 1172#endif 1173#ifdef EBUSY 1174 case EBUSY: 1175 return ("EBUSY"); 1176#endif 1177#ifdef EEXIST 1178 case EEXIST: 1179 return ("EEXIST"); 1180#endif 1181#ifdef EXDEV 1182 case EXDEV: 1183 return ("EXDEV"); 1184#endif 1185#ifdef ENODEV 1186 case ENODEV: 1187 return ("ENODEV"); 1188#endif 1189#ifdef ENOTDIR 1190 case ENOTDIR: 1191 return ("ENOTDIR"); 1192#endif 1193#ifdef EISDIR 1194 case EISDIR: 1195 return ("EISDIR"); 1196#endif 1197#ifdef EINVAL 1198 case EINVAL: 1199 return ("EINVAL"); 1200#endif 1201#ifdef ENFILE 1202 case ENFILE: 1203 return ("ENFILE"); 1204#endif 1205#ifdef EMFILE 1206 case EMFILE: 1207 return ("EMFILE"); 1208#endif 1209#ifdef ENOTTY 1210 case ENOTTY: 1211 return ("ENOTTY"); 1212#endif 1213#ifdef ETXTBSY 1214 case ETXTBSY: 1215 return ("ETXTBSY"); 1216#endif 1217#ifdef EFBIG 1218 case EFBIG: 1219 return ("EFBIG"); 1220#endif 1221#ifdef ENOSPC 1222 case ENOSPC: 1223 return ("ENOSPC"); 1224#endif 1225#ifdef ESPIPE 1226 case ESPIPE: 1227 return ("ESPIPE"); 1228#endif 1229#ifdef EROFS 1230 case EROFS: 1231 return ("EROFS"); 1232#endif 1233#ifdef EMLINK 1234 case EMLINK: 1235 return ("EMLINK"); 1236#endif 1237#ifdef EPIPE 1238 case EPIPE: 1239 return ("EPIPE"); 1240#endif 1241#ifdef EDOM 1242 case EDOM: 1243 return ("EDOM"); 1244#endif 1245#ifdef ERANGE 1246 case ERANGE: 1247 return ("ERANGE"); 1248#endif 1249#ifdef EAGAIN 1250 case EAGAIN: 1251 return ("EAGAIN"); 1252#endif 1253#ifdef EINPROGRESS 1254 case EINPROGRESS: 1255 return ("EINPROGRESS"); 1256#endif 1257#ifdef EALREADY 1258 case EALREADY: 1259 return ("EALREADY"); 1260#endif 1261#ifdef ENOTSOCK 1262 case ENOTSOCK: 1263 return ("ENOTSOCK"); 1264#endif 1265#ifdef EDESTADDRREQ 1266 case EDESTADDRREQ: 1267 return ("EDESTADDRREQ"); 1268#endif 1269#ifdef EMSGSIZE 1270 case EMSGSIZE: 1271 return ("EMSGSIZE"); 1272#endif 1273#ifdef EPROTOTYPE 1274 case EPROTOTYPE: 1275 return ("EPROTOTYPE"); 1276#endif 1277#ifdef ENOPROTOOPT 1278 case ENOPROTOOPT: 1279 return ("ENOPROTOOPT"); 1280#endif 1281#ifdef EPROTONOSUPPORT 1282 case EPROTONOSUPPORT: 1283 return ("EPROTONOSUPPORT"); 1284#endif 1285#ifdef ESOCKTNOSUPPORT 1286 case ESOCKTNOSUPPORT: 1287 return ("ESOCKTNOSUPPORT"); 1288#endif 1289#ifdef EOPNOTSUPP 1290 case EOPNOTSUPP: 1291 return ("EOPNOTSUPP"); 1292#endif 1293#ifdef EPFNOSUPPORT 1294 case EPFNOSUPPORT: 1295 return ("EPFNOSUPPORT"); 1296#endif 1297#ifdef EAFNOSUPPORT 1298 case EAFNOSUPPORT: 1299 return ("EAFNOSUPPORT"); 1300#endif 1301#ifdef EADDRINUSE 1302 case EADDRINUSE: 1303 return ("EADDRINUSE"); 1304#endif 1305#ifdef EADDRNOTAVAIL 1306 case EADDRNOTAVAIL: 1307 return ("EADDRNOTAVAIL"); 1308#endif 1309#ifdef ENETDOWN 1310 case ENETDOWN: 1311 return ("ENETDOWN"); 1312#endif 1313#ifdef ENETUNREACH 1314 case ENETUNREACH: 1315 return ("ENETUNREACH"); 1316#endif 1317#ifdef ENETRESET 1318 case ENETRESET: 1319 return ("ENETRESET"); 1320#endif 1321#ifdef ECONNABORTED 1322 case ECONNABORTED: 1323 return ("ECONNABORTED"); 1324#endif 1325#ifdef ECONNRESET 1326 case ECONNRESET: 1327 return ("ECONNRESET"); 1328#endif 1329#ifdef ENOBUFS 1330 case ENOBUFS: 1331 return ("ENOBUFS"); 1332#endif 1333#ifdef EISCONN 1334 case EISCONN: 1335 return ("EISCONN"); 1336#endif 1337#ifdef ENOTCONN 1338 case ENOTCONN: 1339 return ("ENOTCONN"); 1340#endif 1341#ifdef ESHUTDOWN 1342 case ESHUTDOWN: 1343 return ("ESHUTDOWN"); 1344#endif 1345#ifdef ETOOMANYREFS 1346 case ETOOMANYREFS: 1347 return ("ETOOMANYREFS"); 1348#endif 1349#ifdef ETIMEDOUT 1350 case ETIMEDOUT: 1351 return ("ETIMEDOUT"); 1352#endif 1353#ifdef ECONNREFUSED 1354 case ECONNREFUSED: 1355 return ("ECONNREFUSED"); 1356#endif 1357#ifdef ELOOP 1358 case ELOOP: 1359 return ("ELOOP"); 1360#endif 1361#ifdef ENAMETOOLONG 1362 case ENAMETOOLONG: 1363 return ("ENAMETOOLONG"); 1364#endif 1365#ifdef EHOSTDOWN 1366 case EHOSTDOWN: 1367 return ("EHOSTDOWN"); 1368#endif 1369#ifdef EHOSTUNREACH 1370 case EHOSTUNREACH: 1371 return ("EHOSTUNREACH"); 1372#endif 1373#ifdef ENOTEMPTY 1374 case ENOTEMPTY: 1375 return ("ENOTEMPTY"); 1376#endif 1377#ifdef EPROCLIM 1378 case EPROCLIM: 1379 return ("EPROCLIM"); 1380#endif 1381#ifdef EUSERS 1382 case EUSERS: 1383 return ("EUSERS"); 1384#endif 1385#ifdef EDQUOT 1386 case EDQUOT: 1387 return ("EDQUOT"); 1388#endif 1389#ifdef ESTALE 1390 case ESTALE: 1391 return ("ESTALE"); 1392#endif 1393#ifdef EREMOTE 1394 case EREMOTE: 1395 return ("EREMOTE"); 1396#endif 1397#ifdef EBADRPC 1398 case EBADRPC: 1399 return ("EBADRPC"); 1400#endif 1401#ifdef ERPCMISMATCH 1402 case ERPCMISMATCH: 1403 return ("ERPCMISMATCH"); 1404#endif 1405#ifdef EPROGUNAVAIL 1406 case EPROGUNAVAIL: 1407 return ("EPROGUNAVAIL"); 1408#endif 1409#ifdef EPROGMISMATCH 1410 case EPROGMISMATCH: 1411 return ("EPROGMISMATCH"); 1412#endif 1413#ifdef EPROCUNAVAIL 1414 case EPROCUNAVAIL: 1415 return ("EPROCUNAVAIL"); 1416#endif 1417#ifdef ENOLCK 1418 case ENOLCK: 1419 return ("ENOLCK"); 1420#endif 1421#ifdef ENOSYS 1422 case ENOSYS: 1423 return ("ENOSYS"); 1424#endif 1425#ifdef EFTYPE 1426 case EFTYPE: 1427 return ("EFTYPE"); 1428#endif 1429#ifdef EAUTH 1430 case EAUTH: 1431 return ("EAUTH"); 1432#endif 1433#ifdef ENEEDAUTH 1434 case ENEEDAUTH: 1435 return ("ENEEDAUTH"); 1436#endif 1437#ifdef EIDRM 1438 case EIDRM: 1439 return ("EIDRM"); 1440#endif 1441#ifdef ENOMSG 1442 case ENOMSG: 1443 return ("ENOMSG"); 1444#endif 1445#ifdef EOVERFLOW 1446 case EOVERFLOW: 1447 return ("EOVERFLOW"); 1448#endif 1449#ifdef ECANCELED 1450 case ECANCELED: 1451 return ("ECANCELED"); 1452#endif 1453#ifdef EILSEQ 1454 case EILSEQ: 1455 return ("EILSEQ"); 1456#endif 1457#ifdef ENOATTR 1458 case ENOATTR: 1459 return ("ENOATTR"); 1460#endif 1461#ifdef EDOOFUS 1462 case EDOOFUS: 1463 return ("EDOOFUS"); 1464#endif 1465#ifdef EBADMSG 1466 case EBADMSG: 1467 return ("EBADMSG"); 1468#endif 1469#ifdef EMULTIHOP 1470 case EMULTIHOP: 1471 return ("EMULTIHOP"); 1472#endif 1473#ifdef ENOLINK 1474 case ENOLINK: 1475 return ("ENOLINK"); 1476#endif 1477#ifdef EPROTO 1478 case EPROTO: 1479 return ("EPROTO"); 1480#endif 1481 default: 1482 snprintf(errnum, sizeof(errnum), "%d", error); 1483 return (errnum); 1484 } 1485} 1486