1271294Sngie/*- 2271294Sngie * Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3271294Sngie * All rights reserved. 4271294Sngie * 5271294Sngie * Redistribution and use in source and binary forms, with or without 6271294Sngie * modification, are permitted provided that the following conditions 7271294Sngie * are met: 8271294Sngie * 1. Redistributions of source code must retain the above copyright 9271294Sngie * notice, this list of conditions and the following disclaimer. 10271294Sngie * 2. Redistributions in binary form must reproduce the above copyright 11271294Sngie * notice, this list of conditions and the following disclaimer in the 12271294Sngie * documentation and/or other materials provided with the distribution. 13271294Sngie * 14271294Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15271294Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16271294Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17271294Sngie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18271294Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19271294Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20271294Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21271294Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22271294Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23271294Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24271294Sngie * SUCH DAMAGE. 25271294Sngie * 26271294Sngie * $FreeBSD$ 27271294Sngie */ 28271294Sngie 29271294Sngie#include <sys/param.h> 30271294Sngie#include <sys/types.h> 31271294Sngie#include <sys/stat.h> 32271294Sngie#include <sys/socket.h> 33271294Sngie#include <sys/un.h> 34271294Sngie#ifndef makedev 35271294Sngie#include <sys/mkdev.h> 36271294Sngie#endif 37271294Sngie 38271294Sngie#include <assert.h> 39271294Sngie#include <ctype.h> 40271294Sngie#include <errno.h> 41271294Sngie#include <fcntl.h> 42271294Sngie#include <grp.h> 43271294Sngie#include <stdio.h> 44271294Sngie#include <stdlib.h> 45271294Sngie#include <string.h> 46271294Sngie#include <unistd.h> 47271294Sngie 48271294Sngie#ifndef HAS_TRUNCATE64 49271294Sngie#define truncate64 truncate 50271294Sngie#define ftruncate64 ftruncate 51271294Sngie#endif 52271294Sngie#ifndef HAS_STAT64 53271294Sngie#define stat64 stat 54271294Sngie#define fstat64 fstat 55271294Sngie#define lstat64 lstat 56271294Sngie#endif 57271294Sngie#ifdef HAS_FREEBSD_ACL 58271294Sngie#include <sys/acl.h> 59271294Sngie#endif 60271294Sngie 61271294Sngie#ifndef ALLPERMS 62271294Sngie#define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) 63271294Sngie#endif 64271294Sngie 65271294Sngieenum action { 66271294Sngie ACTION_OPEN, 67271294Sngie ACTION_OPENAT, 68271294Sngie ACTION_CREATE, 69271294Sngie ACTION_UNLINK, 70271294Sngie ACTION_UNLINKAT, 71271294Sngie ACTION_MKDIR, 72271294Sngie ACTION_MKDIRAT, 73271294Sngie ACTION_RMDIR, 74271294Sngie ACTION_LINK, 75271294Sngie ACTION_LINKAT, 76271294Sngie ACTION_SYMLINK, 77271294Sngie ACTION_SYMLINKAT, 78271294Sngie ACTION_RENAME, 79271294Sngie ACTION_RENAMEAT, 80271294Sngie ACTION_MKFIFO, 81271294Sngie ACTION_MKFIFOAT, 82271294Sngie ACTION_MKNOD, 83271294Sngie ACTION_MKNODAT, 84271294Sngie ACTION_BIND, 85271294Sngie#ifdef HAS_BINDAT 86271294Sngie ACTION_BINDAT, 87271294Sngie#endif 88271294Sngie ACTION_CONNECT, 89271294Sngie#ifdef HAS_CONNECTAT 90271294Sngie ACTION_CONNECTAT, 91271294Sngie#endif 92271294Sngie ACTION_CHMOD, 93271294Sngie ACTION_FCHMOD, 94271294Sngie#ifdef HAS_LCHMOD 95271294Sngie ACTION_LCHMOD, 96271294Sngie#endif 97271294Sngie ACTION_FCHMODAT, 98271294Sngie ACTION_CHOWN, 99271294Sngie ACTION_FCHOWN, 100271294Sngie ACTION_LCHOWN, 101271294Sngie ACTION_FCHOWNAT, 102271294Sngie#ifdef HAS_CHFLAGS 103271294Sngie ACTION_CHFLAGS, 104271294Sngie#endif 105271294Sngie#ifdef HAS_FCHFLAGS 106271294Sngie ACTION_FCHFLAGS, 107271294Sngie#endif 108271294Sngie#ifdef HAS_CHFLAGSAT 109271294Sngie ACTION_CHFLAGSAT, 110271294Sngie#endif 111271294Sngie#ifdef HAS_LCHFLAGS 112271294Sngie ACTION_LCHFLAGS, 113271294Sngie#endif 114271294Sngie ACTION_TRUNCATE, 115271294Sngie ACTION_FTRUNCATE, 116271294Sngie ACTION_STAT, 117271294Sngie ACTION_FSTAT, 118271294Sngie ACTION_LSTAT, 119271294Sngie ACTION_FSTATAT, 120271294Sngie ACTION_PATHCONF, 121271294Sngie ACTION_FPATHCONF, 122271294Sngie#ifdef HAS_LPATHCONF 123271294Sngie ACTION_LPATHCONF, 124271294Sngie#endif 125271294Sngie#ifdef HAS_FREEBSD_ACL 126271294Sngie ACTION_PREPENDACL, 127271294Sngie ACTION_READACL, 128271294Sngie#endif 129271294Sngie ACTION_WRITE, 130271294Sngie}; 131271294Sngie 132271294Sngie#define TYPE_NONE 0x0000 133271294Sngie#define TYPE_STRING 0x0001 134271294Sngie#define TYPE_NUMBER 0x0002 135271294Sngie#define TYPE_DESCRIPTOR 0x0003 136271294Sngie#define TYPE_MASK 0x000f 137271294Sngie 138271294Sngie#define TYPE_OPTIONAL 0x0100 139271294Sngie 140271294Sngie#define MAX_ARGS 8 141271294Sngie 142271294Sngiestruct syscall_desc { 143271294Sngie const char *sd_name; 144271294Sngie enum action sd_action; 145271294Sngie int sd_args[MAX_ARGS]; 146271294Sngie}; 147271294Sngie 148271294Sngiestatic struct syscall_desc syscalls[] = { 149271294Sngie { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } }, 150271294Sngie { "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } }, 151271294Sngie { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 152271294Sngie { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } }, 153271294Sngie { "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 154271294Sngie { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 155271294Sngie { "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 156271294Sngie { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } }, 157271294Sngie { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 158271294Sngie { "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 159271294Sngie { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 160271294Sngie { "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 161271294Sngie { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 162271294Sngie { "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 163271294Sngie { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 164271294Sngie { "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 165271294Sngie { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, 166271294Sngie { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, 167271294Sngie { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } }, 168271294Sngie#ifdef HAS_BINDAT 169271294Sngie { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 170271294Sngie#endif 171271294Sngie { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } }, 172271294Sngie#ifdef HAS_CONNECTAT 173271294Sngie { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 174271294Sngie#endif 175271294Sngie { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 176271294Sngie { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } }, 177271294Sngie#ifdef HAS_LCHMOD 178271294Sngie { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 179271294Sngie#endif 180271294Sngie { "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } }, 181271294Sngie { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } }, 182271294Sngie { "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } }, 183271294Sngie { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } }, 184271294Sngie { "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } }, 185271294Sngie#ifdef HAS_CHFLAGS 186271294Sngie { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 187271294Sngie#endif 188271294Sngie#ifdef HAS_FCHFLAGS 189271294Sngie { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 190271294Sngie#endif 191271294Sngie#ifdef HAS_CHFLAGSAT 192271294Sngie { "chflagsat", ACTION_CHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 193271294Sngie#endif 194271294Sngie#ifdef HAS_LCHFLAGS 195271294Sngie { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 196271294Sngie#endif 197271294Sngie { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 198271294Sngie { "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } }, 199271294Sngie { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 200271294Sngie { "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 201271294Sngie { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 202271294Sngie { "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 203271294Sngie { "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 204271294Sngie { "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 205271294Sngie#ifdef HAS_LPATHCONF 206271294Sngie { "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 207271294Sngie#endif 208271294Sngie#ifdef HAS_FREEBSD_ACL 209271294Sngie { "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 210271294Sngie { "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } }, 211271294Sngie#endif 212271294Sngie { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 213271294Sngie { NULL, -1, { TYPE_NONE } } 214271294Sngie}; 215271294Sngie 216271294Sngiestruct flag { 217271294Sngie long long f_flag; 218271294Sngie const char *f_str; 219271294Sngie}; 220271294Sngie 221271294Sngiestatic struct flag open_flags[] = { 222271294Sngie#ifdef O_RDONLY 223271294Sngie { O_RDONLY, "O_RDONLY" }, 224271294Sngie#endif 225271294Sngie#ifdef O_WRONLY 226271294Sngie { O_WRONLY, "O_WRONLY" }, 227271294Sngie#endif 228271294Sngie#ifdef O_RDWR 229271294Sngie { O_RDWR, "O_RDWR" }, 230271294Sngie#endif 231271294Sngie#ifdef O_NONBLOCK 232271294Sngie { O_NONBLOCK, "O_NONBLOCK" }, 233271294Sngie#endif 234271294Sngie#ifdef O_APPEND 235271294Sngie { O_APPEND, "O_APPEND" }, 236271294Sngie#endif 237271294Sngie#ifdef O_CREAT 238271294Sngie { O_CREAT, "O_CREAT" }, 239271294Sngie#endif 240271294Sngie#ifdef O_TRUNC 241271294Sngie { O_TRUNC, "O_TRUNC" }, 242271294Sngie#endif 243271294Sngie#ifdef O_EXCL 244271294Sngie { O_EXCL, "O_EXCL" }, 245271294Sngie#endif 246271294Sngie#ifdef O_SHLOCK 247271294Sngie { O_SHLOCK, "O_SHLOCK" }, 248271294Sngie#endif 249271294Sngie#ifdef O_EXLOCK 250271294Sngie { O_EXLOCK, "O_EXLOCK" }, 251271294Sngie#endif 252271294Sngie#ifdef O_DIRECT 253271294Sngie { O_DIRECT, "O_DIRECT" }, 254271294Sngie#endif 255271294Sngie#ifdef O_FSYNC 256271294Sngie { O_FSYNC, "O_FSYNC" }, 257271294Sngie#endif 258271294Sngie#ifdef O_SYNC 259271294Sngie { O_SYNC, "O_SYNC" }, 260271294Sngie#endif 261271294Sngie#ifdef O_NOFOLLOW 262271294Sngie { O_NOFOLLOW, "O_NOFOLLOW" }, 263271294Sngie#endif 264271294Sngie#ifdef O_NOCTTY 265271294Sngie { O_NOCTTY, "O_NOCTTY" }, 266271294Sngie#endif 267271294Sngie#ifdef O_DIRECTORY 268271294Sngie { O_DIRECTORY, "O_DIRECTORY" }, 269271294Sngie#endif 270271294Sngie { 0, NULL } 271271294Sngie}; 272271294Sngie 273271294Sngie#ifdef HAS_CHFLAGS 274271294Sngiestatic struct flag chflags_flags[] = { 275271294Sngie#ifdef UF_NODUMP 276271294Sngie { UF_NODUMP, "UF_NODUMP" }, 277271294Sngie#endif 278271294Sngie#ifdef UF_IMMUTABLE 279271294Sngie { UF_IMMUTABLE, "UF_IMMUTABLE" }, 280271294Sngie#endif 281271294Sngie#ifdef UF_APPEND 282271294Sngie { UF_APPEND, "UF_APPEND" }, 283271294Sngie#endif 284271294Sngie#ifdef UF_NOUNLINK 285271294Sngie { UF_NOUNLINK, "UF_NOUNLINK" }, 286271294Sngie#endif 287271294Sngie#ifdef UF_OPAQUE 288271294Sngie { UF_OPAQUE, "UF_OPAQUE" }, 289271294Sngie#endif 290271294Sngie#ifdef SF_ARCHIVED 291271294Sngie { SF_ARCHIVED, "SF_ARCHIVED" }, 292271294Sngie#endif 293271294Sngie#ifdef SF_IMMUTABLE 294271294Sngie { SF_IMMUTABLE, "SF_IMMUTABLE" }, 295271294Sngie#endif 296271294Sngie#ifdef SF_APPEND 297271294Sngie { SF_APPEND, "SF_APPEND" }, 298271294Sngie#endif 299271294Sngie#ifdef SF_NOUNLINK 300271294Sngie { SF_NOUNLINK, "SF_NOUNLINK" }, 301271294Sngie#endif 302271294Sngie#ifdef SF_SNAPSHOT 303271294Sngie { SF_SNAPSHOT, "SF_SNAPSHOT" }, 304271294Sngie#endif 305271294Sngie { 0, NULL } 306271294Sngie}; 307271294Sngie#endif 308271294Sngie 309271294Sngiestatic struct flag unlinkat_flags[] = { 310271294Sngie { AT_REMOVEDIR, "AT_REMOVEDIR" }, 311271294Sngie { 0, NULL } 312271294Sngie}; 313271294Sngie 314271294Sngiestatic struct flag linkat_flags[] = { 315271294Sngie { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" }, 316271294Sngie { 0, NULL } 317271294Sngie}; 318271294Sngie 319271294Sngiestatic struct flag chflagsat_flags[] = { 320271294Sngie { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 321271294Sngie { 0, NULL } 322271294Sngie}; 323271294Sngie 324271294Sngiestatic struct flag fchmodat_flags[] = { 325271294Sngie { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 326271294Sngie { 0, NULL } 327271294Sngie}; 328271294Sngie 329271294Sngiestatic struct flag fchownat_flags[] = { 330271294Sngie { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 331271294Sngie { 0, NULL } 332271294Sngie}; 333271294Sngie 334271294Sngiestatic struct flag fstatat_flags[] = { 335271294Sngie { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 336271294Sngie { 0, NULL } 337271294Sngie}; 338271294Sngie 339271294Sngiestruct name { 340271294Sngie int n_name; 341271294Sngie const char *n_str; 342271294Sngie}; 343271294Sngie 344271294Sngiestatic struct name pathconf_names[] = { 345271294Sngie#ifdef _PC_LINK_MAX 346271294Sngie { _PC_LINK_MAX, "_PC_LINK_MAX" }, 347271294Sngie#endif 348271294Sngie#ifdef _PC_NAME_MAX 349271294Sngie { _PC_NAME_MAX, "_PC_NAME_MAX" }, 350271294Sngie#endif 351271294Sngie#ifdef _PC_PATH_MAX 352271294Sngie { _PC_PATH_MAX, "_PC_PATH_MAX" }, 353271294Sngie#endif 354271294Sngie#ifdef _PC_SYMLINK_MAX 355271294Sngie { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" }, 356271294Sngie#endif 357271294Sngie { 0, NULL } 358271294Sngie}; 359271294Sngie 360271294Sngiestatic const char *err2str(int error); 361271294Sngie 362271294Sngiestatic int *descriptors; 363271294Sngiestatic int ndescriptors; 364271294Sngie 365271294Sngiestatic void 366271294Sngieusage(void) 367271294Sngie{ 368271294Sngie 369271294Sngie fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n"); 370271294Sngie exit(1); 371271294Sngie} 372271294Sngie 373271294Sngiestatic long long 374271294Sngiestr2flags(struct flag *tflags, char *sflags) 375271294Sngie{ 376271294Sngie long long flags = 0; 377271294Sngie unsigned int i; 378271294Sngie char *f; 379271294Sngie 380271294Sngie /* 'none' or '0' means no flags */ 381271294Sngie if (strcmp(sflags, "none") == 0 || strcmp(sflags, "0") == 0) 382271294Sngie return (0); 383271294Sngie for (f = strtok(sflags, ",|"); f != NULL; f = strtok(NULL, ",|")) { 384271294Sngie for (i = 0; tflags[i].f_str != NULL; i++) { 385271294Sngie if (strcmp(tflags[i].f_str, f) == 0) 386271294Sngie break; 387271294Sngie } 388271294Sngie if (tflags[i].f_str == NULL) { 389271294Sngie fprintf(stderr, "unknown flag '%s'\n", f); 390271294Sngie exit(1); 391271294Sngie } 392271294Sngie flags |= tflags[i].f_flag; 393271294Sngie } 394271294Sngie return (flags); 395271294Sngie} 396271294Sngie 397271294Sngie#ifdef HAS_CHFLAGS 398271294Sngiestatic char * 399271294Sngieflags2str(struct flag *tflags, long long flags) 400271294Sngie{ 401271294Sngie static char sflags[1024]; 402271294Sngie unsigned int i; 403271294Sngie 404271294Sngie sflags[0] = '\0'; 405271294Sngie for (i = 0; tflags[i].f_str != NULL; i++) { 406271294Sngie if (flags & tflags[i].f_flag) { 407271294Sngie if (sflags[0] != '\0') 408271294Sngie strlcat(sflags, ",", sizeof(sflags)); 409271294Sngie strlcat(sflags, tflags[i].f_str, sizeof(sflags)); 410271294Sngie } 411271294Sngie } 412271294Sngie if (sflags[0] == '\0') 413271294Sngie strlcpy(sflags, "none", sizeof(sflags)); 414271294Sngie return (sflags); 415271294Sngie} 416271294Sngie#endif 417271294Sngie 418271294Sngiestatic int 419271294Sngiestr2name(struct name *names, char *name) 420271294Sngie{ 421271294Sngie unsigned int i; 422271294Sngie 423271294Sngie for (i = 0; names[i].n_str != NULL; i++) { 424271294Sngie if (strcmp(names[i].n_str, name) == 0) 425271294Sngie return (names[i].n_name); 426271294Sngie } 427271294Sngie return (-1); 428271294Sngie} 429271294Sngie 430271294Sngiestatic struct syscall_desc * 431271294Sngiefind_syscall(const char *name) 432271294Sngie{ 433271294Sngie int i; 434271294Sngie 435271294Sngie for (i = 0; syscalls[i].sd_name != NULL; i++) { 436271294Sngie if (strcmp(syscalls[i].sd_name, name) == 0) 437271294Sngie return (&syscalls[i]); 438271294Sngie } 439271294Sngie return (NULL); 440271294Sngie} 441271294Sngie 442271294Sngiestatic void 443271294Sngieshow_stat(struct stat64 *sp, const char *what) 444271294Sngie{ 445271294Sngie 446271294Sngie if (strcmp(what, "mode") == 0) 447271294Sngie printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS)); 448271294Sngie else if (strcmp(what, "inode") == 0) 449271294Sngie printf("%lld", (long long)sp->st_ino); 450271294Sngie else if (strcmp(what, "nlink") == 0) 451271294Sngie printf("%lld", (long long)sp->st_nlink); 452271294Sngie else if (strcmp(what, "uid") == 0) 453271294Sngie printf("%d", (int)sp->st_uid); 454271294Sngie else if (strcmp(what, "gid") == 0) 455271294Sngie printf("%d", (int)sp->st_gid); 456271294Sngie else if (strcmp(what, "size") == 0) 457271294Sngie printf("%lld", (long long)sp->st_size); 458271294Sngie else if (strcmp(what, "blocks") == 0) 459271294Sngie printf("%lld", (long long)sp->st_blocks); 460271294Sngie else if (strcmp(what, "atime") == 0) 461271294Sngie printf("%lld", (long long)sp->st_atime); 462271294Sngie else if (strcmp(what, "mtime") == 0) 463271294Sngie printf("%lld", (long long)sp->st_mtime); 464271294Sngie else if (strcmp(what, "ctime") == 0) 465271294Sngie printf("%lld", (long long)sp->st_ctime); 466271294Sngie#ifdef HAS_CHFLAGS 467271294Sngie else if (strcmp(what, "flags") == 0) 468271294Sngie printf("%s", flags2str(chflags_flags, (long long)sp->st_flags)); 469271294Sngie#endif 470271294Sngie else if (strcmp(what, "major") == 0) 471271294Sngie printf("%u", (unsigned int)major(sp->st_rdev)); 472271294Sngie else if (strcmp(what, "minor") == 0) 473271294Sngie printf("%u", (unsigned int)minor(sp->st_rdev)); 474271294Sngie else if (strcmp(what, "type") == 0) { 475271294Sngie switch (sp->st_mode & S_IFMT) { 476271294Sngie case S_IFIFO: 477271294Sngie printf("fifo"); 478271294Sngie break; 479271294Sngie case S_IFCHR: 480271294Sngie printf("char"); 481271294Sngie break; 482271294Sngie case S_IFDIR: 483271294Sngie printf("dir"); 484271294Sngie break; 485271294Sngie case S_IFBLK: 486271294Sngie printf("block"); 487271294Sngie break; 488271294Sngie case S_IFREG: 489271294Sngie printf("regular"); 490271294Sngie break; 491271294Sngie case S_IFLNK: 492271294Sngie printf("symlink"); 493271294Sngie break; 494271294Sngie case S_IFSOCK: 495271294Sngie printf("socket"); 496271294Sngie break; 497271294Sngie default: 498271294Sngie printf("unknown"); 499271294Sngie break; 500271294Sngie } 501271294Sngie } else { 502271294Sngie printf("unknown"); 503271294Sngie } 504271294Sngie} 505271294Sngie 506271294Sngiestatic void 507271294Sngieshow_stats(struct stat64 *sp, char *what) 508271294Sngie{ 509271294Sngie const char *s = ""; 510271294Sngie char *w; 511271294Sngie 512271294Sngie for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) { 513271294Sngie printf("%s", s); 514271294Sngie show_stat(sp, w); 515271294Sngie s = ","; 516271294Sngie } 517271294Sngie printf("\n"); 518271294Sngie} 519271294Sngie 520271294Sngiestatic void 521271294Sngiedescriptor_add(int fd) 522271294Sngie{ 523271294Sngie 524271294Sngie ndescriptors++; 525271294Sngie if (descriptors == NULL) { 526271294Sngie descriptors = malloc(sizeof(descriptors[0]) * ndescriptors); 527271294Sngie } else { 528271294Sngie descriptors = realloc(descriptors, 529271294Sngie sizeof(descriptors[0]) * ndescriptors); 530271294Sngie } 531271294Sngie assert(descriptors != NULL); 532271294Sngie descriptors[ndescriptors - 1] = fd; 533271294Sngie} 534271294Sngie 535271294Sngiestatic int 536271294Sngiedescriptor_get(int pos) 537271294Sngie{ 538271294Sngie 539271294Sngie if (pos < 0 || pos >= ndescriptors) { 540271294Sngie fprintf(stderr, "invalid descriptor %d\n", pos); 541271294Sngie exit(1); 542271294Sngie } 543271294Sngie 544271294Sngie return (descriptors[pos]); 545271294Sngie} 546271294Sngie 547271294Sngiestatic unsigned int 548271294Sngiecall_syscall(struct syscall_desc *scall, char *argv[]) 549271294Sngie{ 550271294Sngie struct stat64 sb; 551271294Sngie long long flags; 552271294Sngie unsigned int i; 553271294Sngie char *endp; 554271294Sngie int name, rval; 555271294Sngie union { 556271294Sngie char *str; 557271294Sngie long long num; 558271294Sngie } args[MAX_ARGS]; 559271294Sngie#ifdef HAS_FREEBSD_ACL 560271294Sngie int entry_id = ACL_FIRST_ENTRY; 561271294Sngie acl_t acl, newacl; 562271294Sngie acl_entry_t entry, newentry; 563271294Sngie#endif 564271294Sngie 565271294Sngie /* 566271294Sngie * Verify correctness of the arguments. 567271294Sngie */ 568271294Sngie for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) { 569271294Sngie if (scall->sd_args[i] == TYPE_NONE) { 570271294Sngie if (argv[i] == NULL || strcmp(argv[i], ":") == 0) 571271294Sngie break; 572271294Sngie fprintf(stderr, "too many arguments [%s]\n", argv[i]); 573271294Sngie exit(1); 574271294Sngie } else { 575271294Sngie if (argv[i] == NULL || strcmp(argv[i], ":") == 0) { 576271294Sngie if (scall->sd_args[i] & TYPE_OPTIONAL) 577271294Sngie break; 578271294Sngie fprintf(stderr, "too few arguments\n"); 579271294Sngie exit(1); 580271294Sngie } 581271294Sngie if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) { 582271294Sngie if (strcmp(argv[i], "NULL") == 0) 583271294Sngie args[i].str = NULL; 584271294Sngie else if (strcmp(argv[i], "DEADCODE") == 0) 585271294Sngie args[i].str = (void *)0xdeadc0de; 586271294Sngie else 587271294Sngie args[i].str = argv[i]; 588271294Sngie } else if ((scall->sd_args[i] & TYPE_MASK) == 589271294Sngie TYPE_NUMBER) { 590271294Sngie args[i].num = strtoll(argv[i], &endp, 0); 591271294Sngie if (*endp != '\0' && 592271294Sngie !isspace((unsigned char)*endp)) { 593271294Sngie fprintf(stderr, 594271294Sngie "invalid argument %u, number expected [%s]\n", 595271294Sngie i, endp); 596271294Sngie exit(1); 597271294Sngie } 598271294Sngie } else if ((scall->sd_args[i] & TYPE_MASK) == 599271294Sngie TYPE_DESCRIPTOR) { 600271294Sngie if (strcmp(argv[i], "AT_FDCWD") == 0) { 601271294Sngie args[i].num = AT_FDCWD; 602271294Sngie } else if (strcmp(argv[i], "BADFD") == 0) { 603271294Sngie /* In case AT_FDCWD is -1 on some systems... */ 604271294Sngie if (AT_FDCWD == -1) 605271294Sngie args[i].num = -2; 606271294Sngie else 607271294Sngie args[i].num = -1; 608271294Sngie } else { 609271294Sngie int pos; 610271294Sngie 611271294Sngie pos = strtoll(argv[i], &endp, 0); 612271294Sngie if (*endp != '\0' && 613271294Sngie !isspace((unsigned char)*endp)) { 614271294Sngie fprintf(stderr, 615271294Sngie "invalid argument %u, number expected [%s]\n", 616271294Sngie i, endp); 617271294Sngie exit(1); 618271294Sngie } 619271294Sngie args[i].num = descriptor_get(pos); 620271294Sngie } 621271294Sngie } 622271294Sngie } 623271294Sngie } 624271294Sngie /* 625271294Sngie * Call the given syscall. 626271294Sngie */ 627271294Sngie#define NUM(n) (args[(n)].num) 628271294Sngie#define STR(n) (args[(n)].str) 629271294Sngie switch (scall->sd_action) { 630271294Sngie case ACTION_OPEN: 631271294Sngie flags = str2flags(open_flags, STR(1)); 632271294Sngie if (flags & O_CREAT) { 633271294Sngie if (i == 2) { 634271294Sngie fprintf(stderr, "too few arguments\n"); 635271294Sngie exit(1); 636271294Sngie } 637271294Sngie rval = open(STR(0), (int)flags, (mode_t)NUM(2)); 638271294Sngie } else { 639271294Sngie if (i == 3) { 640271294Sngie fprintf(stderr, "too many arguments\n"); 641271294Sngie exit(1); 642271294Sngie } 643271294Sngie rval = open(STR(0), (int)flags); 644271294Sngie } 645271294Sngie if (rval >= 0) 646271294Sngie descriptor_add(rval); 647271294Sngie break; 648271294Sngie case ACTION_OPENAT: 649271294Sngie flags = str2flags(open_flags, STR(2)); 650271294Sngie if (flags & O_CREAT) { 651271294Sngie if (i == 3) { 652271294Sngie fprintf(stderr, "too few arguments\n"); 653271294Sngie exit(1); 654271294Sngie } 655271294Sngie rval = openat(NUM(0), STR(1), (int)flags, 656271294Sngie (mode_t)NUM(3)); 657271294Sngie } else { 658271294Sngie if (i == 4) { 659271294Sngie fprintf(stderr, "too many arguments\n"); 660271294Sngie exit(1); 661271294Sngie } 662271294Sngie rval = openat(NUM(0), STR(1), (int)flags); 663271294Sngie } 664271294Sngie if (rval >= 0) 665271294Sngie descriptor_add(rval); 666271294Sngie break; 667271294Sngie case ACTION_CREATE: 668271294Sngie rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1)); 669271294Sngie if (rval >= 0) 670271294Sngie close(rval); 671271294Sngie break; 672271294Sngie case ACTION_UNLINK: 673271294Sngie rval = unlink(STR(0)); 674271294Sngie break; 675271294Sngie case ACTION_UNLINKAT: 676271294Sngie rval = unlinkat(NUM(0), STR(1), 677271294Sngie (int)str2flags(unlinkat_flags, STR(2))); 678271294Sngie break; 679271294Sngie case ACTION_MKDIR: 680271294Sngie rval = mkdir(STR(0), (mode_t)NUM(1)); 681271294Sngie break; 682271294Sngie case ACTION_MKDIRAT: 683271294Sngie rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2)); 684271294Sngie break; 685271294Sngie case ACTION_RMDIR: 686271294Sngie rval = rmdir(STR(0)); 687271294Sngie break; 688271294Sngie case ACTION_LINK: 689271294Sngie rval = link(STR(0), STR(1)); 690271294Sngie break; 691271294Sngie case ACTION_LINKAT: 692271294Sngie rval = linkat(NUM(0), STR(1), NUM(2), STR(3), 693271294Sngie (int)str2flags(linkat_flags, STR(4))); 694271294Sngie break; 695271294Sngie case ACTION_SYMLINK: 696271294Sngie rval = symlink(STR(0), STR(1)); 697271294Sngie break; 698271294Sngie case ACTION_SYMLINKAT: 699271294Sngie rval = symlinkat(STR(0), NUM(1), STR(2)); 700271294Sngie break; 701271294Sngie case ACTION_RENAME: 702271294Sngie rval = rename(STR(0), STR(1)); 703271294Sngie break; 704271294Sngie case ACTION_RENAMEAT: 705271294Sngie rval = renameat(NUM(0), STR(1), NUM(2), STR(3)); 706271294Sngie break; 707271294Sngie case ACTION_MKFIFO: 708271294Sngie rval = mkfifo(STR(0), (mode_t)NUM(1)); 709271294Sngie break; 710271294Sngie case ACTION_MKFIFOAT: 711271294Sngie rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2)); 712271294Sngie break; 713271294Sngie case ACTION_MKNOD: 714271294Sngie case ACTION_MKNODAT: 715271294Sngie { 716271294Sngie mode_t ntype; 717271294Sngie dev_t dev; 718271294Sngie int fa; 719271294Sngie 720271294Sngie switch (scall->sd_action) { 721271294Sngie case ACTION_MKNOD: 722271294Sngie fa = 0; 723271294Sngie break; 724271294Sngie case ACTION_MKNODAT: 725271294Sngie fa = 1; 726271294Sngie break; 727271294Sngie default: 728271294Sngie abort(); 729271294Sngie } 730271294Sngie 731271294Sngie dev = makedev(NUM(fa + 3), NUM(fa + 4)); 732271294Sngie if (strcmp(STR(fa + 1), "c") == 0) /* character device */ 733271294Sngie ntype = S_IFCHR; 734271294Sngie else if (strcmp(STR(fa + 1), "b") == 0) /* block device */ 735271294Sngie ntype = S_IFBLK; 736271294Sngie else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */ 737271294Sngie ntype = S_IFIFO; 738271294Sngie else if (strcmp(STR(fa + 1), "d") == 0) /* directory */ 739271294Sngie ntype = S_IFDIR; 740271294Sngie else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */ 741271294Sngie ntype = S_IFREG; 742271294Sngie else { 743271294Sngie fprintf(stderr, "wrong argument 1\n"); 744271294Sngie exit(1); 745271294Sngie } 746271294Sngie switch (scall->sd_action) { 747271294Sngie case ACTION_MKNOD: 748271294Sngie rval = mknod(STR(0), ntype | NUM(2), dev); 749271294Sngie break; 750271294Sngie case ACTION_MKNODAT: 751271294Sngie rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev); 752271294Sngie break; 753271294Sngie default: 754271294Sngie abort(); 755271294Sngie } 756271294Sngie break; 757271294Sngie } 758271294Sngie case ACTION_BIND: 759271294Sngie { 760271294Sngie struct sockaddr_un sunx; 761271294Sngie 762271294Sngie sunx.sun_family = AF_UNIX; 763271294Sngie strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); 764271294Sngie sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 765271294Sngie rval = socket(AF_UNIX, SOCK_STREAM, 0); 766271294Sngie if (rval < 0) 767271294Sngie break; 768271294Sngie rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx)); 769271294Sngie break; 770271294Sngie } 771271294Sngie#ifdef HAS_BINDAT 772271294Sngie case ACTION_BINDAT: 773271294Sngie { 774271294Sngie struct sockaddr_un sunx; 775271294Sngie 776271294Sngie sunx.sun_family = AF_UNIX; 777271294Sngie strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); 778271294Sngie sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 779271294Sngie rval = socket(AF_UNIX, SOCK_STREAM, 0); 780271294Sngie if (rval < 0) 781271294Sngie break; 782271294Sngie rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx, 783271294Sngie sizeof(sunx)); 784271294Sngie break; 785271294Sngie } 786271294Sngie#endif 787271294Sngie case ACTION_CONNECT: 788271294Sngie { 789271294Sngie struct sockaddr_un sunx; 790271294Sngie 791271294Sngie sunx.sun_family = AF_UNIX; 792271294Sngie strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); 793271294Sngie sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 794271294Sngie rval = socket(AF_UNIX, SOCK_STREAM, 0); 795271294Sngie if (rval < 0) 796271294Sngie break; 797271294Sngie rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx)); 798271294Sngie break; 799271294Sngie } 800271294Sngie#ifdef HAS_CONNECTAT 801271294Sngie case ACTION_CONNECTAT: 802271294Sngie { 803271294Sngie struct sockaddr_un sunx; 804271294Sngie 805271294Sngie sunx.sun_family = AF_UNIX; 806271294Sngie strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); 807271294Sngie sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 808271294Sngie rval = socket(AF_UNIX, SOCK_STREAM, 0); 809271294Sngie if (rval < 0) 810271294Sngie break; 811271294Sngie rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx, 812271294Sngie sizeof(sunx)); 813271294Sngie break; 814271294Sngie } 815271294Sngie#endif 816271294Sngie case ACTION_CHMOD: 817271294Sngie rval = chmod(STR(0), (mode_t)NUM(1)); 818271294Sngie break; 819271294Sngie case ACTION_FCHMOD: 820271294Sngie rval = fchmod(NUM(0), (mode_t)NUM(1)); 821271294Sngie break; 822271294Sngie#ifdef HAS_LCHMOD 823271294Sngie case ACTION_LCHMOD: 824271294Sngie rval = lchmod(STR(0), (mode_t)NUM(1)); 825271294Sngie break; 826271294Sngie#endif 827271294Sngie case ACTION_FCHMODAT: 828271294Sngie rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2), 829271294Sngie str2flags(fchmodat_flags, STR(3))); 830271294Sngie break; 831271294Sngie case ACTION_CHOWN: 832271294Sngie rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); 833271294Sngie break; 834271294Sngie case ACTION_FCHOWN: 835271294Sngie rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2)); 836271294Sngie break; 837271294Sngie case ACTION_LCHOWN: 838271294Sngie rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); 839271294Sngie break; 840271294Sngie case ACTION_FCHOWNAT: 841271294Sngie rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3), 842271294Sngie (int)str2flags(fchownat_flags, STR(4))); 843271294Sngie break; 844271294Sngie#ifdef HAS_CHFLAGS 845271294Sngie case ACTION_CHFLAGS: 846271294Sngie rval = chflags(STR(0), 847271294Sngie (unsigned long)str2flags(chflags_flags, STR(1))); 848271294Sngie break; 849271294Sngie#endif 850271294Sngie#ifdef HAS_FCHFLAGS 851271294Sngie case ACTION_FCHFLAGS: 852271294Sngie rval = fchflags(NUM(0), 853271294Sngie (unsigned long)str2flags(chflags_flags, STR(1))); 854271294Sngie break; 855271294Sngie#endif 856271294Sngie#ifdef HAS_CHFLAGSAT 857271294Sngie case ACTION_CHFLAGSAT: 858271294Sngie rval = chflagsat(NUM(0), STR(1), 859271294Sngie (unsigned long)str2flags(chflags_flags, STR(2)), 860271294Sngie (int)str2flags(chflagsat_flags, STR(3))); 861271294Sngie break; 862271294Sngie#endif 863271294Sngie#ifdef HAS_LCHFLAGS 864271294Sngie case ACTION_LCHFLAGS: 865271294Sngie rval = lchflags(STR(0), 866271294Sngie (unsigned long)str2flags(chflags_flags, STR(1))); 867271294Sngie break; 868271294Sngie#endif 869271294Sngie case ACTION_TRUNCATE: 870271294Sngie rval = truncate64(STR(0), NUM(1)); 871271294Sngie break; 872271294Sngie case ACTION_FTRUNCATE: 873271294Sngie rval = ftruncate64(NUM(0), NUM(1)); 874271294Sngie break; 875271294Sngie case ACTION_STAT: 876271294Sngie rval = stat64(STR(0), &sb); 877271294Sngie if (rval == 0) { 878271294Sngie show_stats(&sb, STR(1)); 879271294Sngie return (i); 880271294Sngie } 881271294Sngie break; 882271294Sngie case ACTION_FSTAT: 883271294Sngie rval = fstat64(NUM(0), &sb); 884271294Sngie if (rval == 0) { 885271294Sngie show_stats(&sb, STR(1)); 886271294Sngie return (i); 887271294Sngie } 888271294Sngie break; 889271294Sngie case ACTION_LSTAT: 890271294Sngie rval = lstat64(STR(0), &sb); 891271294Sngie if (rval == 0) { 892271294Sngie show_stats(&sb, STR(1)); 893271294Sngie return (i); 894271294Sngie } 895271294Sngie break; 896271294Sngie case ACTION_FSTATAT: 897271294Sngie rval = fstatat(NUM(0), STR(1), &sb, 898271294Sngie (int)str2flags(fstatat_flags, STR(2))); 899271294Sngie if (rval == 0) { 900271294Sngie show_stats(&sb, STR(3)); 901271294Sngie return (i); 902271294Sngie } 903271294Sngie break; 904271294Sngie case ACTION_PATHCONF: 905271294Sngie case ACTION_FPATHCONF: 906271294Sngie#ifdef HAS_LPATHCONF 907271294Sngie case ACTION_LPATHCONF: 908271294Sngie#endif 909271294Sngie { 910271294Sngie long lrval; 911271294Sngie 912271294Sngie name = str2name(pathconf_names, STR(1)); 913271294Sngie if (name == -1) { 914271294Sngie fprintf(stderr, "unknown name %s", STR(1)); 915271294Sngie exit(1); 916271294Sngie } 917271294Sngie errno = 0; 918271294Sngie switch (scall->sd_action) { 919271294Sngie case ACTION_PATHCONF: 920271294Sngie lrval = pathconf(STR(0), name); 921271294Sngie break; 922271294Sngie case ACTION_FPATHCONF: 923271294Sngie lrval = fpathconf(NUM(0), name); 924271294Sngie break; 925271294Sngie#ifdef HAS_LPATHCONF 926271294Sngie case ACTION_LPATHCONF: 927271294Sngie lrval = lpathconf(STR(0), name); 928271294Sngie break; 929271294Sngie#endif 930271294Sngie default: 931271294Sngie abort(); 932271294Sngie } 933271294Sngie if (lrval == -1 && errno == 0) { 934271294Sngie printf("unlimited\n"); 935271294Sngie return (i); 936271294Sngie } else if (lrval >= 0) { 937271294Sngie printf("%ld\n", lrval); 938271294Sngie return (i); 939271294Sngie } 940271294Sngie rval = -1; 941271294Sngie break; 942271294Sngie } 943271294Sngie#ifdef HAS_FREEBSD_ACL 944271294Sngie case ACTION_PREPENDACL: 945271294Sngie rval = -1; 946271294Sngie 947271294Sngie acl = acl_get_file(STR(0), ACL_TYPE_NFS4); 948271294Sngie if (acl == NULL) 949271294Sngie break; 950271294Sngie 951271294Sngie newacl = acl_from_text(STR(1)); 952271294Sngie if (acl == NULL) 953271294Sngie break; 954271294Sngie 955271294Sngie while (acl_get_entry(newacl, entry_id, &newentry) == 1) { 956271294Sngie entry_id = ACL_NEXT_ENTRY; 957271294Sngie 958271294Sngie if (acl_create_entry_np(&acl, &entry, 0)) 959271294Sngie break; 960271294Sngie 961271294Sngie if (acl_copy_entry(entry, newentry)) 962271294Sngie break; 963271294Sngie } 964271294Sngie 965271294Sngie rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl); 966271294Sngie break; 967271294Sngie case ACTION_READACL: 968271294Sngie acl = acl_get_file(STR(0), ACL_TYPE_NFS4); 969271294Sngie if (acl == NULL) 970271294Sngie rval = -1; 971271294Sngie else 972271294Sngie rval = 0; 973271294Sngie break; 974271294Sngie#endif 975271294Sngie case ACTION_WRITE: 976271294Sngie rval = write(NUM(0), STR(1), strlen(STR(1))); 977271294Sngie break; 978271294Sngie default: 979271294Sngie fprintf(stderr, "unsupported syscall\n"); 980271294Sngie exit(1); 981271294Sngie } 982271294Sngie#undef STR 983271294Sngie#undef NUM 984271294Sngie if (rval < 0) { 985271294Sngie const char *serrno; 986271294Sngie 987271294Sngie serrno = err2str(errno); 988271294Sngie fprintf(stderr, "%s returned %d\n", scall->sd_name, rval); 989271294Sngie printf("%s\n", serrno); 990271294Sngie exit(1); 991271294Sngie } 992271294Sngie printf("0\n"); 993271294Sngie return (i); 994271294Sngie} 995271294Sngie 996271294Sngiestatic void 997271294Sngieset_gids(char *gids) 998271294Sngie{ 999271294Sngie gid_t *gidset; 1000271294Sngie long ngroups; 1001271294Sngie char *g, *endp; 1002271294Sngie unsigned i; 1003271294Sngie 1004271294Sngie ngroups = sysconf(_SC_NGROUPS_MAX); 1005271294Sngie assert(ngroups > 0); 1006271294Sngie gidset = malloc(sizeof(*gidset) * ngroups); 1007271294Sngie assert(gidset != NULL); 1008271294Sngie for (i = 0, g = strtok(gids, ","); g != NULL; 1009271294Sngie g = strtok(NULL, ","), i++) { 1010271294Sngie if (i >= ngroups) { 1011271294Sngie fprintf(stderr, "too many gids\n"); 1012271294Sngie exit(1); 1013271294Sngie } 1014271294Sngie gidset[i] = strtol(g, &endp, 0); 1015271294Sngie if (*endp != '\0' && !isspace((unsigned char)*endp)) { 1016271294Sngie fprintf(stderr, "invalid gid '%s' - number expected\n", 1017271294Sngie g); 1018271294Sngie exit(1); 1019271294Sngie } 1020271294Sngie } 1021271294Sngie if (setgroups(i, gidset) < 0) { 1022271294Sngie fprintf(stderr, "cannot change groups: %s\n", strerror(errno)); 1023271294Sngie exit(1); 1024271294Sngie } 1025271294Sngie if (setegid(gidset[0]) < 0) { 1026271294Sngie fprintf(stderr, "cannot change effective gid: %s\n", 1027271294Sngie strerror(errno)); 1028271294Sngie exit(1); 1029271294Sngie } 1030271294Sngie free(gidset); 1031271294Sngie} 1032271294Sngie 1033271294Sngieint 1034271294Sngiemain(int argc, char *argv[]) 1035271294Sngie{ 1036271294Sngie struct syscall_desc *scall; 1037271294Sngie unsigned int n; 1038271294Sngie char *gids, *endp; 1039271294Sngie int uid, umsk, ch; 1040271294Sngie 1041271294Sngie uid = -1; 1042271294Sngie gids = NULL; 1043271294Sngie umsk = 0; 1044271294Sngie 1045271294Sngie while ((ch = getopt(argc, argv, "g:u:U:")) != -1) { 1046271294Sngie switch(ch) { 1047271294Sngie case 'g': 1048271294Sngie gids = optarg; 1049271294Sngie break; 1050271294Sngie case 'u': 1051271294Sngie uid = (int)strtol(optarg, &endp, 0); 1052271294Sngie if (*endp != '\0' && !isspace((unsigned char)*endp)) { 1053271294Sngie fprintf(stderr, "invalid uid '%s' - number " 1054271294Sngie "expected\n", optarg); 1055271294Sngie exit(1); 1056271294Sngie } 1057271294Sngie break; 1058271294Sngie case 'U': 1059271294Sngie umsk = (int)strtol(optarg, &endp, 0); 1060271294Sngie if (*endp != '\0' && !isspace((unsigned char)*endp)) { 1061271294Sngie fprintf(stderr, "invalid umask '%s' - number " 1062271294Sngie "expected\n", optarg); 1063271294Sngie exit(1); 1064271294Sngie } 1065271294Sngie break; 1066271294Sngie default: 1067271294Sngie usage(); 1068271294Sngie } 1069271294Sngie } 1070271294Sngie argc -= optind; 1071271294Sngie argv += optind; 1072271294Sngie 1073271294Sngie if (argc < 1) { 1074271294Sngie fprintf(stderr, "too few arguments\n"); 1075271294Sngie usage(); 1076271294Sngie } 1077271294Sngie 1078271294Sngie if (gids != NULL) { 1079271294Sngie fprintf(stderr, "changing groups to %s\n", gids); 1080271294Sngie set_gids(gids); 1081271294Sngie } 1082271294Sngie if (uid != -1) { 1083271294Sngie fprintf(stderr, "changing uid to %d\n", uid); 1084271294Sngie if (setuid(uid) < 0) { 1085271294Sngie fprintf(stderr, "cannot change uid: %s\n", 1086271294Sngie strerror(errno)); 1087271294Sngie exit(1); 1088271294Sngie } 1089271294Sngie } 1090271294Sngie 1091271294Sngie /* Change umask to requested value or to 0, if not requested. */ 1092271294Sngie umask(umsk); 1093271294Sngie 1094271294Sngie for (;;) { 1095271294Sngie scall = find_syscall(argv[0]); 1096271294Sngie if (scall == NULL) { 1097271294Sngie fprintf(stderr, "syscall '%s' not supported\n", 1098271294Sngie argv[0]); 1099271294Sngie exit(1); 1100271294Sngie } 1101271294Sngie argc++; 1102271294Sngie argv++; 1103271294Sngie n = call_syscall(scall, argv); 1104271294Sngie argc += n; 1105271294Sngie argv += n; 1106271294Sngie if (argv[0] == NULL) 1107271294Sngie break; 1108271294Sngie argc++; 1109271294Sngie argv++; 1110271294Sngie } 1111271294Sngie 1112271294Sngie exit(0); 1113271294Sngie} 1114271294Sngie 1115271294Sngiestatic const char * 1116271294Sngieerr2str(int error) 1117271294Sngie{ 1118271294Sngie static char errnum[8]; 1119271294Sngie 1120271294Sngie switch (error) { 1121271294Sngie#ifdef EPERM 1122271294Sngie case EPERM: 1123271294Sngie return ("EPERM"); 1124271294Sngie#endif 1125271294Sngie#ifdef ENOENT 1126271294Sngie case ENOENT: 1127271294Sngie return ("ENOENT"); 1128271294Sngie#endif 1129271294Sngie#ifdef ESRCH 1130271294Sngie case ESRCH: 1131271294Sngie return ("ESRCH"); 1132271294Sngie#endif 1133271294Sngie#ifdef EINTR 1134271294Sngie case EINTR: 1135271294Sngie return ("EINTR"); 1136271294Sngie#endif 1137271294Sngie#ifdef EIO 1138271294Sngie case EIO: 1139271294Sngie return ("EIO"); 1140271294Sngie#endif 1141271294Sngie#ifdef ENXIO 1142271294Sngie case ENXIO: 1143271294Sngie return ("ENXIO"); 1144271294Sngie#endif 1145271294Sngie#ifdef E2BIG 1146271294Sngie case E2BIG: 1147271294Sngie return ("E2BIG"); 1148271294Sngie#endif 1149271294Sngie#ifdef ENOEXEC 1150271294Sngie case ENOEXEC: 1151271294Sngie return ("ENOEXEC"); 1152271294Sngie#endif 1153271294Sngie#ifdef EBADF 1154271294Sngie case EBADF: 1155271294Sngie return ("EBADF"); 1156271294Sngie#endif 1157271294Sngie#ifdef ECHILD 1158271294Sngie case ECHILD: 1159271294Sngie return ("ECHILD"); 1160271294Sngie#endif 1161271294Sngie#ifdef EDEADLK 1162271294Sngie case EDEADLK: 1163271294Sngie return ("EDEADLK"); 1164271294Sngie#endif 1165271294Sngie#ifdef ENOMEM 1166271294Sngie case ENOMEM: 1167271294Sngie return ("ENOMEM"); 1168271294Sngie#endif 1169271294Sngie#ifdef EACCES 1170271294Sngie case EACCES: 1171271294Sngie return ("EACCES"); 1172271294Sngie#endif 1173271294Sngie#ifdef EFAULT 1174271294Sngie case EFAULT: 1175271294Sngie return ("EFAULT"); 1176271294Sngie#endif 1177271294Sngie#ifdef ENOTBLK 1178271294Sngie case ENOTBLK: 1179271294Sngie return ("ENOTBLK"); 1180271294Sngie#endif 1181271294Sngie#ifdef EBUSY 1182271294Sngie case EBUSY: 1183271294Sngie return ("EBUSY"); 1184271294Sngie#endif 1185271294Sngie#ifdef EEXIST 1186271294Sngie case EEXIST: 1187271294Sngie return ("EEXIST"); 1188271294Sngie#endif 1189271294Sngie#ifdef EXDEV 1190271294Sngie case EXDEV: 1191271294Sngie return ("EXDEV"); 1192271294Sngie#endif 1193271294Sngie#ifdef ENODEV 1194271294Sngie case ENODEV: 1195271294Sngie return ("ENODEV"); 1196271294Sngie#endif 1197271294Sngie#ifdef ENOTDIR 1198271294Sngie case ENOTDIR: 1199271294Sngie return ("ENOTDIR"); 1200271294Sngie#endif 1201271294Sngie#ifdef EISDIR 1202271294Sngie case EISDIR: 1203271294Sngie return ("EISDIR"); 1204271294Sngie#endif 1205271294Sngie#ifdef EINVAL 1206271294Sngie case EINVAL: 1207271294Sngie return ("EINVAL"); 1208271294Sngie#endif 1209271294Sngie#ifdef ENFILE 1210271294Sngie case ENFILE: 1211271294Sngie return ("ENFILE"); 1212271294Sngie#endif 1213271294Sngie#ifdef EMFILE 1214271294Sngie case EMFILE: 1215271294Sngie return ("EMFILE"); 1216271294Sngie#endif 1217271294Sngie#ifdef ENOTTY 1218271294Sngie case ENOTTY: 1219271294Sngie return ("ENOTTY"); 1220271294Sngie#endif 1221271294Sngie#ifdef ETXTBSY 1222271294Sngie case ETXTBSY: 1223271294Sngie return ("ETXTBSY"); 1224271294Sngie#endif 1225271294Sngie#ifdef EFBIG 1226271294Sngie case EFBIG: 1227271294Sngie return ("EFBIG"); 1228271294Sngie#endif 1229271294Sngie#ifdef ENOSPC 1230271294Sngie case ENOSPC: 1231271294Sngie return ("ENOSPC"); 1232271294Sngie#endif 1233271294Sngie#ifdef ESPIPE 1234271294Sngie case ESPIPE: 1235271294Sngie return ("ESPIPE"); 1236271294Sngie#endif 1237271294Sngie#ifdef EROFS 1238271294Sngie case EROFS: 1239271294Sngie return ("EROFS"); 1240271294Sngie#endif 1241271294Sngie#ifdef EMLINK 1242271294Sngie case EMLINK: 1243271294Sngie return ("EMLINK"); 1244271294Sngie#endif 1245271294Sngie#ifdef EPIPE 1246271294Sngie case EPIPE: 1247271294Sngie return ("EPIPE"); 1248271294Sngie#endif 1249271294Sngie#ifdef EDOM 1250271294Sngie case EDOM: 1251271294Sngie return ("EDOM"); 1252271294Sngie#endif 1253271294Sngie#ifdef ERANGE 1254271294Sngie case ERANGE: 1255271294Sngie return ("ERANGE"); 1256271294Sngie#endif 1257271294Sngie#ifdef EAGAIN 1258271294Sngie case EAGAIN: 1259271294Sngie return ("EAGAIN"); 1260271294Sngie#endif 1261271294Sngie#ifdef EINPROGRESS 1262271294Sngie case EINPROGRESS: 1263271294Sngie return ("EINPROGRESS"); 1264271294Sngie#endif 1265271294Sngie#ifdef EALREADY 1266271294Sngie case EALREADY: 1267271294Sngie return ("EALREADY"); 1268271294Sngie#endif 1269271294Sngie#ifdef ENOTSOCK 1270271294Sngie case ENOTSOCK: 1271271294Sngie return ("ENOTSOCK"); 1272271294Sngie#endif 1273271294Sngie#ifdef EDESTADDRREQ 1274271294Sngie case EDESTADDRREQ: 1275271294Sngie return ("EDESTADDRREQ"); 1276271294Sngie#endif 1277271294Sngie#ifdef EMSGSIZE 1278271294Sngie case EMSGSIZE: 1279271294Sngie return ("EMSGSIZE"); 1280271294Sngie#endif 1281271294Sngie#ifdef EPROTOTYPE 1282271294Sngie case EPROTOTYPE: 1283271294Sngie return ("EPROTOTYPE"); 1284271294Sngie#endif 1285271294Sngie#ifdef ENOPROTOOPT 1286271294Sngie case ENOPROTOOPT: 1287271294Sngie return ("ENOPROTOOPT"); 1288271294Sngie#endif 1289271294Sngie#ifdef EPROTONOSUPPORT 1290271294Sngie case EPROTONOSUPPORT: 1291271294Sngie return ("EPROTONOSUPPORT"); 1292271294Sngie#endif 1293271294Sngie#ifdef ESOCKTNOSUPPORT 1294271294Sngie case ESOCKTNOSUPPORT: 1295271294Sngie return ("ESOCKTNOSUPPORT"); 1296271294Sngie#endif 1297271294Sngie#ifdef EOPNOTSUPP 1298271294Sngie case EOPNOTSUPP: 1299271294Sngie return ("EOPNOTSUPP"); 1300271294Sngie#endif 1301271294Sngie#ifdef EPFNOSUPPORT 1302271294Sngie case EPFNOSUPPORT: 1303271294Sngie return ("EPFNOSUPPORT"); 1304271294Sngie#endif 1305271294Sngie#ifdef EAFNOSUPPORT 1306271294Sngie case EAFNOSUPPORT: 1307271294Sngie return ("EAFNOSUPPORT"); 1308271294Sngie#endif 1309271294Sngie#ifdef EADDRINUSE 1310271294Sngie case EADDRINUSE: 1311271294Sngie return ("EADDRINUSE"); 1312271294Sngie#endif 1313271294Sngie#ifdef EADDRNOTAVAIL 1314271294Sngie case EADDRNOTAVAIL: 1315271294Sngie return ("EADDRNOTAVAIL"); 1316271294Sngie#endif 1317271294Sngie#ifdef ENETDOWN 1318271294Sngie case ENETDOWN: 1319271294Sngie return ("ENETDOWN"); 1320271294Sngie#endif 1321271294Sngie#ifdef ENETUNREACH 1322271294Sngie case ENETUNREACH: 1323271294Sngie return ("ENETUNREACH"); 1324271294Sngie#endif 1325271294Sngie#ifdef ENETRESET 1326271294Sngie case ENETRESET: 1327271294Sngie return ("ENETRESET"); 1328271294Sngie#endif 1329271294Sngie#ifdef ECONNABORTED 1330271294Sngie case ECONNABORTED: 1331271294Sngie return ("ECONNABORTED"); 1332271294Sngie#endif 1333271294Sngie#ifdef ECONNRESET 1334271294Sngie case ECONNRESET: 1335271294Sngie return ("ECONNRESET"); 1336271294Sngie#endif 1337271294Sngie#ifdef ENOBUFS 1338271294Sngie case ENOBUFS: 1339271294Sngie return ("ENOBUFS"); 1340271294Sngie#endif 1341271294Sngie#ifdef EISCONN 1342271294Sngie case EISCONN: 1343271294Sngie return ("EISCONN"); 1344271294Sngie#endif 1345271294Sngie#ifdef ENOTCONN 1346271294Sngie case ENOTCONN: 1347271294Sngie return ("ENOTCONN"); 1348271294Sngie#endif 1349271294Sngie#ifdef ESHUTDOWN 1350271294Sngie case ESHUTDOWN: 1351271294Sngie return ("ESHUTDOWN"); 1352271294Sngie#endif 1353271294Sngie#ifdef ETOOMANYREFS 1354271294Sngie case ETOOMANYREFS: 1355271294Sngie return ("ETOOMANYREFS"); 1356271294Sngie#endif 1357271294Sngie#ifdef ETIMEDOUT 1358271294Sngie case ETIMEDOUT: 1359271294Sngie return ("ETIMEDOUT"); 1360271294Sngie#endif 1361271294Sngie#ifdef ECONNREFUSED 1362271294Sngie case ECONNREFUSED: 1363271294Sngie return ("ECONNREFUSED"); 1364271294Sngie#endif 1365271294Sngie#ifdef ELOOP 1366271294Sngie case ELOOP: 1367271294Sngie return ("ELOOP"); 1368271294Sngie#endif 1369271294Sngie#ifdef ENAMETOOLONG 1370271294Sngie case ENAMETOOLONG: 1371271294Sngie return ("ENAMETOOLONG"); 1372271294Sngie#endif 1373271294Sngie#ifdef EHOSTDOWN 1374271294Sngie case EHOSTDOWN: 1375271294Sngie return ("EHOSTDOWN"); 1376271294Sngie#endif 1377271294Sngie#ifdef EHOSTUNREACH 1378271294Sngie case EHOSTUNREACH: 1379271294Sngie return ("EHOSTUNREACH"); 1380271294Sngie#endif 1381271294Sngie#ifdef ENOTEMPTY 1382271294Sngie case ENOTEMPTY: 1383271294Sngie return ("ENOTEMPTY"); 1384271294Sngie#endif 1385271294Sngie#ifdef EPROCLIM 1386271294Sngie case EPROCLIM: 1387271294Sngie return ("EPROCLIM"); 1388271294Sngie#endif 1389271294Sngie#ifdef EUSERS 1390271294Sngie case EUSERS: 1391271294Sngie return ("EUSERS"); 1392271294Sngie#endif 1393271294Sngie#ifdef EDQUOT 1394271294Sngie case EDQUOT: 1395271294Sngie return ("EDQUOT"); 1396271294Sngie#endif 1397271294Sngie#ifdef ESTALE 1398271294Sngie case ESTALE: 1399271294Sngie return ("ESTALE"); 1400271294Sngie#endif 1401271294Sngie#ifdef EREMOTE 1402271294Sngie case EREMOTE: 1403271294Sngie return ("EREMOTE"); 1404271294Sngie#endif 1405271294Sngie#ifdef EBADRPC 1406271294Sngie case EBADRPC: 1407271294Sngie return ("EBADRPC"); 1408271294Sngie#endif 1409271294Sngie#ifdef ERPCMISMATCH 1410271294Sngie case ERPCMISMATCH: 1411271294Sngie return ("ERPCMISMATCH"); 1412271294Sngie#endif 1413271294Sngie#ifdef EPROGUNAVAIL 1414271294Sngie case EPROGUNAVAIL: 1415271294Sngie return ("EPROGUNAVAIL"); 1416271294Sngie#endif 1417271294Sngie#ifdef EPROGMISMATCH 1418271294Sngie case EPROGMISMATCH: 1419271294Sngie return ("EPROGMISMATCH"); 1420271294Sngie#endif 1421271294Sngie#ifdef EPROCUNAVAIL 1422271294Sngie case EPROCUNAVAIL: 1423271294Sngie return ("EPROCUNAVAIL"); 1424271294Sngie#endif 1425271294Sngie#ifdef ENOLCK 1426271294Sngie case ENOLCK: 1427271294Sngie return ("ENOLCK"); 1428271294Sngie#endif 1429271294Sngie#ifdef ENOSYS 1430271294Sngie case ENOSYS: 1431271294Sngie return ("ENOSYS"); 1432271294Sngie#endif 1433271294Sngie#ifdef EFTYPE 1434271294Sngie case EFTYPE: 1435271294Sngie return ("EFTYPE"); 1436271294Sngie#endif 1437271294Sngie#ifdef EAUTH 1438271294Sngie case EAUTH: 1439271294Sngie return ("EAUTH"); 1440271294Sngie#endif 1441271294Sngie#ifdef ENEEDAUTH 1442271294Sngie case ENEEDAUTH: 1443271294Sngie return ("ENEEDAUTH"); 1444271294Sngie#endif 1445271294Sngie#ifdef EIDRM 1446271294Sngie case EIDRM: 1447271294Sngie return ("EIDRM"); 1448271294Sngie#endif 1449271294Sngie#ifdef ENOMSG 1450271294Sngie case ENOMSG: 1451271294Sngie return ("ENOMSG"); 1452271294Sngie#endif 1453271294Sngie#ifdef EOVERFLOW 1454271294Sngie case EOVERFLOW: 1455271294Sngie return ("EOVERFLOW"); 1456271294Sngie#endif 1457271294Sngie#ifdef ECANCELED 1458271294Sngie case ECANCELED: 1459271294Sngie return ("ECANCELED"); 1460271294Sngie#endif 1461271294Sngie#ifdef EILSEQ 1462271294Sngie case EILSEQ: 1463271294Sngie return ("EILSEQ"); 1464271294Sngie#endif 1465271294Sngie#ifdef ENOATTR 1466271294Sngie case ENOATTR: 1467271294Sngie return ("ENOATTR"); 1468271294Sngie#endif 1469271294Sngie#ifdef EDOOFUS 1470271294Sngie case EDOOFUS: 1471271294Sngie return ("EDOOFUS"); 1472271294Sngie#endif 1473271294Sngie#ifdef EBADMSG 1474271294Sngie case EBADMSG: 1475271294Sngie return ("EBADMSG"); 1476271294Sngie#endif 1477271294Sngie#ifdef EMULTIHOP 1478271294Sngie case EMULTIHOP: 1479271294Sngie return ("EMULTIHOP"); 1480271294Sngie#endif 1481271294Sngie#ifdef ENOLINK 1482271294Sngie case ENOLINK: 1483271294Sngie return ("ENOLINK"); 1484271294Sngie#endif 1485271294Sngie#ifdef EPROTO 1486271294Sngie case EPROTO: 1487271294Sngie return ("EPROTO"); 1488271294Sngie#endif 1489271294Sngie default: 1490271294Sngie snprintf(errnum, sizeof(errnum), "%d", error); 1491271294Sngie return (errnum); 1492271294Sngie } 1493271294Sngie} 1494