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