1 /* $OpenBSD: fstest.c,v 1.6 2017/01/12 01:12:56 bluhm Exp $ */ 2 3 /* 4 * Copyright (c) 2006-2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: src/tools/regression/fstest/fstest.c,v 1.1 2007/01/17 01:42:07 pjd Exp $ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/stat.h> 33 #include <sys/sysctl.h> 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 #include <fcntl.h> 39 #include <grp.h> 40 #include <string.h> 41 #include <ctype.h> 42 #include <errno.h> 43 #include <assert.h> 44 45 enum action { 46 ACTION_OPEN, 47 ACTION_CREATE, 48 ACTION_UNLINK, 49 ACTION_MKDIR, 50 ACTION_RMDIR, 51 ACTION_LINK, 52 ACTION_SYMLINK, 53 ACTION_RENAME, 54 ACTION_MKFIFO, 55 ACTION_CHMOD, 56 ACTION_CHOWN, 57 ACTION_LCHOWN, 58 ACTION_CHFLAGS, 59 ACTION_LCHFLAGS, 60 ACTION_TRUNCATE, 61 ACTION_STAT, 62 ACTION_LSTAT, 63 }; 64 65 #define TYPE_NONE 0x0000 66 #define TYPE_STRING 0x0001 67 #define TYPE_NUMBER 0x0002 68 #define TYPE_OPTIONAL 0x0100 69 #define MAX_ARGS 8 70 71 struct syscall_desc { 72 char *sd_name; 73 enum action sd_action; 74 int sd_args[MAX_ARGS]; 75 }; 76 77 static struct syscall_desc syscalls[] = { 78 { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, 79 TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } }, 80 { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 81 { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } }, 82 { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 83 { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } }, 84 { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 85 { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 86 { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 87 { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 88 { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 89 { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, 90 TYPE_NUMBER, TYPE_NONE } }, 91 { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, 92 TYPE_NUMBER, TYPE_NONE } }, 93 { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 94 { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, 95 TYPE_NONE } }, 96 { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, 97 TYPE_NONE } }, 98 { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 99 { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 100 { NULL, -1, { TYPE_NONE } } 101 }; 102 103 struct flag { 104 long long f_flag; 105 char *f_str; 106 }; 107 108 static struct flag open_flags[] = { 109 { O_RDONLY, "O_RDONLY" }, 110 { O_WRONLY, "O_WRONLY" }, 111 { O_RDWR, "O_RDWR" }, 112 { O_NONBLOCK, "O_NONBLOCK" }, 113 { O_APPEND, "O_APPEND" }, 114 { O_CREAT, "O_CREAT" }, 115 { O_TRUNC, "O_TRUNC" }, 116 { O_EXCL, "O_EXCL" }, 117 { O_SHLOCK, "O_SHLOCK" }, 118 { O_EXLOCK, "O_EXLOCK" }, 119 { O_FSYNC, "O_FSYNC" }, 120 { O_SYNC, "O_SYNC" }, 121 { O_NOFOLLOW, "O_NOFOLLOW" }, 122 { O_NOCTTY, "O_NOCTTY" }, 123 { 0, NULL } 124 }; 125 126 static struct flag chflags_flags[] = { 127 { UF_NODUMP, "UF_NODUMP" }, 128 { UF_IMMUTABLE, "UF_IMMUTABLE" }, 129 { UF_APPEND, "UF_APPEND" }, 130 { UF_OPAQUE, "UF_OPAQUE" }, 131 { SF_ARCHIVED, "SF_ARCHIVED" }, 132 { SF_IMMUTABLE, "SF_IMMUTABLE" }, 133 { SF_APPEND, "SF_APPEND" }, 134 { 0, NULL } 135 }; 136 137 static const char *err2str(int error); 138 int use_appimm; /* use the SF_APPEND and SF_IMMUTABLE chflags */ 139 140 __dead static void 141 usage(void) 142 { 143 fprintf(stderr, "usage: fstest [-u uid] [-g gid1[,gid2[...]]] syscall " 144 "args ...\n"); 145 exit(1); 146 } 147 148 static long long 149 str2flags(struct flag *tflags, char *sflags) 150 { 151 long long flags = 0; 152 unsigned int i; 153 char *f; 154 155 for (f = strtok(sflags, ","); f != NULL; f = strtok(NULL, ",")) { 156 /* Support magic 'none' flag which just reset all flags. */ 157 if (strcmp(f, "none") == 0) 158 return (0); 159 for (i = 0; tflags[i].f_str != NULL; i++) { 160 if (strcmp(tflags[i].f_str, f) == 0) 161 break; 162 } 163 if (tflags[i].f_str == NULL) { 164 fprintf(stderr, "unknown flag '%s'\n", f); 165 exit(1); 166 } 167 flags |= tflags[i].f_flag; 168 } 169 return (flags); 170 } 171 172 static char * 173 flags2str(struct flag *tflags, long long flags) 174 { 175 static char sflags[1024]; 176 unsigned int i; 177 178 sflags[0] = '\0'; 179 for (i = 0; tflags[i].f_str != NULL; i++) { 180 if (flags & tflags[i].f_flag) { 181 if (sflags[0] != '\0') 182 strlcat(sflags, ",", sizeof(sflags)); 183 strlcat(sflags, tflags[i].f_str, sizeof(sflags)); 184 } 185 } 186 if (sflags[0] == '\0') 187 strlcpy(sflags, "none", sizeof(sflags)); 188 return (sflags); 189 } 190 191 static struct syscall_desc * 192 find_syscall(const char *name) 193 { 194 int i; 195 196 for (i = 0; syscalls[i].sd_name != NULL; i++) { 197 if (strcmp(syscalls[i].sd_name, name) == 0) 198 return (&syscalls[i]); 199 } 200 return (NULL); 201 } 202 203 static void 204 show_stat(struct stat *sp, const char *what) 205 { 206 207 if (strcmp(what, "mode") == 0) 208 printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS)); 209 else if (strcmp(what, "inode") == 0) 210 printf("%llu", (unsigned long long)sp->st_ino); 211 else if (strcmp(what, "nlink") == 0) 212 printf("%lld", (long long)sp->st_nlink); 213 else if (strcmp(what, "uid") == 0) 214 printf("%d", (int)sp->st_uid); 215 else if (strcmp(what, "gid") == 0) 216 printf("%d", (int)sp->st_gid); 217 else if (strcmp(what, "size") == 0) 218 printf("%lld", (long long)sp->st_size); 219 else if (strcmp(what, "blocks") == 0) 220 printf("%lld", (long long)sp->st_blocks); 221 else if (strcmp(what, "atime") == 0) 222 printf("%lld", (long long)sp->st_atime); 223 else if (strcmp(what, "mtime") == 0) 224 printf("%lld", (long long)sp->st_mtime); 225 else if (strcmp(what, "ctime") == 0) 226 printf("%lld", (long long)sp->st_ctime); 227 else if (strcmp(what, "flags") == 0) 228 printf("%s", flags2str(chflags_flags, sp->st_flags)); 229 else if (strcmp(what, "type") == 0) { 230 switch (sp->st_mode & S_IFMT) { 231 case S_IFIFO: 232 printf("fifo"); 233 break; 234 case S_IFCHR: 235 printf("char"); 236 break; 237 case S_IFDIR: 238 printf("dir"); 239 break; 240 case S_IFBLK: 241 printf("block"); 242 break; 243 case S_IFREG: 244 printf("regular"); 245 break; 246 case S_IFLNK: 247 printf("symlink"); 248 break; 249 case S_IFSOCK: 250 printf("socket"); 251 break; 252 default: 253 printf("unknown"); 254 break; 255 } 256 } else { 257 printf("unknown"); 258 } 259 } 260 261 static void 262 show_stats(struct stat *sp, char *what) 263 { 264 const char *s = ""; 265 char *w; 266 267 for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) { 268 printf("%s", s); 269 show_stat(sp, w); 270 s = ","; 271 } 272 printf("\n"); 273 } 274 275 static unsigned int 276 call_syscall(struct syscall_desc *scall, char *argv[]) 277 { 278 struct stat sb; 279 long long flags; 280 unsigned int i; 281 char *endp; 282 int rval; 283 union { 284 char *str; 285 long long num; 286 } args[MAX_ARGS]; 287 unsigned int ch_flags; 288 289 /* 290 * Verify correctness of the arguments. 291 */ 292 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) { 293 if (scall->sd_args[i] == TYPE_NONE) { 294 if (argv[i] == NULL || strcmp(argv[i], ":") == 0) 295 break; 296 fprintf(stderr, "too many arguments [%s]\n", argv[i]); 297 exit(1); 298 } else { 299 if (argv[i] == NULL || strcmp(argv[i], ":") == 0) { 300 if (scall->sd_args[i] & TYPE_OPTIONAL) 301 break; 302 fprintf(stderr, "too few arguments\n"); 303 exit(1); 304 } 305 if (scall->sd_args[i] & TYPE_STRING) { 306 if (strcmp(argv[i], "NULL") == 0) 307 args[i].str = NULL; 308 else if (strcmp(argv[i], "DEADCODE") == 0) 309 args[i].str = (void *)0xdeadc0de; 310 else 311 args[i].str = argv[i]; 312 } else if (scall->sd_args[i] & TYPE_NUMBER) { 313 args[i].num = strtoll(argv[i], &endp, 0); 314 if (*endp != '\0' && 315 !isspace((unsigned char)*endp)) { 316 fprintf(stderr, "invalid argument %u, " 317 "number expected [%s]\n", i, endp); 318 exit(1); 319 } 320 } 321 } 322 } 323 /* 324 * Call the given syscall. 325 */ 326 #define NUM(n) (args[(n)].num) 327 #define STR(n) (args[(n)].str) 328 switch (scall->sd_action) { 329 case ACTION_OPEN: 330 flags = str2flags(open_flags, STR(1)); 331 if (flags & O_CREAT) { 332 if (i == 2) { 333 fprintf(stderr, "too few arguments\n"); 334 exit(1); 335 } 336 rval = open(STR(0), flags, (mode_t)NUM(2)); 337 } else { 338 if (i == 3) { 339 fprintf(stderr, "too many arguments\n"); 340 exit(1); 341 } 342 rval = open(STR(0), flags); 343 } 344 break; 345 case ACTION_CREATE: 346 rval = open(STR(0), O_CREAT | O_EXCL, NUM(1)); 347 if (rval >= 0) 348 close(rval); 349 break; 350 case ACTION_UNLINK: 351 rval = unlink(STR(0)); 352 break; 353 case ACTION_MKDIR: 354 rval = mkdir(STR(0), NUM(1)); 355 break; 356 case ACTION_RMDIR: 357 rval = rmdir(STR(0)); 358 break; 359 case ACTION_LINK: 360 rval = link(STR(0), STR(1)); 361 break; 362 case ACTION_SYMLINK: 363 rval = symlink(STR(0), STR(1)); 364 break; 365 case ACTION_RENAME: 366 rval = rename(STR(0), STR(1)); 367 break; 368 case ACTION_MKFIFO: 369 rval = mkfifo(STR(0), NUM(1)); 370 break; 371 case ACTION_CHMOD: 372 rval = chmod(STR(0), NUM(1)); 373 break; 374 case ACTION_CHOWN: 375 rval = chown(STR(0), NUM(1), NUM(2)); 376 break; 377 case ACTION_LCHOWN: 378 rval = lchown(STR(0), NUM(1), NUM(2)); 379 break; 380 case ACTION_CHFLAGS: 381 ch_flags = str2flags(chflags_flags, STR(1)); 382 if (!use_appimm) 383 ch_flags &= ~(SF_APPEND|SF_IMMUTABLE); 384 rval = chflags(STR(0), ch_flags); 385 break; 386 case ACTION_LCHFLAGS: 387 ch_flags = str2flags(chflags_flags, STR(1)); 388 if (!use_appimm) 389 ch_flags &= ~(SF_APPEND|SF_IMMUTABLE); 390 rval = chflagsat(AT_FDCWD, STR(0), ch_flags, 391 AT_SYMLINK_NOFOLLOW); 392 break; 393 case ACTION_TRUNCATE: 394 rval = truncate(STR(0), NUM(1)); 395 break; 396 case ACTION_STAT: 397 rval = stat(STR(0), &sb); 398 if (rval == 0) { 399 show_stats(&sb, STR(1)); 400 return (i); 401 } 402 break; 403 case ACTION_LSTAT: 404 rval = lstat(STR(0), &sb); 405 if (rval == 0) { 406 show_stats(&sb, STR(1)); 407 return (i); 408 } 409 break; 410 default: 411 fprintf(stderr, "unsupported syscall\n"); 412 exit(1); 413 } 414 #undef STR 415 #undef NUM 416 if (rval < 0) { 417 printf("%s\n", err2str(errno)); 418 exit(1); 419 } 420 printf("0\n"); 421 return (i); 422 } 423 424 static void 425 set_gids(char *gids) 426 { 427 gid_t *gidset; 428 long ngroups; 429 char *g, *endp; 430 unsigned i; 431 432 ngroups = sysconf(_SC_NGROUPS_MAX); 433 assert(ngroups > 0); 434 gidset = reallocarray(NULL, ngroups, sizeof(*gidset)); 435 assert(gidset != NULL); 436 for (i = 0, g = strtok(gids, ","); g != NULL; 437 g = strtok(NULL, ","), i++) { 438 if (i >= ngroups) { 439 fprintf(stderr, "too many gids\n"); 440 exit(1); 441 } 442 gidset[i] = strtol(g, &endp, 0); 443 if (*endp != '\0' && !isspace((unsigned char)*endp)) { 444 fprintf(stderr, "invalid gid '%s' - number expected\n", 445 g); 446 exit(1); 447 } 448 } 449 if (setgroups(i, gidset) < 0) { 450 fprintf(stderr, "cannot change groups: %s\n", strerror(errno)); 451 exit(1); 452 } 453 free(gidset); 454 } 455 456 int 457 main(int argc, char *argv[]) 458 { 459 struct syscall_desc *scall; 460 unsigned int n; 461 char *gids, *endp; 462 int uid, umsk, ch; 463 int mib[2]; 464 size_t len; 465 int securelevel; 466 467 uid = -1; 468 gids = NULL; 469 umsk = 0; 470 471 while ((ch = getopt(argc, argv, "g:u:U:")) != -1) { 472 switch(ch) { 473 case 'g': 474 gids = optarg; 475 break; 476 case 'u': 477 uid = (int)strtol(optarg, &endp, 0); 478 if (*endp != '\0' && !isspace((unsigned char)*endp)) { 479 fprintf(stderr, "invalid uid '%s' - number " 480 "expected\n", optarg); 481 exit(1); 482 } 483 break; 484 case 'U': 485 umsk = (int)strtol(optarg, &endp, 0); 486 if (*endp != '\0' && !isspace((unsigned char)*endp)) { 487 fprintf(stderr, "invalid umask '%s' - number " 488 "expected\n", optarg); 489 exit(1); 490 } 491 break; 492 default: 493 usage(); 494 } 495 } 496 argc -= optind; 497 argv += optind; 498 499 if (argc < 1) { 500 fprintf(stderr, "too few arguments\n"); 501 usage(); 502 } 503 504 if (gids != NULL) 505 set_gids(gids); 506 if (uid != -1) { 507 if (setuid(uid) < 0) { 508 fprintf(stderr, "cannot change uid: %s\n", 509 strerror(errno)); 510 exit(1); 511 } 512 } 513 514 /* 515 * Find out if we should use the SF_IMMUTABLE and SF_APPEND flags; 516 * Since we run by default on kern.securelevel=1 these cause false 517 * positives. 518 */ 519 mib[0] = CTL_KERN; 520 mib[1] = KERN_SECURELVL; 521 len = sizeof(securelevel); 522 if (sysctl(mib, 2, &securelevel, &len, NULL, 0) == -1) { 523 fprintf(stderr, "cannot get kernel securelevel\n"); 524 exit(1); 525 } 526 if (securelevel == 0 || securelevel == -1) 527 use_appimm = 1; 528 else 529 use_appimm = 0; 530 531 /* Change umask to requested value or to 0, if not requested. */ 532 umask(umsk); 533 534 for (;;) { 535 scall = find_syscall(argv[0]); 536 if (scall == NULL) { 537 fprintf(stderr, "syscall '%s' not supported\n", 538 argv[0]); 539 exit(1); 540 } 541 argc++; 542 argv++; 543 n = call_syscall(scall, argv); 544 argc += n; 545 argv += n; 546 if (argv[0] == NULL) 547 break; 548 argc++; 549 argv++; 550 } 551 552 exit(0); 553 } 554 555 static const char * 556 err2str(int error) 557 { 558 static char errnum[8]; 559 560 switch (error) { 561 case EPERM: 562 return ("EPERM"); 563 case ENOENT: 564 return ("ENOENT"); 565 case ESRCH: 566 return ("ESRCH"); 567 case EINTR: 568 return ("EINTR"); 569 case EIO: 570 return ("EIO"); 571 case ENXIO: 572 return ("ENXIO"); 573 case E2BIG: 574 return ("E2BIG"); 575 case ENOEXEC: 576 return ("ENOEXEC"); 577 case EBADF: 578 return ("EBADF"); 579 case ECHILD: 580 return ("ECHILD"); 581 case EDEADLK: 582 return ("EDEADLK"); 583 case ENOMEM: 584 return ("ENOMEM"); 585 case EACCES: 586 return ("EACCES"); 587 case EFAULT: 588 return ("EFAULT"); 589 case ENOTBLK: 590 return ("ENOTBLK"); 591 case EBUSY: 592 return ("EBUSY"); 593 case EEXIST: 594 return ("EEXIST"); 595 case EXDEV: 596 return ("EXDEV"); 597 case ENODEV: 598 return ("ENODEV"); 599 case ENOTDIR: 600 return ("ENOTDIR"); 601 case EISDIR: 602 return ("EISDIR"); 603 case EINVAL: 604 return ("EINVAL"); 605 case ENFILE: 606 return ("ENFILE"); 607 case EMFILE: 608 return ("EMFILE"); 609 case ENOTTY: 610 return ("ENOTTY"); 611 case ETXTBSY: 612 return ("ETXTBSY"); 613 case EFBIG: 614 return ("EFBIG"); 615 case ENOSPC: 616 return ("ENOSPC"); 617 case ESPIPE: 618 return ("ESPIPE"); 619 case EROFS: 620 return ("EROFS"); 621 case EMLINK: 622 return ("EMLINK"); 623 case EPIPE: 624 return ("EPIPE"); 625 case EDOM: 626 return ("EDOM"); 627 case ERANGE: 628 return ("ERANGE"); 629 case EAGAIN: 630 return ("EAGAIN"); 631 case EINPROGRESS: 632 return ("EINPROGRESS"); 633 case EALREADY: 634 return ("EALREADY"); 635 case ENOTSOCK: 636 return ("ENOTSOCK"); 637 case EDESTADDRREQ: 638 return ("EDESTADDRREQ"); 639 case EMSGSIZE: 640 return ("EMSGSIZE"); 641 case EPROTOTYPE: 642 return ("EPROTOTYPE"); 643 case ENOPROTOOPT: 644 return ("ENOPROTOOPT"); 645 case EPROTONOSUPPORT: 646 return ("EPROTONOSUPPORT"); 647 case ESOCKTNOSUPPORT: 648 return ("ESOCKTNOSUPPORT"); 649 case EOPNOTSUPP: 650 return ("EOPNOTSUPP"); 651 case EPFNOSUPPORT: 652 return ("EPFNOSUPPORT"); 653 case EAFNOSUPPORT: 654 return ("EAFNOSUPPORT"); 655 case EADDRINUSE: 656 return ("EADDRINUSE"); 657 case EADDRNOTAVAIL: 658 return ("EADDRNOTAVAIL"); 659 case ENETDOWN: 660 return ("ENETDOWN"); 661 case ENETUNREACH: 662 return ("ENETUNREACH"); 663 case ENETRESET: 664 return ("ENETRESET"); 665 case ECONNABORTED: 666 return ("ECONNABORTED"); 667 case ECONNRESET: 668 return ("ECONNRESET"); 669 case ENOBUFS: 670 return ("ENOBUFS"); 671 case EISCONN: 672 return ("EISCONN"); 673 case ENOTCONN: 674 return ("ENOTCONN"); 675 case ESHUTDOWN: 676 return ("ESHUTDOWN"); 677 case ETOOMANYREFS: 678 return ("ETOOMANYREFS"); 679 case ETIMEDOUT: 680 return ("ETIMEDOUT"); 681 case ECONNREFUSED: 682 return ("ECONNREFUSED"); 683 case ELOOP: 684 return ("ELOOP"); 685 case ENAMETOOLONG: 686 return ("ENAMETOOLONG"); 687 case EHOSTDOWN: 688 return ("EHOSTDOWN"); 689 case EHOSTUNREACH: 690 return ("EHOSTUNREACH"); 691 case ENOTEMPTY: 692 return ("ENOTEMPTY"); 693 case EPROCLIM: 694 return ("EPROCLIM"); 695 case EUSERS: 696 return ("EUSERS"); 697 case EDQUOT: 698 return ("EDQUOT"); 699 case ESTALE: 700 return ("ESTALE"); 701 case EREMOTE: 702 return ("EREMOTE"); 703 case EBADRPC: 704 return ("EBADRPC"); 705 case ERPCMISMATCH: 706 return ("ERPCMISMATCH"); 707 case EPROGUNAVAIL: 708 return ("EPROGUNAVAIL"); 709 case EPROGMISMATCH: 710 return ("EPROGMISMATCH"); 711 case EPROCUNAVAIL: 712 return ("EPROCUNAVAIL"); 713 case ENOLCK: 714 return ("ENOLCK"); 715 case ENOSYS: 716 return ("ENOSYS"); 717 case EFTYPE: 718 return ("EFTYPE"); 719 case EAUTH: 720 return ("EAUTH"); 721 case ENEEDAUTH: 722 return ("ENEEDAUTH"); 723 case EILSEQ: 724 return ("EILSEQ"); 725 case ENOATTR: 726 return ("ENOATTR"); 727 default: 728 snprintf(errnum, sizeof(errnum), "%d", error); 729 return (errnum); 730 } 731 } 732