2 * Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 /* Needs to be first to twiddle appropriate system configuration/HAVE_* flags */
32 #include <sys/param.h>
36 #ifdef HAVE_SYS_MKDEV_H
37 #include <sys/mkdev.h>
40 #include <sys/socket.h>
58 typedef struct stat64 stat_t;
60 typedef struct stat stat_t;
64 #define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
105 #ifdef HAVE_CONNECTAT
126 #ifdef HAVE_CHFLAGSAT
134 #ifdef HAVE_POSIX_FALLOCATE
135 ACTION_POSIX_FALLOCATE,
143 #ifdef HAVE_LPATHCONF
146 #ifdef HAS_NFSV4_ACL_SUPPORT
151 #ifdef HAVE_UTIMENSAT
156 #define TYPE_NONE 0x0000
157 #define TYPE_STRING 0x0001
158 #define TYPE_NUMBER 0x0002
159 #define TYPE_DESCRIPTOR 0x0003
160 #define TYPE_MASK 0x000f
162 #define TYPE_OPTIONAL 0x0100
166 struct syscall_desc {
168 enum action sd_action;
169 int sd_args[MAX_ARGS];
172 static struct syscall_desc syscalls[] = {
173 { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
175 { "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
177 { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
178 { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } },
180 { "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
182 { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
184 { "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
186 { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } },
187 { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
189 { "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
191 { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
192 #ifdef HAVE_SYMLINKAT
193 { "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
195 { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
197 { "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
199 { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
201 { "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
203 { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
205 { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
207 { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } },
209 { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
211 { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } },
212 #ifdef HAVE_CONNECTAT
213 { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
215 { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
216 { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
218 { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
221 { "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
223 { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
224 { "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
225 { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
227 { "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
230 { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
233 { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
235 #ifdef HAVE_CHFLAGSAT
236 { "chflagsat", ACTION_CHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
239 { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
241 { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
242 { "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
243 #ifdef HAVE_POSIX_FALLOCATE
244 { "posix_fallocate", ACTION_POSIX_FALLOCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
246 { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
247 { "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
248 { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
250 { "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
252 { "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
253 { "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
254 #ifdef HAVE_LPATHCONF
255 { "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
257 #ifdef HAS_NFSV4_ACL_SUPPORT
258 { "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
259 { "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } },
261 { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
262 #ifdef HAVE_UTIMENSAT
263 { "utimensat", ACTION_UTIMENSAT, {
264 TYPE_DESCRIPTOR, /* Directory */
265 TYPE_STRING, /* Relative path */
266 TYPE_NUMBER, /* atime seconds */
267 TYPE_STRING, /* atime nanoseconds */
268 TYPE_NUMBER, /* mtime seconds */
269 TYPE_STRING, /* mtime nanoseconds */
270 TYPE_STRING, /* flags */}},
272 { NULL, -1, { TYPE_NONE } }
280 static struct flag open_flags[] = {
282 { O_RDONLY, "O_RDONLY" },
285 { O_WRONLY, "O_WRONLY" },
288 { O_RDWR, "O_RDWR" },
291 { O_NONBLOCK, "O_NONBLOCK" },
294 { O_APPEND, "O_APPEND" },
297 { O_CREAT, "O_CREAT" },
300 { O_TRUNC, "O_TRUNC" },
303 { O_EXCL, "O_EXCL" },
306 { O_SHLOCK, "O_SHLOCK" },
309 { O_EXLOCK, "O_EXLOCK" },
312 { O_DIRECT, "O_DIRECT" },
315 { O_FSYNC, "O_FSYNC" },
318 { O_SYNC, "O_SYNC" },
321 { O_NOFOLLOW, "O_NOFOLLOW" },
324 { O_NOCTTY, "O_NOCTTY" },
327 { O_DIRECTORY, "O_DIRECTORY" },
333 static struct flag chflags_flags[] = {
335 { UF_NODUMP, "UF_NODUMP" },
338 { UF_IMMUTABLE, "UF_IMMUTABLE" },
341 { UF_APPEND, "UF_APPEND" },
344 { UF_NOUNLINK, "UF_NOUNLINK" },
347 { UF_OPAQUE, "UF_OPAQUE" },
350 { SF_ARCHIVED, "SF_ARCHIVED" },
353 { SF_IMMUTABLE, "SF_IMMUTABLE" },
356 { SF_APPEND, "SF_APPEND" },
359 { SF_NOUNLINK, "SF_NOUNLINK" },
362 { SF_SNAPSHOT, "SF_SNAPSHOT" },
369 static struct flag unlinkat_flags[] = {
370 { AT_REMOVEDIR, "AT_REMOVEDIR" },
376 static struct flag linkat_flags[] = {
377 #ifdef AT_SYMLINK_FOLLOW
378 { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" },
384 #ifdef HAVE_CHFLAGSAT
385 static struct flag chflagsat_flags[] = {
386 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
392 static struct flag fchmodat_flags[] = {
393 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
399 static struct flag fchownat_flags[] = {
400 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
406 static struct flag fstatat_flags[] = {
407 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
417 static struct name pathconf_names[] = {
419 { _PC_LINK_MAX, "_PC_LINK_MAX" },
422 { _PC_NAME_MAX, "_PC_NAME_MAX" },
425 { _PC_PATH_MAX, "_PC_PATH_MAX" },
427 #ifdef _PC_SYMLINK_MAX
428 { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" },
433 static const char *err2str(int error);
435 static int *descriptors;
436 static int ndescriptors;
442 fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n");
447 str2flags(struct flag *tflags, char *sflags)
453 /* 'none' or '0' means no flags */
454 if (strcmp(sflags, "none") == 0 || strcmp(sflags, "0") == 0)
456 for (f = strtok(sflags, ",|"); f != NULL; f = strtok(NULL, ",|")) {
457 for (i = 0; tflags[i].f_str != NULL; i++) {
458 if (strcmp(tflags[i].f_str, f) == 0)
461 if (tflags[i].f_str == NULL) {
462 fprintf(stderr, "unknown flag '%s'\n", f);
465 flags |= tflags[i].f_flag;
472 flags2str(struct flag *tflags, long long flags)
474 static char sflags[1024];
478 for (i = 0; tflags[i].f_str != NULL; i++) {
479 if (flags & tflags[i].f_flag) {
480 if (sflags[0] != '\0')
481 strlcat(sflags, ",", sizeof(sflags));
482 strlcat(sflags, tflags[i].f_str, sizeof(sflags));
485 if (sflags[0] == '\0')
486 strlcpy(sflags, "none", sizeof(sflags));
492 str2name(struct name *names, char *name)
496 for (i = 0; names[i].n_str != NULL; i++) {
497 if (strcmp(names[i].n_str, name) == 0)
498 return (names[i].n_name);
503 static struct syscall_desc *
504 find_syscall(const char *name)
508 for (i = 0; syscalls[i].sd_name != NULL; i++) {
509 if (strcmp(syscalls[i].sd_name, name) == 0)
510 return (&syscalls[i]);
516 show_stat(stat_t *sp, const char *what)
519 if (strcmp(what, "mode") == 0)
520 printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS));
521 else if (strcmp(what, "inode") == 0)
522 printf("%lld", (long long)sp->st_ino);
523 else if (strcmp(what, "nlink") == 0)
524 printf("%lld", (long long)sp->st_nlink);
525 else if (strcmp(what, "uid") == 0)
526 printf("%d", (int)sp->st_uid);
527 else if (strcmp(what, "gid") == 0)
528 printf("%d", (int)sp->st_gid);
529 else if (strcmp(what, "size") == 0)
530 printf("%lld", (long long)sp->st_size);
531 else if (strcmp(what, "blocks") == 0)
532 printf("%lld", (long long)sp->st_blocks);
533 else if (strcmp(what, "atime") == 0)
534 printf("%lld", (long long)sp->st_atime);
535 #if defined(HAVE_STRUCT_STAT_ST_ATIM) || \
536 defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
537 else if (strcmp(what, "atime_ns") == 0)
538 #ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC
539 printf("%lld", (long long)sp->st_atimespec.tv_nsec);
541 printf("%lld", (long long)sp->st_atim.tv_nsec);
543 #endif /* st_atim* */
544 else if (strcmp(what, "ctime") == 0)
545 printf("%lld", (long long)sp->st_ctime);
546 #if defined(HAVE_STRUCT_STAT_ST_CTIM) || \
547 defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
548 else if (strcmp(what, "ctime_ns") == 0)
549 #ifdef HAVE_STRUCT_STAT_ST_CTIMESPEC
550 printf("%lld", (long long)sp->st_ctimespec.tv_nsec);
552 printf("%lld", (long long)sp->st_ctim.tv_nsec);
554 #endif /* st_ctim* */
555 else if (strcmp(what, "mtime") == 0)
556 printf("%lld", (long long)sp->st_mtime);
557 else if (strcmp(what, "mtime_ns") == 0)
558 #if defined(HAVE_STRUCT_STAT_ST_MTIM) || \
559 defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
560 #ifdef HAVE_STRUCT_STAT_ST_MTIMESPEC
561 printf("%lld", (long long)sp->st_mtimespec.tv_nsec);
563 printf("%lld", (long long)sp->st_mtim.tv_nsec);
565 #endif /* st_mtim* */
566 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
567 else if (strcmp(what, "birthtime") == 0)
568 printf("%lld", (long long)sp->st_birthtime);
569 #endif /* st_birthtime */
570 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIM) || \
571 defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
572 else if (strcmp(what, "birthtime_ns") == 0)
573 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC
574 printf("%lld", (long long)sp->st_birthtimespec.tv_nsec);
576 printf("%lld", (long long)sp->st_birthtim.tv_nsec);
578 #endif /* st_birthtim{,espec} */
580 else if (strcmp(what, "flags") == 0)
581 printf("%s", flags2str(chflags_flags, (long long)sp->st_flags));
583 else if (strcmp(what, "major") == 0)
584 printf("%u", (unsigned int)major(sp->st_rdev));
585 else if (strcmp(what, "minor") == 0)
586 printf("%u", (unsigned int)minor(sp->st_rdev));
587 else if (strcmp(what, "type") == 0) {
588 switch (sp->st_mode & S_IFMT) {
620 show_stats(stat_t *sp, char *what)
625 for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) {
634 descriptor_add(int fd)
638 if (descriptors == NULL) {
639 descriptors = malloc(sizeof(descriptors[0]) * ndescriptors);
641 descriptors = realloc(descriptors,
642 sizeof(descriptors[0]) * ndescriptors);
644 assert(descriptors != NULL);
645 descriptors[ndescriptors - 1] = fd;
649 descriptor_get(int pos)
652 if (pos < 0 || pos >= ndescriptors) {
653 fprintf(stderr, "invalid descriptor %d\n", pos);
657 return (descriptors[pos]);
661 call_syscall(struct syscall_desc *scall, char *argv[])
664 #ifdef HAVE_UTIMENSAT
665 struct timespec times[2];
676 #ifdef HAS_NFSV4_ACL_SUPPORT
677 int entry_id = ACL_FIRST_ENTRY;
679 acl_entry_t entry, newentry;
683 * Verify correctness of the arguments.
685 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
686 if (scall->sd_args[i] == TYPE_NONE) {
687 if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
689 fprintf(stderr, "too many arguments [%s]\n", argv[i]);
692 if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
693 if (scall->sd_args[i] & TYPE_OPTIONAL)
695 fprintf(stderr, "too few arguments\n");
698 if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
699 if (strcmp(argv[i], "NULL") == 0)
701 else if (strcmp(argv[i], "DEADCODE") == 0)
702 args[i].str = (void *)0xdeadc0de;
704 args[i].str = argv[i];
705 } else if ((scall->sd_args[i] & TYPE_MASK) ==
707 args[i].num = strtoll(argv[i], &endp, 0);
709 !isspace((unsigned char)*endp)) {
711 "invalid argument %u, number expected [%s]\n",
715 } else if ((scall->sd_args[i] & TYPE_MASK) ==
717 if (strcmp(argv[i], "AT_FDCWD") == 0) {
718 args[i].num = AT_FDCWD;
719 } else if (strcmp(argv[i], "BADFD") == 0) {
720 /* In case AT_FDCWD is -1 on some systems... */
728 pos = strtoll(argv[i], &endp, 0);
730 !isspace((unsigned char)*endp)) {
732 "invalid argument %u, number expected [%s]\n",
736 args[i].num = descriptor_get(pos);
742 * Call the given syscall.
744 #define NUM(n) (args[(n)].num)
745 #define STR(n) (args[(n)].str)
746 switch (scall->sd_action) {
748 flags = str2flags(open_flags, STR(1));
749 if (flags & O_CREAT) {
751 fprintf(stderr, "too few arguments\n");
754 rval = open(STR(0), (int)flags, (mode_t)NUM(2));
757 fprintf(stderr, "too many arguments\n");
760 rval = open(STR(0), (int)flags);
763 descriptor_add(rval);
767 flags = str2flags(open_flags, STR(2));
768 if (flags & O_CREAT) {
770 fprintf(stderr, "too few arguments\n");
773 rval = openat(NUM(0), STR(1), (int)flags,
777 fprintf(stderr, "too many arguments\n");
780 rval = openat(NUM(0), STR(1), (int)flags);
783 descriptor_add(rval);
787 rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
792 rval = unlink(STR(0));
795 case ACTION_UNLINKAT:
796 rval = unlinkat(NUM(0), STR(1),
797 (int)str2flags(unlinkat_flags, STR(2)));
801 rval = mkdir(STR(0), (mode_t)NUM(1));
805 rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
809 rval = rmdir(STR(0));
812 rval = link(STR(0), STR(1));
816 rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
817 (int)str2flags(linkat_flags, STR(4)));
821 rval = symlink(STR(0), STR(1));
823 #ifdef HAVE_SYMLINKAT
824 case ACTION_SYMLINKAT:
825 rval = symlinkat(STR(0), NUM(1), STR(2));
829 rval = rename(STR(0), STR(1));
832 case ACTION_RENAMEAT:
833 rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
837 rval = mkfifo(STR(0), (mode_t)NUM(1));
840 case ACTION_MKFIFOAT:
841 rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
853 switch (scall->sd_action) {
866 dev = makedev(NUM(fa + 3), NUM(fa + 4));
867 if (strcmp(STR(fa + 1), "c") == 0) /* character device */
869 else if (strcmp(STR(fa + 1), "b") == 0) /* block device */
871 else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */
873 else if (strcmp(STR(fa + 1), "d") == 0) /* directory */
875 else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */
878 fprintf(stderr, "wrong argument 1\n");
881 switch (scall->sd_action) {
883 rval = mknod(STR(0), ntype | NUM(2), dev);
887 rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
897 struct sockaddr_un sunx;
899 sunx.sun_family = AF_UNIX;
900 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
901 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
902 rval = socket(AF_UNIX, SOCK_STREAM, 0);
905 rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
911 struct sockaddr_un sunx;
913 sunx.sun_family = AF_UNIX;
914 strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
915 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
916 rval = socket(AF_UNIX, SOCK_STREAM, 0);
919 rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
926 struct sockaddr_un sunx;
928 sunx.sun_family = AF_UNIX;
929 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
930 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
931 rval = socket(AF_UNIX, SOCK_STREAM, 0);
934 rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
937 #ifdef HAVE_CONNECTAT
938 case ACTION_CONNECTAT:
940 struct sockaddr_un sunx;
942 sunx.sun_family = AF_UNIX;
943 strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
944 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
945 rval = socket(AF_UNIX, SOCK_STREAM, 0);
948 rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
954 rval = chmod(STR(0), (mode_t)NUM(1));
957 rval = fchmod(NUM(0), (mode_t)NUM(1));
961 rval = lchmod(STR(0), (mode_t)NUM(1));
965 case ACTION_FCHMODAT:
966 rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
967 str2flags(fchmodat_flags, STR(3)));
971 rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
974 rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
977 rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
980 case ACTION_FCHOWNAT:
981 rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
982 (int)str2flags(fchownat_flags, STR(4)));
987 rval = chflags(STR(0),
988 (unsigned long)str2flags(chflags_flags, STR(1)));
992 case ACTION_FCHFLAGS:
993 rval = fchflags(NUM(0),
994 (unsigned long)str2flags(chflags_flags, STR(1)));
997 #ifdef HAVE_CHFLAGSAT
998 case ACTION_CHFLAGSAT:
999 rval = chflagsat(NUM(0), STR(1),
1000 (unsigned long)str2flags(chflags_flags, STR(2)),
1001 (int)str2flags(chflagsat_flags, STR(3)));
1004 #ifdef HAVE_LCHFLAGS
1005 case ACTION_LCHFLAGS:
1006 rval = lchflags(STR(0),
1007 (unsigned long)str2flags(chflags_flags, STR(1)));
1010 case ACTION_TRUNCATE:
1012 rval = truncate64(STR(0), NUM(1));
1014 rval = truncate(STR(0), NUM(1));
1017 case ACTION_FTRUNCATE:
1019 rval = ftruncate64(NUM(0), NUM(1));
1021 rval = ftruncate(NUM(0), NUM(1));
1024 #ifdef HAVE_POSIX_FALLOCATE
1025 case ACTION_POSIX_FALLOCATE:
1026 rval = posix_fallocate(NUM(0), NUM(1), NUM(2));
1035 rval = stat64(STR(0), &sb);
1037 rval = stat(STR(0), &sb);
1040 show_stats(&sb, STR(1));
1046 rval = fstat64(NUM(0), &sb);
1048 rval = fstat(NUM(0), &sb);
1051 show_stats(&sb, STR(1));
1057 rval = lstat64(STR(0), &sb);
1059 rval = lstat(STR(0), &sb);
1062 show_stats(&sb, STR(1));
1067 case ACTION_FSTATAT:
1068 rval = fstatat(NUM(0), STR(1), &sb,
1069 (int)str2flags(fstatat_flags, STR(2)));
1071 show_stats(&sb, STR(3));
1076 case ACTION_PATHCONF:
1077 case ACTION_FPATHCONF:
1078 #ifdef HAVE_LPATHCONF
1079 case ACTION_LPATHCONF:
1084 name = str2name(pathconf_names, STR(1));
1086 fprintf(stderr, "unknown name %s", STR(1));
1090 switch (scall->sd_action) {
1091 case ACTION_PATHCONF:
1092 lrval = pathconf(STR(0), name);
1094 case ACTION_FPATHCONF:
1095 lrval = fpathconf(NUM(0), name);
1097 #ifdef HAVE_LPATHCONF
1098 case ACTION_LPATHCONF:
1099 lrval = lpathconf(STR(0), name);
1105 if (lrval == -1 && errno == 0) {
1106 printf("unlimited\n");
1108 } else if (lrval >= 0) {
1109 printf("%ld\n", lrval);
1115 #ifdef HAS_NFSV4_ACL_SUPPORT
1116 case ACTION_PREPENDACL:
1119 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
1123 newacl = acl_from_text(STR(1));
1127 while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
1128 entry_id = ACL_NEXT_ENTRY;
1130 if (acl_create_entry_np(&acl, &entry, 0))
1133 if (acl_copy_entry(entry, newentry))
1137 rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
1139 case ACTION_READACL:
1140 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
1148 rval = write(NUM(0), STR(1), strlen(STR(1)));
1150 #ifdef HAVE_UTIMENSAT
1151 case ACTION_UTIMENSAT:
1152 times[0].tv_sec = NUM(2);
1153 if (strcmp(STR(3), "UTIME_NOW") == 0)
1154 times[0].tv_nsec = UTIME_NOW;
1155 else if (strcmp(STR(3), "UTIME_OMIT") == 0)
1156 times[0].tv_nsec = UTIME_OMIT;
1158 times[0].tv_nsec = strtol(STR(3), NULL, 10);
1159 times[1].tv_sec = NUM(4);
1160 if (strcmp(STR(5), "UTIME_NOW") == 0)
1161 times[1].tv_nsec = UTIME_NOW;
1162 else if (strcmp(STR(5), "UTIME_OMIT") == 0)
1163 times[1].tv_nsec = UTIME_OMIT;
1165 times[1].tv_nsec = strtol(STR(5), NULL, 10);
1166 if (strcmp(STR(6), "AT_SYMLINK_NOFOLLOW") == 0)
1167 flag = AT_SYMLINK_NOFOLLOW;
1169 flag = strtol(STR(6), NULL, 10);
1170 rval = utimensat(NUM(0), STR(1), times, flag);
1174 fprintf(stderr, "unsupported syscall\n");
1182 serrno = err2str(errno);
1183 fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
1184 printf("%s\n", serrno);
1192 set_gids(char *gids)
1199 ngroups = sysconf(_SC_NGROUPS_MAX);
1200 assert(ngroups > 0);
1201 gidset = malloc(sizeof(*gidset) * ngroups);
1202 assert(gidset != NULL);
1203 for (i = 0, g = strtok(gids, ","); g != NULL;
1204 g = strtok(NULL, ","), i++) {
1205 if ((long)i >= ngroups) {
1206 fprintf(stderr, "too many gids\n");
1209 gidset[i] = strtol(g, &endp, 0);
1210 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1211 fprintf(stderr, "invalid gid '%s' - number expected\n",
1216 if (setgroups(i, gidset) < 0) {
1217 fprintf(stderr, "cannot change groups: %s\n", strerror(errno));
1220 if (setegid(gidset[0]) < 0) {
1221 fprintf(stderr, "cannot change effective gid: %s\n",
1229 main(int argc, char *argv[])
1231 struct syscall_desc *scall;
1240 while ((ch = getopt(argc, argv, "g:u:U:")) != -1) {
1246 uid = (int)strtol(optarg, &endp, 0);
1247 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1248 fprintf(stderr, "invalid uid '%s' - number "
1249 "expected\n", optarg);
1254 umsk = (int)strtol(optarg, &endp, 0);
1255 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1256 fprintf(stderr, "invalid umask '%s' - number "
1257 "expected\n", optarg);
1269 fprintf(stderr, "too few arguments\n");
1274 fprintf(stderr, "changing groups to %s\n", gids);
1278 fprintf(stderr, "changing uid to %d\n", uid);
1279 if (setuid(uid) < 0) {
1280 fprintf(stderr, "cannot change uid: %s\n",
1286 /* Change umask to requested value or to 0, if not requested. */
1290 scall = find_syscall(argv[0]);
1291 if (scall == NULL) {
1292 fprintf(stderr, "syscall '%s' not supported\n",
1298 n = call_syscall(scall, argv);
1301 if (argv[0] == NULL)
1313 static char errnum[8];
1458 return ("EINPROGRESS");
1462 return ("EALREADY");
1466 return ("ENOTSOCK");
1470 return ("EDESTADDRREQ");
1474 return ("EMSGSIZE");
1478 return ("EPROTOTYPE");
1482 return ("ENOPROTOOPT");
1484 #ifdef EPROTONOSUPPORT
1485 case EPROTONOSUPPORT:
1486 return ("EPROTONOSUPPORT");
1488 #ifdef ESOCKTNOSUPPORT
1489 case ESOCKTNOSUPPORT:
1490 return ("ESOCKTNOSUPPORT");
1494 return ("EOPNOTSUPP");
1498 return ("EPFNOSUPPORT");
1502 return ("EAFNOSUPPORT");
1506 return ("EADDRINUSE");
1508 #ifdef EADDRNOTAVAIL
1510 return ("EADDRNOTAVAIL");
1514 return ("ENETDOWN");
1518 return ("ENETUNREACH");
1522 return ("ENETRESET");
1526 return ("ECONNABORTED");
1530 return ("ECONNRESET");
1542 return ("ENOTCONN");
1546 return ("ESHUTDOWN");
1550 return ("ETOOMANYREFS");
1554 return ("ETIMEDOUT");
1558 return ("ECONNREFUSED");
1566 return ("ENAMETOOLONG");
1570 return ("EHOSTDOWN");
1574 return ("EHOSTUNREACH");
1578 return ("ENOTEMPTY");
1582 return ("EPROCLIM");
1606 return ("ERPCMISMATCH");
1610 return ("EPROGUNAVAIL");
1612 #ifdef EPROGMISMATCH
1614 return ("EPROGMISMATCH");
1618 return ("EPROCUNAVAIL");
1638 return ("ENEEDAUTH");
1650 return ("EOVERFLOW");
1654 return ("ECANCELED");
1674 return ("EMULTIHOP");
1685 snprintf(errnum, sizeof(errnum), "%d", error);