1166065Spjd/*- 2211351Spjd * Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3166065Spjd * All rights reserved. 4166065Spjd * 5166065Spjd * Redistribution and use in source and binary forms, with or without 6166065Spjd * modification, are permitted provided that the following conditions 7166065Spjd * are met: 8166065Spjd * 1. Redistributions of source code must retain the above copyright 9166065Spjd * notice, this list of conditions and the following disclaimer. 10166065Spjd * 2. Redistributions in binary form must reproduce the above copyright 11166065Spjd * notice, this list of conditions and the following disclaimer in the 12166065Spjd * documentation and/or other materials provided with the distribution. 13166065Spjd * 14166065Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15166065Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16166065Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17166065Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18166065Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19166065Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20166065Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21166065Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22166065Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23166065Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24166065Spjd * SUCH DAMAGE. 25166065Spjd * 26166065Spjd * $FreeBSD$ 27166065Spjd */ 28166065Spjd 29166065Spjd#include <sys/param.h> 30210965Spjd#include <sys/types.h> 31166065Spjd#include <sys/stat.h> 32210951Spjd#include <sys/socket.h> 33210951Spjd#include <sys/un.h> 34210965Spjd#ifndef makedev 35210965Spjd#include <sys/mkdev.h> 36210965Spjd#endif 37210964Spjd 38210964Spjd#include <assert.h> 39210964Spjd#include <ctype.h> 40210964Spjd#include <errno.h> 41210964Spjd#include <fcntl.h> 42210964Spjd#include <grp.h> 43166065Spjd#include <stdio.h> 44166065Spjd#include <stdlib.h> 45210964Spjd#include <string.h> 46166065Spjd#include <unistd.h> 47166065Spjd 48166065Spjd#ifndef HAS_TRUNCATE64 49166065Spjd#define truncate64 truncate 50219437Spjd#define ftruncate64 ftruncate 51166065Spjd#endif 52166065Spjd#ifndef HAS_STAT64 53166065Spjd#define stat64 stat 54219437Spjd#define fstat64 fstat 55166065Spjd#define lstat64 lstat 56166065Spjd#endif 57196948Strasz#ifdef HAS_FREEBSD_ACL 58196948Strasz#include <sys/acl.h> 59196948Strasz#endif 60166065Spjd 61166065Spjd#ifndef ALLPERMS 62166065Spjd#define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) 63166065Spjd#endif 64166065Spjd 65166065Spjdenum action { 66166065Spjd ACTION_OPEN, 67219464Spjd ACTION_OPENAT, 68166065Spjd ACTION_CREATE, 69166065Spjd ACTION_UNLINK, 70219464Spjd ACTION_UNLINKAT, 71166065Spjd ACTION_MKDIR, 72219464Spjd ACTION_MKDIRAT, 73166065Spjd ACTION_RMDIR, 74166065Spjd ACTION_LINK, 75219464Spjd ACTION_LINKAT, 76166065Spjd ACTION_SYMLINK, 77219464Spjd ACTION_SYMLINKAT, 78166065Spjd ACTION_RENAME, 79219464Spjd ACTION_RENAMEAT, 80166065Spjd ACTION_MKFIFO, 81219464Spjd ACTION_MKFIFOAT, 82210965Spjd ACTION_MKNOD, 83219464Spjd ACTION_MKNODAT, 84210951Spjd ACTION_BIND, 85247669Spjd#ifdef HAS_BINDAT 86247669Spjd ACTION_BINDAT, 87247669Spjd#endif 88210951Spjd ACTION_CONNECT, 89247669Spjd#ifdef HAS_CONNECTAT 90247669Spjd ACTION_CONNECTAT, 91247669Spjd#endif 92166065Spjd ACTION_CHMOD, 93219437Spjd ACTION_FCHMOD, 94166065Spjd#ifdef HAS_LCHMOD 95166065Spjd ACTION_LCHMOD, 96166065Spjd#endif 97219464Spjd ACTION_FCHMODAT, 98166065Spjd ACTION_CHOWN, 99219437Spjd ACTION_FCHOWN, 100166065Spjd ACTION_LCHOWN, 101219464Spjd ACTION_FCHOWNAT, 102166065Spjd#ifdef HAS_CHFLAGS 103166065Spjd ACTION_CHFLAGS, 104166065Spjd#endif 105219437Spjd#ifdef HAS_FCHFLAGS 106219437Spjd ACTION_FCHFLAGS, 107219437Spjd#endif 108248603Spjd#ifdef HAS_CHFLAGSAT 109248603Spjd ACTION_CHFLAGSAT, 110248603Spjd#endif 111166065Spjd#ifdef HAS_LCHFLAGS 112166065Spjd ACTION_LCHFLAGS, 113166065Spjd#endif 114166065Spjd ACTION_TRUNCATE, 115219437Spjd ACTION_FTRUNCATE, 116166065Spjd ACTION_STAT, 117219437Spjd ACTION_FSTAT, 118166065Spjd ACTION_LSTAT, 119219464Spjd ACTION_FSTATAT, 120196948Strasz ACTION_PATHCONF, 121219437Spjd ACTION_FPATHCONF, 122219437Spjd ACTION_LPATHCONF, 123196948Strasz#ifdef HAS_FREEBSD_ACL 124196948Strasz ACTION_PREPENDACL, 125196948Strasz ACTION_READACL, 126196948Strasz#endif 127196948Strasz ACTION_WRITE, 128166065Spjd}; 129166065Spjd 130166065Spjd#define TYPE_NONE 0x0000 131166065Spjd#define TYPE_STRING 0x0001 132166065Spjd#define TYPE_NUMBER 0x0002 133219464Spjd#define TYPE_DESCRIPTOR 0x0003 134219464Spjd#define TYPE_MASK 0x000f 135166065Spjd 136166065Spjd#define TYPE_OPTIONAL 0x0100 137166065Spjd 138166065Spjd#define MAX_ARGS 8 139166065Spjd 140166065Spjdstruct syscall_desc { 141219566Spjd const char *sd_name; 142166065Spjd enum action sd_action; 143166065Spjd int sd_args[MAX_ARGS]; 144166065Spjd}; 145166065Spjd 146166065Spjdstatic struct syscall_desc syscalls[] = { 147166065Spjd { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } }, 148219464Spjd { "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } }, 149166065Spjd { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 150166065Spjd { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } }, 151219464Spjd { "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 152166065Spjd { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 153219464Spjd { "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 154166065Spjd { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } }, 155166065Spjd { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 156219464Spjd { "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 157166065Spjd { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 158219464Spjd { "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 159166065Spjd { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 160219464Spjd { "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 161166065Spjd { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 162219464Spjd { "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 163210965Spjd { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, 164219464Spjd { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, 165210951Spjd { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } }, 166247669Spjd#ifdef HAS_BINDAT 167247669Spjd { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 168247669Spjd#endif 169210951Spjd { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } }, 170247669Spjd#ifdef HAS_CONNECTAT 171247669Spjd { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 172247669Spjd#endif 173166065Spjd { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 174219464Spjd { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } }, 175166065Spjd#ifdef HAS_LCHMOD 176166065Spjd { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 177166065Spjd#endif 178219464Spjd { "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } }, 179166065Spjd { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } }, 180219464Spjd { "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } }, 181166065Spjd { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } }, 182219464Spjd { "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } }, 183166065Spjd#ifdef HAS_CHFLAGS 184166065Spjd { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 185166065Spjd#endif 186219437Spjd#ifdef HAS_FCHFLAGS 187219464Spjd { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 188219437Spjd#endif 189248603Spjd#ifdef HAS_CHFLAGSAT 190248603Spjd { "chflagsat", ACTION_CHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 191248603Spjd#endif 192166065Spjd#ifdef HAS_LCHFLAGS 193166065Spjd { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 194166065Spjd#endif 195166065Spjd { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, 196219464Spjd { "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } }, 197166065Spjd { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 198219464Spjd { "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 199166065Spjd { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 200219464Spjd { "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 201185219Spjd { "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 202219464Spjd { "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 203219437Spjd { "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 204196948Strasz#ifdef HAS_FREEBSD_ACL 205196948Strasz { "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } }, 206196948Strasz { "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } }, 207196948Strasz#endif 208219464Spjd { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, 209166065Spjd { NULL, -1, { TYPE_NONE } } 210166065Spjd}; 211166065Spjd 212166065Spjdstruct flag { 213166065Spjd long long f_flag; 214219566Spjd const char *f_str; 215166065Spjd}; 216166065Spjd 217166065Spjdstatic struct flag open_flags[] = { 218166065Spjd#ifdef O_RDONLY 219166065Spjd { O_RDONLY, "O_RDONLY" }, 220166065Spjd#endif 221166065Spjd#ifdef O_WRONLY 222166065Spjd { O_WRONLY, "O_WRONLY" }, 223166065Spjd#endif 224166065Spjd#ifdef O_RDWR 225166065Spjd { O_RDWR, "O_RDWR" }, 226166065Spjd#endif 227166065Spjd#ifdef O_NONBLOCK 228166065Spjd { O_NONBLOCK, "O_NONBLOCK" }, 229166065Spjd#endif 230166065Spjd#ifdef O_APPEND 231166065Spjd { O_APPEND, "O_APPEND" }, 232166065Spjd#endif 233166065Spjd#ifdef O_CREAT 234166065Spjd { O_CREAT, "O_CREAT" }, 235166065Spjd#endif 236166065Spjd#ifdef O_TRUNC 237166065Spjd { O_TRUNC, "O_TRUNC" }, 238166065Spjd#endif 239166065Spjd#ifdef O_EXCL 240166065Spjd { O_EXCL, "O_EXCL" }, 241166065Spjd#endif 242166065Spjd#ifdef O_SHLOCK 243166065Spjd { O_SHLOCK, "O_SHLOCK" }, 244166065Spjd#endif 245166065Spjd#ifdef O_EXLOCK 246166065Spjd { O_EXLOCK, "O_EXLOCK" }, 247166065Spjd#endif 248166065Spjd#ifdef O_DIRECT 249166065Spjd { O_DIRECT, "O_DIRECT" }, 250166065Spjd#endif 251166065Spjd#ifdef O_FSYNC 252166065Spjd { O_FSYNC, "O_FSYNC" }, 253166065Spjd#endif 254166065Spjd#ifdef O_SYNC 255166065Spjd { O_SYNC, "O_SYNC" }, 256166065Spjd#endif 257166065Spjd#ifdef O_NOFOLLOW 258166065Spjd { O_NOFOLLOW, "O_NOFOLLOW" }, 259166065Spjd#endif 260166065Spjd#ifdef O_NOCTTY 261166065Spjd { O_NOCTTY, "O_NOCTTY" }, 262166065Spjd#endif 263219464Spjd#ifdef O_DIRECTORY 264219464Spjd { O_DIRECTORY, "O_DIRECTORY" }, 265219464Spjd#endif 266166065Spjd { 0, NULL } 267166065Spjd}; 268166065Spjd 269166065Spjd#ifdef HAS_CHFLAGS 270166065Spjdstatic struct flag chflags_flags[] = { 271166065Spjd#ifdef UF_NODUMP 272166065Spjd { UF_NODUMP, "UF_NODUMP" }, 273166065Spjd#endif 274166065Spjd#ifdef UF_IMMUTABLE 275166065Spjd { UF_IMMUTABLE, "UF_IMMUTABLE" }, 276166065Spjd#endif 277166065Spjd#ifdef UF_APPEND 278166065Spjd { UF_APPEND, "UF_APPEND" }, 279166065Spjd#endif 280166065Spjd#ifdef UF_NOUNLINK 281166065Spjd { UF_NOUNLINK, "UF_NOUNLINK" }, 282166065Spjd#endif 283166065Spjd#ifdef UF_OPAQUE 284166065Spjd { UF_OPAQUE, "UF_OPAQUE" }, 285166065Spjd#endif 286166065Spjd#ifdef SF_ARCHIVED 287166065Spjd { SF_ARCHIVED, "SF_ARCHIVED" }, 288166065Spjd#endif 289166065Spjd#ifdef SF_IMMUTABLE 290166065Spjd { SF_IMMUTABLE, "SF_IMMUTABLE" }, 291166065Spjd#endif 292166065Spjd#ifdef SF_APPEND 293166065Spjd { SF_APPEND, "SF_APPEND" }, 294166065Spjd#endif 295166065Spjd#ifdef SF_NOUNLINK 296166065Spjd { SF_NOUNLINK, "SF_NOUNLINK" }, 297166065Spjd#endif 298166065Spjd#ifdef SF_SNAPSHOT 299166065Spjd { SF_SNAPSHOT, "SF_SNAPSHOT" }, 300166065Spjd#endif 301166065Spjd { 0, NULL } 302166065Spjd}; 303166065Spjd#endif 304166065Spjd 305219464Spjdstatic struct flag unlinkat_flags[] = { 306219464Spjd { AT_REMOVEDIR, "AT_REMOVEDIR" }, 307219464Spjd { 0, NULL } 308219464Spjd}; 309219464Spjd 310219464Spjdstatic struct flag linkat_flags[] = { 311219464Spjd { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" }, 312219464Spjd { 0, NULL } 313219464Spjd}; 314219464Spjd 315248603Spjdstatic struct flag chflagsat_flags[] = { 316248603Spjd { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 317248603Spjd { 0, NULL } 318248603Spjd}; 319248603Spjd 320219464Spjdstatic struct flag fchmodat_flags[] = { 321219464Spjd { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 322219464Spjd { 0, NULL } 323219464Spjd}; 324219464Spjd 325219464Spjdstatic struct flag fchownat_flags[] = { 326219464Spjd { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 327219464Spjd { 0, NULL } 328219464Spjd}; 329219464Spjd 330219464Spjdstatic struct flag fstatat_flags[] = { 331219464Spjd { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" }, 332219464Spjd { 0, NULL } 333219464Spjd}; 334219464Spjd 335185219Spjdstruct name { 336219566Spjd int n_name; 337219566Spjd const char *n_str; 338185219Spjd}; 339185219Spjd 340185219Spjdstatic struct name pathconf_names[] = { 341185219Spjd#ifdef _PC_LINK_MAX 342185219Spjd { _PC_LINK_MAX, "_PC_LINK_MAX" }, 343185219Spjd#endif 344185219Spjd#ifdef _PC_NAME_MAX 345185219Spjd { _PC_NAME_MAX, "_PC_NAME_MAX" }, 346185219Spjd#endif 347185219Spjd#ifdef _PC_PATH_MAX 348185219Spjd { _PC_PATH_MAX, "_PC_PATH_MAX" }, 349185219Spjd#endif 350185219Spjd#ifdef _PC_SYMLINK_MAX 351185219Spjd { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" }, 352185219Spjd#endif 353185219Spjd { 0, NULL } 354185219Spjd}; 355185219Spjd 356166065Spjdstatic const char *err2str(int error); 357166065Spjd 358219437Spjdstatic int *descriptors; 359219437Spjdstatic int ndescriptors; 360219437Spjd 361166065Spjdstatic void 362166065Spjdusage(void) 363166065Spjd{ 364166065Spjd 365211354Spjd fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n"); 366166065Spjd exit(1); 367166065Spjd} 368166065Spjd 369166065Spjdstatic long long 370166065Spjdstr2flags(struct flag *tflags, char *sflags) 371166065Spjd{ 372166065Spjd long long flags = 0; 373166065Spjd unsigned int i; 374166065Spjd char *f; 375166065Spjd 376238110Spjd /* 'none' or '0' means no flags */ 377238110Spjd if (strcmp(sflags, "none") == 0 || strcmp(sflags, "0") == 0) 378238110Spjd return (0); 379238110Spjd for (f = strtok(sflags, ",|"); f != NULL; f = strtok(NULL, ",|")) { 380166065Spjd for (i = 0; tflags[i].f_str != NULL; i++) { 381166065Spjd if (strcmp(tflags[i].f_str, f) == 0) 382166065Spjd break; 383166065Spjd } 384166065Spjd if (tflags[i].f_str == NULL) { 385166065Spjd fprintf(stderr, "unknown flag '%s'\n", f); 386166065Spjd exit(1); 387166065Spjd } 388166065Spjd flags |= tflags[i].f_flag; 389166065Spjd } 390166065Spjd return (flags); 391166065Spjd} 392166065Spjd 393166065Spjd#ifdef HAS_CHFLAGS 394166065Spjdstatic char * 395166065Spjdflags2str(struct flag *tflags, long long flags) 396166065Spjd{ 397166065Spjd static char sflags[1024]; 398166065Spjd unsigned int i; 399166065Spjd 400166065Spjd sflags[0] = '\0'; 401166065Spjd for (i = 0; tflags[i].f_str != NULL; i++) { 402166065Spjd if (flags & tflags[i].f_flag) { 403166065Spjd if (sflags[0] != '\0') 404166065Spjd strlcat(sflags, ",", sizeof(sflags)); 405166065Spjd strlcat(sflags, tflags[i].f_str, sizeof(sflags)); 406166065Spjd } 407166065Spjd } 408166065Spjd if (sflags[0] == '\0') 409166065Spjd strlcpy(sflags, "none", sizeof(sflags)); 410166065Spjd return (sflags); 411166065Spjd} 412166065Spjd#endif 413166065Spjd 414185219Spjdstatic int 415185219Spjdstr2name(struct name *names, char *name) 416185219Spjd{ 417185219Spjd unsigned int i; 418185219Spjd 419185219Spjd for (i = 0; names[i].n_str != NULL; i++) { 420185219Spjd if (strcmp(names[i].n_str, name) == 0) 421185219Spjd return (names[i].n_name); 422185219Spjd } 423185219Spjd return (-1); 424185219Spjd} 425185219Spjd 426166065Spjdstatic struct syscall_desc * 427166065Spjdfind_syscall(const char *name) 428166065Spjd{ 429166065Spjd int i; 430166065Spjd 431166065Spjd for (i = 0; syscalls[i].sd_name != NULL; i++) { 432166065Spjd if (strcmp(syscalls[i].sd_name, name) == 0) 433166065Spjd return (&syscalls[i]); 434166065Spjd } 435166065Spjd return (NULL); 436166065Spjd} 437166065Spjd 438166065Spjdstatic void 439166065Spjdshow_stat(struct stat64 *sp, const char *what) 440166065Spjd{ 441166065Spjd 442166065Spjd if (strcmp(what, "mode") == 0) 443166065Spjd printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS)); 444166065Spjd else if (strcmp(what, "inode") == 0) 445166065Spjd printf("%lld", (long long)sp->st_ino); 446166065Spjd else if (strcmp(what, "nlink") == 0) 447166065Spjd printf("%lld", (long long)sp->st_nlink); 448166065Spjd else if (strcmp(what, "uid") == 0) 449166065Spjd printf("%d", (int)sp->st_uid); 450166065Spjd else if (strcmp(what, "gid") == 0) 451166065Spjd printf("%d", (int)sp->st_gid); 452166065Spjd else if (strcmp(what, "size") == 0) 453166065Spjd printf("%lld", (long long)sp->st_size); 454166065Spjd else if (strcmp(what, "blocks") == 0) 455166065Spjd printf("%lld", (long long)sp->st_blocks); 456166065Spjd else if (strcmp(what, "atime") == 0) 457166065Spjd printf("%lld", (long long)sp->st_atime); 458166065Spjd else if (strcmp(what, "mtime") == 0) 459166065Spjd printf("%lld", (long long)sp->st_mtime); 460166065Spjd else if (strcmp(what, "ctime") == 0) 461166065Spjd printf("%lld", (long long)sp->st_ctime); 462166065Spjd#ifdef HAS_CHFLAGS 463166065Spjd else if (strcmp(what, "flags") == 0) 464188934Spjd printf("%s", flags2str(chflags_flags, (long long)sp->st_flags)); 465166065Spjd#endif 466210965Spjd else if (strcmp(what, "major") == 0) 467210965Spjd printf("%u", (unsigned int)major(sp->st_rdev)); 468210965Spjd else if (strcmp(what, "minor") == 0) 469210965Spjd printf("%u", (unsigned int)minor(sp->st_rdev)); 470166065Spjd else if (strcmp(what, "type") == 0) { 471166065Spjd switch (sp->st_mode & S_IFMT) { 472166065Spjd case S_IFIFO: 473166065Spjd printf("fifo"); 474166065Spjd break; 475166065Spjd case S_IFCHR: 476166065Spjd printf("char"); 477166065Spjd break; 478166065Spjd case S_IFDIR: 479166065Spjd printf("dir"); 480166065Spjd break; 481166065Spjd case S_IFBLK: 482166065Spjd printf("block"); 483166065Spjd break; 484166065Spjd case S_IFREG: 485166065Spjd printf("regular"); 486166065Spjd break; 487166065Spjd case S_IFLNK: 488166065Spjd printf("symlink"); 489166065Spjd break; 490166065Spjd case S_IFSOCK: 491166065Spjd printf("socket"); 492166065Spjd break; 493166065Spjd default: 494166065Spjd printf("unknown"); 495166065Spjd break; 496166065Spjd } 497166065Spjd } else { 498166065Spjd printf("unknown"); 499166065Spjd } 500166065Spjd} 501166065Spjd 502166065Spjdstatic void 503166065Spjdshow_stats(struct stat64 *sp, char *what) 504166065Spjd{ 505166065Spjd const char *s = ""; 506166065Spjd char *w; 507166065Spjd 508166065Spjd for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) { 509166065Spjd printf("%s", s); 510166065Spjd show_stat(sp, w); 511166065Spjd s = ","; 512166065Spjd } 513166065Spjd printf("\n"); 514166065Spjd} 515166065Spjd 516219437Spjdstatic void 517219437Spjddescriptor_add(int fd) 518219437Spjd{ 519219437Spjd 520219437Spjd ndescriptors++; 521219437Spjd if (descriptors == NULL) { 522219437Spjd descriptors = malloc(sizeof(descriptors[0]) * ndescriptors); 523219437Spjd } else { 524219437Spjd descriptors = realloc(descriptors, 525219437Spjd sizeof(descriptors[0]) * ndescriptors); 526219437Spjd } 527219437Spjd assert(descriptors != NULL); 528219437Spjd descriptors[ndescriptors - 1] = fd; 529219437Spjd} 530219437Spjd 531219437Spjdstatic int 532219437Spjddescriptor_get(int pos) 533219437Spjd{ 534219437Spjd 535219437Spjd if (pos < 0 || pos >= ndescriptors) { 536219437Spjd fprintf(stderr, "invalid descriptor %d\n", pos); 537219437Spjd exit(1); 538219437Spjd } 539219437Spjd 540219437Spjd return (descriptors[pos]); 541219437Spjd} 542219437Spjd 543166065Spjdstatic unsigned int 544166065Spjdcall_syscall(struct syscall_desc *scall, char *argv[]) 545166065Spjd{ 546166065Spjd struct stat64 sb; 547166065Spjd long long flags; 548166065Spjd unsigned int i; 549166065Spjd char *endp; 550185219Spjd int name, rval; 551166065Spjd union { 552166065Spjd char *str; 553166065Spjd long long num; 554166065Spjd } args[MAX_ARGS]; 555196948Strasz#ifdef HAS_FREEBSD_ACL 556196948Strasz int entry_id = ACL_FIRST_ENTRY; 557196948Strasz acl_t acl, newacl; 558196948Strasz acl_entry_t entry, newentry; 559196948Strasz#endif 560166065Spjd 561166065Spjd /* 562166065Spjd * Verify correctness of the arguments. 563166065Spjd */ 564166065Spjd for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) { 565166065Spjd if (scall->sd_args[i] == TYPE_NONE) { 566166065Spjd if (argv[i] == NULL || strcmp(argv[i], ":") == 0) 567166065Spjd break; 568166065Spjd fprintf(stderr, "too many arguments [%s]\n", argv[i]); 569166065Spjd exit(1); 570166065Spjd } else { 571166065Spjd if (argv[i] == NULL || strcmp(argv[i], ":") == 0) { 572166065Spjd if (scall->sd_args[i] & TYPE_OPTIONAL) 573166065Spjd break; 574166065Spjd fprintf(stderr, "too few arguments\n"); 575166065Spjd exit(1); 576166065Spjd } 577219464Spjd if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) { 578166065Spjd if (strcmp(argv[i], "NULL") == 0) 579166065Spjd args[i].str = NULL; 580166065Spjd else if (strcmp(argv[i], "DEADCODE") == 0) 581166065Spjd args[i].str = (void *)0xdeadc0de; 582166065Spjd else 583166065Spjd args[i].str = argv[i]; 584249594Spjd } else if ((scall->sd_args[i] & TYPE_MASK) == 585249594Spjd TYPE_NUMBER) { 586166065Spjd args[i].num = strtoll(argv[i], &endp, 0); 587249594Spjd if (*endp != '\0' && 588249594Spjd !isspace((unsigned char)*endp)) { 589249594Spjd fprintf(stderr, 590249594Spjd "invalid argument %u, number expected [%s]\n", 591249594Spjd i, endp); 592166065Spjd exit(1); 593166065Spjd } 594249594Spjd } else if ((scall->sd_args[i] & TYPE_MASK) == 595249594Spjd TYPE_DESCRIPTOR) { 596219464Spjd if (strcmp(argv[i], "AT_FDCWD") == 0) { 597219464Spjd args[i].num = AT_FDCWD; 598219464Spjd } else if (strcmp(argv[i], "BADFD") == 0) { 599219464Spjd /* In case AT_FDCWD is -1 on some systems... */ 600219464Spjd if (AT_FDCWD == -1) 601219464Spjd args[i].num = -2; 602219464Spjd else 603219464Spjd args[i].num = -1; 604219464Spjd } else { 605219464Spjd int pos; 606219464Spjd 607219464Spjd pos = strtoll(argv[i], &endp, 0); 608249594Spjd if (*endp != '\0' && 609249594Spjd !isspace((unsigned char)*endp)) { 610249594Spjd fprintf(stderr, 611249594Spjd "invalid argument %u, number expected [%s]\n", 612249594Spjd i, endp); 613219464Spjd exit(1); 614219464Spjd } 615219464Spjd args[i].num = descriptor_get(pos); 616219464Spjd } 617166065Spjd } 618166065Spjd } 619166065Spjd } 620166065Spjd /* 621166065Spjd * Call the given syscall. 622166065Spjd */ 623166065Spjd#define NUM(n) (args[(n)].num) 624166065Spjd#define STR(n) (args[(n)].str) 625166065Spjd switch (scall->sd_action) { 626166065Spjd case ACTION_OPEN: 627166065Spjd flags = str2flags(open_flags, STR(1)); 628166065Spjd if (flags & O_CREAT) { 629166065Spjd if (i == 2) { 630166065Spjd fprintf(stderr, "too few arguments\n"); 631166065Spjd exit(1); 632166065Spjd } 633188934Spjd rval = open(STR(0), (int)flags, (mode_t)NUM(2)); 634166065Spjd } else { 635166065Spjd if (i == 3) { 636166065Spjd fprintf(stderr, "too many arguments\n"); 637166065Spjd exit(1); 638166065Spjd } 639188934Spjd rval = open(STR(0), (int)flags); 640166065Spjd } 641219437Spjd if (rval >= 0) 642219437Spjd descriptor_add(rval); 643166065Spjd break; 644219464Spjd case ACTION_OPENAT: 645219464Spjd flags = str2flags(open_flags, STR(2)); 646219464Spjd if (flags & O_CREAT) { 647219464Spjd if (i == 3) { 648219464Spjd fprintf(stderr, "too few arguments\n"); 649219464Spjd exit(1); 650219464Spjd } 651249594Spjd rval = openat(NUM(0), STR(1), (int)flags, 652249594Spjd (mode_t)NUM(3)); 653219464Spjd } else { 654219464Spjd if (i == 4) { 655219464Spjd fprintf(stderr, "too many arguments\n"); 656219464Spjd exit(1); 657219464Spjd } 658219464Spjd rval = openat(NUM(0), STR(1), (int)flags); 659219464Spjd } 660219464Spjd if (rval >= 0) 661219464Spjd descriptor_add(rval); 662219464Spjd break; 663166065Spjd case ACTION_CREATE: 664188934Spjd rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1)); 665166065Spjd if (rval >= 0) 666166065Spjd close(rval); 667166065Spjd break; 668166065Spjd case ACTION_UNLINK: 669166065Spjd rval = unlink(STR(0)); 670166065Spjd break; 671219464Spjd case ACTION_UNLINKAT: 672219464Spjd rval = unlinkat(NUM(0), STR(1), 673219464Spjd (int)str2flags(unlinkat_flags, STR(2))); 674219464Spjd break; 675166065Spjd case ACTION_MKDIR: 676188934Spjd rval = mkdir(STR(0), (mode_t)NUM(1)); 677166065Spjd break; 678219464Spjd case ACTION_MKDIRAT: 679219464Spjd rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2)); 680219464Spjd break; 681166065Spjd case ACTION_RMDIR: 682166065Spjd rval = rmdir(STR(0)); 683166065Spjd break; 684166065Spjd case ACTION_LINK: 685166065Spjd rval = link(STR(0), STR(1)); 686166065Spjd break; 687219464Spjd case ACTION_LINKAT: 688219464Spjd rval = linkat(NUM(0), STR(1), NUM(2), STR(3), 689219464Spjd (int)str2flags(linkat_flags, STR(4))); 690219464Spjd break; 691166065Spjd case ACTION_SYMLINK: 692166065Spjd rval = symlink(STR(0), STR(1)); 693166065Spjd break; 694219464Spjd case ACTION_SYMLINKAT: 695219464Spjd rval = symlinkat(STR(0), NUM(1), STR(2)); 696219464Spjd break; 697166065Spjd case ACTION_RENAME: 698166065Spjd rval = rename(STR(0), STR(1)); 699166065Spjd break; 700219464Spjd case ACTION_RENAMEAT: 701219464Spjd rval = renameat(NUM(0), STR(1), NUM(2), STR(3)); 702219464Spjd break; 703166065Spjd case ACTION_MKFIFO: 704188934Spjd rval = mkfifo(STR(0), (mode_t)NUM(1)); 705166065Spjd break; 706219464Spjd case ACTION_MKFIFOAT: 707219464Spjd rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2)); 708219464Spjd break; 709210965Spjd case ACTION_MKNOD: 710219464Spjd case ACTION_MKNODAT: 711210965Spjd { 712210965Spjd mode_t ntype; 713210965Spjd dev_t dev; 714219464Spjd int fa; 715210965Spjd 716219464Spjd switch (scall->sd_action) { 717219464Spjd case ACTION_MKNOD: 718219464Spjd fa = 0; 719219464Spjd break; 720219464Spjd case ACTION_MKNODAT: 721219464Spjd fa = 1; 722219464Spjd break; 723219464Spjd default: 724219464Spjd abort(); 725219464Spjd } 726219464Spjd 727219464Spjd dev = makedev(NUM(fa + 3), NUM(fa + 4)); 728249594Spjd if (strcmp(STR(fa + 1), "c") == 0) /* character device */ 729210965Spjd ntype = S_IFCHR; 730219464Spjd else if (strcmp(STR(fa + 1), "b") == 0) /* block device */ 731210965Spjd ntype = S_IFBLK; 732219464Spjd else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */ 733210965Spjd ntype = S_IFIFO; 734219464Spjd else if (strcmp(STR(fa + 1), "d") == 0) /* directory */ 735210965Spjd ntype = S_IFDIR; 736219464Spjd else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */ 737210965Spjd ntype = S_IFREG; 738210965Spjd else { 739210965Spjd fprintf(stderr, "wrong argument 1\n"); 740210965Spjd exit(1); 741210965Spjd } 742219464Spjd switch (scall->sd_action) { 743219464Spjd case ACTION_MKNOD: 744219464Spjd rval = mknod(STR(0), ntype | NUM(2), dev); 745219464Spjd break; 746219464Spjd case ACTION_MKNODAT: 747219464Spjd rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev); 748219464Spjd break; 749219464Spjd default: 750219464Spjd abort(); 751219464Spjd } 752210965Spjd break; 753210965Spjd } 754210951Spjd case ACTION_BIND: 755210951Spjd { 756211110Spjd struct sockaddr_un sunx; 757210951Spjd 758211110Spjd sunx.sun_family = AF_UNIX; 759211116Spjd strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); 760211116Spjd sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 761210951Spjd rval = socket(AF_UNIX, SOCK_STREAM, 0); 762210951Spjd if (rval < 0) 763210951Spjd break; 764211110Spjd rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx)); 765210951Spjd break; 766210951Spjd } 767247669Spjd#ifdef HAS_BINDAT 768247669Spjd case ACTION_BINDAT: 769247669Spjd { 770247669Spjd struct sockaddr_un sunx; 771247669Spjd 772247669Spjd sunx.sun_family = AF_UNIX; 773247669Spjd strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); 774247669Spjd sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 775247669Spjd rval = socket(AF_UNIX, SOCK_STREAM, 0); 776247669Spjd if (rval < 0) 777247669Spjd break; 778247669Spjd rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx, 779247669Spjd sizeof(sunx)); 780247669Spjd break; 781247669Spjd } 782247669Spjd#endif 783210951Spjd case ACTION_CONNECT: 784210951Spjd { 785211110Spjd struct sockaddr_un sunx; 786210951Spjd 787211110Spjd sunx.sun_family = AF_UNIX; 788211116Spjd strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); 789211116Spjd sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 790210951Spjd rval = socket(AF_UNIX, SOCK_STREAM, 0); 791210951Spjd if (rval < 0) 792210951Spjd break; 793211110Spjd rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx)); 794210951Spjd break; 795210951Spjd } 796247669Spjd#ifdef HAS_CONNECTAT 797247669Spjd case ACTION_CONNECTAT: 798247669Spjd { 799247669Spjd struct sockaddr_un sunx; 800247669Spjd 801247669Spjd sunx.sun_family = AF_UNIX; 802247669Spjd strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); 803247669Spjd sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; 804247669Spjd rval = socket(AF_UNIX, SOCK_STREAM, 0); 805247669Spjd if (rval < 0) 806247669Spjd break; 807247669Spjd rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx, 808247669Spjd sizeof(sunx)); 809247669Spjd break; 810247669Spjd } 811247669Spjd#endif 812166065Spjd case ACTION_CHMOD: 813188934Spjd rval = chmod(STR(0), (mode_t)NUM(1)); 814166065Spjd break; 815219437Spjd case ACTION_FCHMOD: 816219464Spjd rval = fchmod(NUM(0), (mode_t)NUM(1)); 817219437Spjd break; 818166065Spjd#ifdef HAS_LCHMOD 819166065Spjd case ACTION_LCHMOD: 820188934Spjd rval = lchmod(STR(0), (mode_t)NUM(1)); 821166065Spjd break; 822166065Spjd#endif 823219464Spjd case ACTION_FCHMODAT: 824219464Spjd rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2), 825219464Spjd str2flags(fchmodat_flags, STR(3))); 826219464Spjd break; 827166065Spjd case ACTION_CHOWN: 828188934Spjd rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); 829166065Spjd break; 830219437Spjd case ACTION_FCHOWN: 831219464Spjd rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2)); 832219437Spjd break; 833166065Spjd case ACTION_LCHOWN: 834188934Spjd rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); 835166065Spjd break; 836219464Spjd case ACTION_FCHOWNAT: 837219464Spjd rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3), 838219464Spjd (int)str2flags(fchownat_flags, STR(4))); 839219464Spjd break; 840166065Spjd#ifdef HAS_CHFLAGS 841166065Spjd case ACTION_CHFLAGS: 842219464Spjd rval = chflags(STR(0), 843219464Spjd (unsigned long)str2flags(chflags_flags, STR(1))); 844166065Spjd break; 845166065Spjd#endif 846219437Spjd#ifdef HAS_FCHFLAGS 847219437Spjd case ACTION_FCHFLAGS: 848219464Spjd rval = fchflags(NUM(0), 849219464Spjd (unsigned long)str2flags(chflags_flags, STR(1))); 850219437Spjd break; 851219437Spjd#endif 852248603Spjd#ifdef HAS_CHFLAGSAT 853248603Spjd case ACTION_CHFLAGSAT: 854248603Spjd rval = chflagsat(NUM(0), STR(1), 855248603Spjd (unsigned long)str2flags(chflags_flags, STR(2)), 856248603Spjd (int)str2flags(chflagsat_flags, STR(3))); 857248603Spjd break; 858248603Spjd#endif 859166065Spjd#ifdef HAS_LCHFLAGS 860166065Spjd case ACTION_LCHFLAGS: 861248597Spjd rval = lchflags(STR(0), 862248597Spjd (unsigned long)str2flags(chflags_flags, STR(1))); 863166065Spjd break; 864166065Spjd#endif 865166065Spjd case ACTION_TRUNCATE: 866166065Spjd rval = truncate64(STR(0), NUM(1)); 867166065Spjd break; 868219437Spjd case ACTION_FTRUNCATE: 869219464Spjd rval = ftruncate64(NUM(0), NUM(1)); 870219437Spjd break; 871166065Spjd case ACTION_STAT: 872166065Spjd rval = stat64(STR(0), &sb); 873166065Spjd if (rval == 0) { 874166065Spjd show_stats(&sb, STR(1)); 875166065Spjd return (i); 876166065Spjd } 877166065Spjd break; 878219437Spjd case ACTION_FSTAT: 879219464Spjd rval = fstat64(NUM(0), &sb); 880219437Spjd if (rval == 0) { 881219437Spjd show_stats(&sb, STR(1)); 882219437Spjd return (i); 883219437Spjd } 884219437Spjd break; 885166065Spjd case ACTION_LSTAT: 886166065Spjd rval = lstat64(STR(0), &sb); 887166065Spjd if (rval == 0) { 888166065Spjd show_stats(&sb, STR(1)); 889166065Spjd return (i); 890166065Spjd } 891166065Spjd break; 892219464Spjd case ACTION_FSTATAT: 893219464Spjd rval = fstatat(NUM(0), STR(1), &sb, 894219464Spjd (int)str2flags(fstatat_flags, STR(2))); 895219464Spjd if (rval == 0) { 896219464Spjd show_stats(&sb, STR(3)); 897219464Spjd return (i); 898219464Spjd } 899219464Spjd break; 900185219Spjd case ACTION_PATHCONF: 901219437Spjd case ACTION_FPATHCONF: 902219437Spjd case ACTION_LPATHCONF: 903185219Spjd { 904185219Spjd long lrval; 905185219Spjd 906185219Spjd name = str2name(pathconf_names, STR(1)); 907185219Spjd if (name == -1) { 908185219Spjd fprintf(stderr, "unknown name %s", STR(1)); 909185219Spjd exit(1); 910185219Spjd } 911185219Spjd errno = 0; 912219437Spjd switch (scall->sd_action) { 913219437Spjd case ACTION_PATHCONF: 914219437Spjd lrval = pathconf(STR(0), name); 915219437Spjd break; 916219437Spjd case ACTION_FPATHCONF: 917219464Spjd lrval = fpathconf(NUM(0), name); 918219437Spjd break; 919219437Spjd case ACTION_LPATHCONF: 920219437Spjd lrval = lpathconf(STR(0), name); 921219437Spjd break; 922219437Spjd default: 923219437Spjd abort(); 924219437Spjd } 925185219Spjd if (lrval == -1 && errno == 0) { 926185219Spjd printf("unlimited\n"); 927185219Spjd return (i); 928185219Spjd } else if (lrval >= 0) { 929185219Spjd printf("%ld\n", lrval); 930185219Spjd return (i); 931185219Spjd } 932185219Spjd rval = -1; 933185219Spjd break; 934185219Spjd } 935196948Strasz#ifdef HAS_FREEBSD_ACL 936196948Strasz case ACTION_PREPENDACL: 937196948Strasz rval = -1; 938196948Strasz 939196948Strasz acl = acl_get_file(STR(0), ACL_TYPE_NFS4); 940196948Strasz if (acl == NULL) 941196948Strasz break; 942196948Strasz 943196948Strasz newacl = acl_from_text(STR(1)); 944196948Strasz if (acl == NULL) 945196948Strasz break; 946196948Strasz 947196948Strasz while (acl_get_entry(newacl, entry_id, &newentry) == 1) { 948196948Strasz entry_id = ACL_NEXT_ENTRY; 949196948Strasz 950196948Strasz if (acl_create_entry_np(&acl, &entry, 0)) 951196948Strasz break; 952196948Strasz 953196948Strasz if (acl_copy_entry(entry, newentry)) 954196948Strasz break; 955196948Strasz } 956196948Strasz 957196948Strasz rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl); 958196948Strasz break; 959196948Strasz case ACTION_READACL: 960196948Strasz acl = acl_get_file(STR(0), ACL_TYPE_NFS4); 961196948Strasz if (acl == NULL) 962196948Strasz rval = -1; 963196948Strasz else 964196948Strasz rval = 0; 965196948Strasz break; 966196948Strasz#endif 967196948Strasz case ACTION_WRITE: 968219464Spjd rval = write(NUM(0), STR(1), strlen(STR(1))); 969196948Strasz break; 970166065Spjd default: 971166065Spjd fprintf(stderr, "unsupported syscall\n"); 972166065Spjd exit(1); 973166065Spjd } 974166065Spjd#undef STR 975166065Spjd#undef NUM 976166065Spjd if (rval < 0) { 977166065Spjd const char *serrno; 978166065Spjd 979166065Spjd serrno = err2str(errno); 980166065Spjd fprintf(stderr, "%s returned %d\n", scall->sd_name, rval); 981166065Spjd printf("%s\n", serrno); 982166065Spjd exit(1); 983166065Spjd } 984166065Spjd printf("0\n"); 985166065Spjd return (i); 986166065Spjd} 987166065Spjd 988166065Spjdstatic void 989166065Spjdset_gids(char *gids) 990166065Spjd{ 991166065Spjd gid_t *gidset; 992166065Spjd long ngroups; 993166065Spjd char *g, *endp; 994166065Spjd unsigned i; 995166065Spjd 996166065Spjd ngroups = sysconf(_SC_NGROUPS_MAX); 997166065Spjd assert(ngroups > 0); 998166065Spjd gidset = malloc(sizeof(*gidset) * ngroups); 999166065Spjd assert(gidset != NULL); 1000249594Spjd for (i = 0, g = strtok(gids, ","); g != NULL; 1001249594Spjd g = strtok(NULL, ","), i++) { 1002166065Spjd if (i >= ngroups) { 1003166065Spjd fprintf(stderr, "too many gids\n"); 1004166065Spjd exit(1); 1005166065Spjd } 1006166065Spjd gidset[i] = strtol(g, &endp, 0); 1007166065Spjd if (*endp != '\0' && !isspace((unsigned char)*endp)) { 1008166065Spjd fprintf(stderr, "invalid gid '%s' - number expected\n", 1009166065Spjd g); 1010166065Spjd exit(1); 1011166065Spjd } 1012166065Spjd } 1013166065Spjd if (setgroups(i, gidset) < 0) { 1014166065Spjd fprintf(stderr, "cannot change groups: %s\n", strerror(errno)); 1015166065Spjd exit(1); 1016166065Spjd } 1017171486Spjd if (setegid(gidset[0]) < 0) { 1018249594Spjd fprintf(stderr, "cannot change effective gid: %s\n", 1019249594Spjd strerror(errno)); 1020171486Spjd exit(1); 1021171486Spjd } 1022166065Spjd free(gidset); 1023166065Spjd} 1024166065Spjd 1025166065Spjdint 1026166065Spjdmain(int argc, char *argv[]) 1027166065Spjd{ 1028166065Spjd struct syscall_desc *scall; 1029166065Spjd unsigned int n; 1030166065Spjd char *gids, *endp; 1031166065Spjd int uid, umsk, ch; 1032166065Spjd 1033166065Spjd uid = -1; 1034166065Spjd gids = NULL; 1035166065Spjd umsk = 0; 1036166065Spjd 1037166065Spjd while ((ch = getopt(argc, argv, "g:u:U:")) != -1) { 1038166065Spjd switch(ch) { 1039166065Spjd case 'g': 1040166065Spjd gids = optarg; 1041166065Spjd break; 1042166065Spjd case 'u': 1043166065Spjd uid = (int)strtol(optarg, &endp, 0); 1044166065Spjd if (*endp != '\0' && !isspace((unsigned char)*endp)) { 1045166065Spjd fprintf(stderr, "invalid uid '%s' - number " 1046166065Spjd "expected\n", optarg); 1047166065Spjd exit(1); 1048166065Spjd } 1049166065Spjd break; 1050166065Spjd case 'U': 1051166065Spjd umsk = (int)strtol(optarg, &endp, 0); 1052166065Spjd if (*endp != '\0' && !isspace((unsigned char)*endp)) { 1053166065Spjd fprintf(stderr, "invalid umask '%s' - number " 1054166065Spjd "expected\n", optarg); 1055166065Spjd exit(1); 1056166065Spjd } 1057166065Spjd break; 1058166065Spjd default: 1059166065Spjd usage(); 1060166065Spjd } 1061166065Spjd } 1062166065Spjd argc -= optind; 1063166065Spjd argv += optind; 1064166065Spjd 1065166065Spjd if (argc < 1) { 1066166065Spjd fprintf(stderr, "too few arguments\n"); 1067166065Spjd usage(); 1068166065Spjd } 1069166065Spjd 1070166065Spjd if (gids != NULL) { 1071166065Spjd fprintf(stderr, "changing groups to %s\n", gids); 1072166065Spjd set_gids(gids); 1073166065Spjd } 1074166065Spjd if (uid != -1) { 1075166065Spjd fprintf(stderr, "changing uid to %d\n", uid); 1076166065Spjd if (setuid(uid) < 0) { 1077166065Spjd fprintf(stderr, "cannot change uid: %s\n", 1078166065Spjd strerror(errno)); 1079166065Spjd exit(1); 1080166065Spjd } 1081166065Spjd } 1082166065Spjd 1083166065Spjd /* Change umask to requested value or to 0, if not requested. */ 1084166065Spjd umask(umsk); 1085166065Spjd 1086166065Spjd for (;;) { 1087166065Spjd scall = find_syscall(argv[0]); 1088166065Spjd if (scall == NULL) { 1089249594Spjd fprintf(stderr, "syscall '%s' not supported\n", 1090249594Spjd argv[0]); 1091166065Spjd exit(1); 1092166065Spjd } 1093166065Spjd argc++; 1094166065Spjd argv++; 1095166065Spjd n = call_syscall(scall, argv); 1096166065Spjd argc += n; 1097166065Spjd argv += n; 1098166065Spjd if (argv[0] == NULL) 1099166065Spjd break; 1100166065Spjd argc++; 1101166065Spjd argv++; 1102166065Spjd } 1103166065Spjd 1104166065Spjd exit(0); 1105166065Spjd} 1106166065Spjd 1107166065Spjdstatic const char * 1108166065Spjderr2str(int error) 1109166065Spjd{ 1110166065Spjd static char errnum[8]; 1111166065Spjd 1112166065Spjd switch (error) { 1113166065Spjd#ifdef EPERM 1114166065Spjd case EPERM: 1115166065Spjd return ("EPERM"); 1116166065Spjd#endif 1117166065Spjd#ifdef ENOENT 1118166065Spjd case ENOENT: 1119166065Spjd return ("ENOENT"); 1120166065Spjd#endif 1121166065Spjd#ifdef ESRCH 1122166065Spjd case ESRCH: 1123166065Spjd return ("ESRCH"); 1124166065Spjd#endif 1125166065Spjd#ifdef EINTR 1126166065Spjd case EINTR: 1127166065Spjd return ("EINTR"); 1128166065Spjd#endif 1129166065Spjd#ifdef EIO 1130166065Spjd case EIO: 1131166065Spjd return ("EIO"); 1132166065Spjd#endif 1133166065Spjd#ifdef ENXIO 1134166065Spjd case ENXIO: 1135166065Spjd return ("ENXIO"); 1136166065Spjd#endif 1137166065Spjd#ifdef E2BIG 1138166065Spjd case E2BIG: 1139166065Spjd return ("E2BIG"); 1140166065Spjd#endif 1141166065Spjd#ifdef ENOEXEC 1142166065Spjd case ENOEXEC: 1143166065Spjd return ("ENOEXEC"); 1144166065Spjd#endif 1145166065Spjd#ifdef EBADF 1146166065Spjd case EBADF: 1147166065Spjd return ("EBADF"); 1148166065Spjd#endif 1149166065Spjd#ifdef ECHILD 1150166065Spjd case ECHILD: 1151166065Spjd return ("ECHILD"); 1152166065Spjd#endif 1153166065Spjd#ifdef EDEADLK 1154166065Spjd case EDEADLK: 1155166065Spjd return ("EDEADLK"); 1156166065Spjd#endif 1157166065Spjd#ifdef ENOMEM 1158166065Spjd case ENOMEM: 1159166065Spjd return ("ENOMEM"); 1160166065Spjd#endif 1161166065Spjd#ifdef EACCES 1162166065Spjd case EACCES: 1163166065Spjd return ("EACCES"); 1164166065Spjd#endif 1165166065Spjd#ifdef EFAULT 1166166065Spjd case EFAULT: 1167166065Spjd return ("EFAULT"); 1168166065Spjd#endif 1169166065Spjd#ifdef ENOTBLK 1170166065Spjd case ENOTBLK: 1171166065Spjd return ("ENOTBLK"); 1172166065Spjd#endif 1173166065Spjd#ifdef EBUSY 1174166065Spjd case EBUSY: 1175166065Spjd return ("EBUSY"); 1176166065Spjd#endif 1177166065Spjd#ifdef EEXIST 1178166065Spjd case EEXIST: 1179166065Spjd return ("EEXIST"); 1180166065Spjd#endif 1181166065Spjd#ifdef EXDEV 1182166065Spjd case EXDEV: 1183166065Spjd return ("EXDEV"); 1184166065Spjd#endif 1185166065Spjd#ifdef ENODEV 1186166065Spjd case ENODEV: 1187166065Spjd return ("ENODEV"); 1188166065Spjd#endif 1189166065Spjd#ifdef ENOTDIR 1190166065Spjd case ENOTDIR: 1191166065Spjd return ("ENOTDIR"); 1192166065Spjd#endif 1193166065Spjd#ifdef EISDIR 1194166065Spjd case EISDIR: 1195166065Spjd return ("EISDIR"); 1196166065Spjd#endif 1197166065Spjd#ifdef EINVAL 1198166065Spjd case EINVAL: 1199166065Spjd return ("EINVAL"); 1200166065Spjd#endif 1201166065Spjd#ifdef ENFILE 1202166065Spjd case ENFILE: 1203166065Spjd return ("ENFILE"); 1204166065Spjd#endif 1205166065Spjd#ifdef EMFILE 1206166065Spjd case EMFILE: 1207166065Spjd return ("EMFILE"); 1208166065Spjd#endif 1209166065Spjd#ifdef ENOTTY 1210166065Spjd case ENOTTY: 1211166065Spjd return ("ENOTTY"); 1212166065Spjd#endif 1213166065Spjd#ifdef ETXTBSY 1214166065Spjd case ETXTBSY: 1215166065Spjd return ("ETXTBSY"); 1216166065Spjd#endif 1217166065Spjd#ifdef EFBIG 1218166065Spjd case EFBIG: 1219166065Spjd return ("EFBIG"); 1220166065Spjd#endif 1221166065Spjd#ifdef ENOSPC 1222166065Spjd case ENOSPC: 1223166065Spjd return ("ENOSPC"); 1224166065Spjd#endif 1225166065Spjd#ifdef ESPIPE 1226166065Spjd case ESPIPE: 1227166065Spjd return ("ESPIPE"); 1228166065Spjd#endif 1229166065Spjd#ifdef EROFS 1230166065Spjd case EROFS: 1231166065Spjd return ("EROFS"); 1232166065Spjd#endif 1233166065Spjd#ifdef EMLINK 1234166065Spjd case EMLINK: 1235166065Spjd return ("EMLINK"); 1236166065Spjd#endif 1237166065Spjd#ifdef EPIPE 1238166065Spjd case EPIPE: 1239166065Spjd return ("EPIPE"); 1240166065Spjd#endif 1241166065Spjd#ifdef EDOM 1242166065Spjd case EDOM: 1243166065Spjd return ("EDOM"); 1244166065Spjd#endif 1245166065Spjd#ifdef ERANGE 1246166065Spjd case ERANGE: 1247166065Spjd return ("ERANGE"); 1248166065Spjd#endif 1249166065Spjd#ifdef EAGAIN 1250166065Spjd case EAGAIN: 1251166065Spjd return ("EAGAIN"); 1252166065Spjd#endif 1253166065Spjd#ifdef EINPROGRESS 1254166065Spjd case EINPROGRESS: 1255166065Spjd return ("EINPROGRESS"); 1256166065Spjd#endif 1257166065Spjd#ifdef EALREADY 1258166065Spjd case EALREADY: 1259166065Spjd return ("EALREADY"); 1260166065Spjd#endif 1261166065Spjd#ifdef ENOTSOCK 1262166065Spjd case ENOTSOCK: 1263166065Spjd return ("ENOTSOCK"); 1264166065Spjd#endif 1265166065Spjd#ifdef EDESTADDRREQ 1266166065Spjd case EDESTADDRREQ: 1267166065Spjd return ("EDESTADDRREQ"); 1268166065Spjd#endif 1269166065Spjd#ifdef EMSGSIZE 1270166065Spjd case EMSGSIZE: 1271166065Spjd return ("EMSGSIZE"); 1272166065Spjd#endif 1273166065Spjd#ifdef EPROTOTYPE 1274166065Spjd case EPROTOTYPE: 1275166065Spjd return ("EPROTOTYPE"); 1276166065Spjd#endif 1277166065Spjd#ifdef ENOPROTOOPT 1278166065Spjd case ENOPROTOOPT: 1279166065Spjd return ("ENOPROTOOPT"); 1280166065Spjd#endif 1281166065Spjd#ifdef EPROTONOSUPPORT 1282166065Spjd case EPROTONOSUPPORT: 1283166065Spjd return ("EPROTONOSUPPORT"); 1284166065Spjd#endif 1285166065Spjd#ifdef ESOCKTNOSUPPORT 1286166065Spjd case ESOCKTNOSUPPORT: 1287166065Spjd return ("ESOCKTNOSUPPORT"); 1288166065Spjd#endif 1289166065Spjd#ifdef EOPNOTSUPP 1290166065Spjd case EOPNOTSUPP: 1291166065Spjd return ("EOPNOTSUPP"); 1292166065Spjd#endif 1293166065Spjd#ifdef EPFNOSUPPORT 1294166065Spjd case EPFNOSUPPORT: 1295166065Spjd return ("EPFNOSUPPORT"); 1296166065Spjd#endif 1297166065Spjd#ifdef EAFNOSUPPORT 1298166065Spjd case EAFNOSUPPORT: 1299166065Spjd return ("EAFNOSUPPORT"); 1300166065Spjd#endif 1301166065Spjd#ifdef EADDRINUSE 1302166065Spjd case EADDRINUSE: 1303166065Spjd return ("EADDRINUSE"); 1304166065Spjd#endif 1305166065Spjd#ifdef EADDRNOTAVAIL 1306166065Spjd case EADDRNOTAVAIL: 1307166065Spjd return ("EADDRNOTAVAIL"); 1308166065Spjd#endif 1309166065Spjd#ifdef ENETDOWN 1310166065Spjd case ENETDOWN: 1311166065Spjd return ("ENETDOWN"); 1312166065Spjd#endif 1313166065Spjd#ifdef ENETUNREACH 1314166065Spjd case ENETUNREACH: 1315166065Spjd return ("ENETUNREACH"); 1316166065Spjd#endif 1317166065Spjd#ifdef ENETRESET 1318166065Spjd case ENETRESET: 1319166065Spjd return ("ENETRESET"); 1320166065Spjd#endif 1321166065Spjd#ifdef ECONNABORTED 1322166065Spjd case ECONNABORTED: 1323166065Spjd return ("ECONNABORTED"); 1324166065Spjd#endif 1325166065Spjd#ifdef ECONNRESET 1326166065Spjd case ECONNRESET: 1327166065Spjd return ("ECONNRESET"); 1328166065Spjd#endif 1329166065Spjd#ifdef ENOBUFS 1330166065Spjd case ENOBUFS: 1331166065Spjd return ("ENOBUFS"); 1332166065Spjd#endif 1333166065Spjd#ifdef EISCONN 1334166065Spjd case EISCONN: 1335166065Spjd return ("EISCONN"); 1336166065Spjd#endif 1337166065Spjd#ifdef ENOTCONN 1338166065Spjd case ENOTCONN: 1339166065Spjd return ("ENOTCONN"); 1340166065Spjd#endif 1341166065Spjd#ifdef ESHUTDOWN 1342166065Spjd case ESHUTDOWN: 1343166065Spjd return ("ESHUTDOWN"); 1344166065Spjd#endif 1345166065Spjd#ifdef ETOOMANYREFS 1346166065Spjd case ETOOMANYREFS: 1347166065Spjd return ("ETOOMANYREFS"); 1348166065Spjd#endif 1349166065Spjd#ifdef ETIMEDOUT 1350166065Spjd case ETIMEDOUT: 1351166065Spjd return ("ETIMEDOUT"); 1352166065Spjd#endif 1353166065Spjd#ifdef ECONNREFUSED 1354166065Spjd case ECONNREFUSED: 1355166065Spjd return ("ECONNREFUSED"); 1356166065Spjd#endif 1357166065Spjd#ifdef ELOOP 1358166065Spjd case ELOOP: 1359166065Spjd return ("ELOOP"); 1360166065Spjd#endif 1361166065Spjd#ifdef ENAMETOOLONG 1362166065Spjd case ENAMETOOLONG: 1363166065Spjd return ("ENAMETOOLONG"); 1364166065Spjd#endif 1365166065Spjd#ifdef EHOSTDOWN 1366166065Spjd case EHOSTDOWN: 1367166065Spjd return ("EHOSTDOWN"); 1368166065Spjd#endif 1369166065Spjd#ifdef EHOSTUNREACH 1370166065Spjd case EHOSTUNREACH: 1371166065Spjd return ("EHOSTUNREACH"); 1372166065Spjd#endif 1373166065Spjd#ifdef ENOTEMPTY 1374166065Spjd case ENOTEMPTY: 1375166065Spjd return ("ENOTEMPTY"); 1376166065Spjd#endif 1377166065Spjd#ifdef EPROCLIM 1378166065Spjd case EPROCLIM: 1379166065Spjd return ("EPROCLIM"); 1380166065Spjd#endif 1381166065Spjd#ifdef EUSERS 1382166065Spjd case EUSERS: 1383166065Spjd return ("EUSERS"); 1384166065Spjd#endif 1385166065Spjd#ifdef EDQUOT 1386166065Spjd case EDQUOT: 1387166065Spjd return ("EDQUOT"); 1388166065Spjd#endif 1389166065Spjd#ifdef ESTALE 1390166065Spjd case ESTALE: 1391166065Spjd return ("ESTALE"); 1392166065Spjd#endif 1393166065Spjd#ifdef EREMOTE 1394166065Spjd case EREMOTE: 1395166065Spjd return ("EREMOTE"); 1396166065Spjd#endif 1397166065Spjd#ifdef EBADRPC 1398166065Spjd case EBADRPC: 1399166065Spjd return ("EBADRPC"); 1400166065Spjd#endif 1401166065Spjd#ifdef ERPCMISMATCH 1402166065Spjd case ERPCMISMATCH: 1403166065Spjd return ("ERPCMISMATCH"); 1404166065Spjd#endif 1405166065Spjd#ifdef EPROGUNAVAIL 1406166065Spjd case EPROGUNAVAIL: 1407166065Spjd return ("EPROGUNAVAIL"); 1408166065Spjd#endif 1409166065Spjd#ifdef EPROGMISMATCH 1410166065Spjd case EPROGMISMATCH: 1411166065Spjd return ("EPROGMISMATCH"); 1412166065Spjd#endif 1413166065Spjd#ifdef EPROCUNAVAIL 1414166065Spjd case EPROCUNAVAIL: 1415166065Spjd return ("EPROCUNAVAIL"); 1416166065Spjd#endif 1417166065Spjd#ifdef ENOLCK 1418166065Spjd case ENOLCK: 1419166065Spjd return ("ENOLCK"); 1420166065Spjd#endif 1421166065Spjd#ifdef ENOSYS 1422166065Spjd case ENOSYS: 1423166065Spjd return ("ENOSYS"); 1424166065Spjd#endif 1425166065Spjd#ifdef EFTYPE 1426166065Spjd case EFTYPE: 1427166065Spjd return ("EFTYPE"); 1428166065Spjd#endif 1429166065Spjd#ifdef EAUTH 1430166065Spjd case EAUTH: 1431166065Spjd return ("EAUTH"); 1432166065Spjd#endif 1433166065Spjd#ifdef ENEEDAUTH 1434166065Spjd case ENEEDAUTH: 1435166065Spjd return ("ENEEDAUTH"); 1436166065Spjd#endif 1437166065Spjd#ifdef EIDRM 1438166065Spjd case EIDRM: 1439166065Spjd return ("EIDRM"); 1440166065Spjd#endif 1441166065Spjd#ifdef ENOMSG 1442166065Spjd case ENOMSG: 1443166065Spjd return ("ENOMSG"); 1444166065Spjd#endif 1445166065Spjd#ifdef EOVERFLOW 1446166065Spjd case EOVERFLOW: 1447166065Spjd return ("EOVERFLOW"); 1448166065Spjd#endif 1449166065Spjd#ifdef ECANCELED 1450166065Spjd case ECANCELED: 1451166065Spjd return ("ECANCELED"); 1452166065Spjd#endif 1453166065Spjd#ifdef EILSEQ 1454166065Spjd case EILSEQ: 1455166065Spjd return ("EILSEQ"); 1456166065Spjd#endif 1457166065Spjd#ifdef ENOATTR 1458166065Spjd case ENOATTR: 1459166065Spjd return ("ENOATTR"); 1460166065Spjd#endif 1461166065Spjd#ifdef EDOOFUS 1462166065Spjd case EDOOFUS: 1463166065Spjd return ("EDOOFUS"); 1464166065Spjd#endif 1465166065Spjd#ifdef EBADMSG 1466166065Spjd case EBADMSG: 1467166065Spjd return ("EBADMSG"); 1468166065Spjd#endif 1469166065Spjd#ifdef EMULTIHOP 1470166065Spjd case EMULTIHOP: 1471166065Spjd return ("EMULTIHOP"); 1472166065Spjd#endif 1473166065Spjd#ifdef ENOLINK 1474166065Spjd case ENOLINK: 1475166065Spjd return ("ENOLINK"); 1476166065Spjd#endif 1477166065Spjd#ifdef EPROTO 1478166065Spjd case EPROTO: 1479166065Spjd return ("EPROTO"); 1480166065Spjd#endif 1481166065Spjd default: 1482166065Spjd snprintf(errnum, sizeof(errnum), "%d", error); 1483166065Spjd return (errnum); 1484166065Spjd } 1485166065Spjd} 1486