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