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 #include <sys/param.h>
30 #include <sys/types.h>
32 #include <sys/socket.h>
35 #include <sys/mkdev.h>
48 #ifndef HAS_TRUNCATE64
49 #define truncate64 truncate
50 #define ftruncate64 ftruncate
57 #ifdef HAS_FREEBSD_ACL
62 #define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
125 #ifdef HAS_FREEBSD_ACL
132 #define TYPE_NONE 0x0000
133 #define TYPE_STRING 0x0001
134 #define TYPE_NUMBER 0x0002
135 #define TYPE_DESCRIPTOR 0x0003
136 #define TYPE_MASK 0x000f
138 #define TYPE_OPTIONAL 0x0100
142 struct syscall_desc {
144 enum action sd_action;
145 int sd_args[MAX_ARGS];
148 static struct syscall_desc syscalls[] = {
149 { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
150 { "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
151 { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
152 { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } },
153 { "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
154 { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
155 { "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
156 { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } },
157 { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
158 { "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
159 { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
160 { "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
161 { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
162 { "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
163 { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
164 { "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
165 { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
166 { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
167 { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } },
169 { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
171 { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } },
173 { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
175 { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
176 { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
178 { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
180 { "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
181 { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
182 { "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
183 { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
184 { "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
186 { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
189 { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
192 { "chflagsat", ACTION_CHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
195 { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
197 { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
198 { "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
199 { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
200 { "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
201 { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
202 { "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
203 { "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
204 { "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
206 { "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
208 #ifdef HAS_FREEBSD_ACL
209 { "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
210 { "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } },
212 { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
213 { NULL, -1, { TYPE_NONE } }
221 static struct flag open_flags[] = {
223 { O_RDONLY, "O_RDONLY" },
226 { O_WRONLY, "O_WRONLY" },
229 { O_RDWR, "O_RDWR" },
232 { O_NONBLOCK, "O_NONBLOCK" },
235 { O_APPEND, "O_APPEND" },
238 { O_CREAT, "O_CREAT" },
241 { O_TRUNC, "O_TRUNC" },
244 { O_EXCL, "O_EXCL" },
247 { O_SHLOCK, "O_SHLOCK" },
250 { O_EXLOCK, "O_EXLOCK" },
253 { O_DIRECT, "O_DIRECT" },
256 { O_FSYNC, "O_FSYNC" },
259 { O_SYNC, "O_SYNC" },
262 { O_NOFOLLOW, "O_NOFOLLOW" },
265 { O_NOCTTY, "O_NOCTTY" },
268 { O_DIRECTORY, "O_DIRECTORY" },
274 static struct flag chflags_flags[] = {
276 { UF_NODUMP, "UF_NODUMP" },
279 { UF_IMMUTABLE, "UF_IMMUTABLE" },
282 { UF_APPEND, "UF_APPEND" },
285 { UF_NOUNLINK, "UF_NOUNLINK" },
288 { UF_OPAQUE, "UF_OPAQUE" },
291 { SF_ARCHIVED, "SF_ARCHIVED" },
294 { SF_IMMUTABLE, "SF_IMMUTABLE" },
297 { SF_APPEND, "SF_APPEND" },
300 { SF_NOUNLINK, "SF_NOUNLINK" },
303 { SF_SNAPSHOT, "SF_SNAPSHOT" },
309 static struct flag unlinkat_flags[] = {
310 { AT_REMOVEDIR, "AT_REMOVEDIR" },
314 static struct flag linkat_flags[] = {
315 { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" },
319 static struct flag chflagsat_flags[] = {
320 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
324 static struct flag fchmodat_flags[] = {
325 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
329 static struct flag fchownat_flags[] = {
330 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
334 static struct flag fstatat_flags[] = {
335 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
344 static struct name pathconf_names[] = {
346 { _PC_LINK_MAX, "_PC_LINK_MAX" },
349 { _PC_NAME_MAX, "_PC_NAME_MAX" },
352 { _PC_PATH_MAX, "_PC_PATH_MAX" },
354 #ifdef _PC_SYMLINK_MAX
355 { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" },
360 static const char *err2str(int error);
362 static int *descriptors;
363 static int ndescriptors;
369 fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n");
374 str2flags(struct flag *tflags, char *sflags)
380 /* 'none' or '0' means no flags */
381 if (strcmp(sflags, "none") == 0 || strcmp(sflags, "0") == 0)
383 for (f = strtok(sflags, ",|"); f != NULL; f = strtok(NULL, ",|")) {
384 for (i = 0; tflags[i].f_str != NULL; i++) {
385 if (strcmp(tflags[i].f_str, f) == 0)
388 if (tflags[i].f_str == NULL) {
389 fprintf(stderr, "unknown flag '%s'\n", f);
392 flags |= tflags[i].f_flag;
399 flags2str(struct flag *tflags, long long flags)
401 static char sflags[1024];
405 for (i = 0; tflags[i].f_str != NULL; i++) {
406 if (flags & tflags[i].f_flag) {
407 if (sflags[0] != '\0')
408 strlcat(sflags, ",", sizeof(sflags));
409 strlcat(sflags, tflags[i].f_str, sizeof(sflags));
412 if (sflags[0] == '\0')
413 strlcpy(sflags, "none", sizeof(sflags));
419 str2name(struct name *names, char *name)
423 for (i = 0; names[i].n_str != NULL; i++) {
424 if (strcmp(names[i].n_str, name) == 0)
425 return (names[i].n_name);
430 static struct syscall_desc *
431 find_syscall(const char *name)
435 for (i = 0; syscalls[i].sd_name != NULL; i++) {
436 if (strcmp(syscalls[i].sd_name, name) == 0)
437 return (&syscalls[i]);
443 show_stat(struct stat64 *sp, const char *what)
446 if (strcmp(what, "mode") == 0)
447 printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS));
448 else if (strcmp(what, "inode") == 0)
449 printf("%lld", (long long)sp->st_ino);
450 else if (strcmp(what, "nlink") == 0)
451 printf("%lld", (long long)sp->st_nlink);
452 else if (strcmp(what, "uid") == 0)
453 printf("%d", (int)sp->st_uid);
454 else if (strcmp(what, "gid") == 0)
455 printf("%d", (int)sp->st_gid);
456 else if (strcmp(what, "size") == 0)
457 printf("%lld", (long long)sp->st_size);
458 else if (strcmp(what, "blocks") == 0)
459 printf("%lld", (long long)sp->st_blocks);
460 else if (strcmp(what, "atime") == 0)
461 printf("%lld", (long long)sp->st_atime);
462 else if (strcmp(what, "mtime") == 0)
463 printf("%lld", (long long)sp->st_mtime);
464 else if (strcmp(what, "ctime") == 0)
465 printf("%lld", (long long)sp->st_ctime);
467 else if (strcmp(what, "flags") == 0)
468 printf("%s", flags2str(chflags_flags, (long long)sp->st_flags));
470 else if (strcmp(what, "major") == 0)
471 printf("%u", (unsigned int)major(sp->st_rdev));
472 else if (strcmp(what, "minor") == 0)
473 printf("%u", (unsigned int)minor(sp->st_rdev));
474 else if (strcmp(what, "type") == 0) {
475 switch (sp->st_mode & S_IFMT) {
507 show_stats(struct stat64 *sp, char *what)
512 for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) {
521 descriptor_add(int fd)
525 if (descriptors == NULL) {
526 descriptors = malloc(sizeof(descriptors[0]) * ndescriptors);
528 descriptors = realloc(descriptors,
529 sizeof(descriptors[0]) * ndescriptors);
531 assert(descriptors != NULL);
532 descriptors[ndescriptors - 1] = fd;
536 descriptor_get(int pos)
539 if (pos < 0 || pos >= ndescriptors) {
540 fprintf(stderr, "invalid descriptor %d\n", pos);
544 return (descriptors[pos]);
548 call_syscall(struct syscall_desc *scall, char *argv[])
559 #ifdef HAS_FREEBSD_ACL
560 int entry_id = ACL_FIRST_ENTRY;
562 acl_entry_t entry, newentry;
566 * Verify correctness of the arguments.
568 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
569 if (scall->sd_args[i] == TYPE_NONE) {
570 if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
572 fprintf(stderr, "too many arguments [%s]\n", argv[i]);
575 if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
576 if (scall->sd_args[i] & TYPE_OPTIONAL)
578 fprintf(stderr, "too few arguments\n");
581 if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
582 if (strcmp(argv[i], "NULL") == 0)
584 else if (strcmp(argv[i], "DEADCODE") == 0)
585 args[i].str = (void *)0xdeadc0de;
587 args[i].str = argv[i];
588 } else if ((scall->sd_args[i] & TYPE_MASK) ==
590 args[i].num = strtoll(argv[i], &endp, 0);
592 !isspace((unsigned char)*endp)) {
594 "invalid argument %u, number expected [%s]\n",
598 } else if ((scall->sd_args[i] & TYPE_MASK) ==
600 if (strcmp(argv[i], "AT_FDCWD") == 0) {
601 args[i].num = AT_FDCWD;
602 } else if (strcmp(argv[i], "BADFD") == 0) {
603 /* In case AT_FDCWD is -1 on some systems... */
611 pos = strtoll(argv[i], &endp, 0);
613 !isspace((unsigned char)*endp)) {
615 "invalid argument %u, number expected [%s]\n",
619 args[i].num = descriptor_get(pos);
625 * Call the given syscall.
627 #define NUM(n) (args[(n)].num)
628 #define STR(n) (args[(n)].str)
629 switch (scall->sd_action) {
631 flags = str2flags(open_flags, STR(1));
632 if (flags & O_CREAT) {
634 fprintf(stderr, "too few arguments\n");
637 rval = open(STR(0), (int)flags, (mode_t)NUM(2));
640 fprintf(stderr, "too many arguments\n");
643 rval = open(STR(0), (int)flags);
646 descriptor_add(rval);
649 flags = str2flags(open_flags, STR(2));
650 if (flags & O_CREAT) {
652 fprintf(stderr, "too few arguments\n");
655 rval = openat(NUM(0), STR(1), (int)flags,
659 fprintf(stderr, "too many arguments\n");
662 rval = openat(NUM(0), STR(1), (int)flags);
665 descriptor_add(rval);
668 rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
673 rval = unlink(STR(0));
675 case ACTION_UNLINKAT:
676 rval = unlinkat(NUM(0), STR(1),
677 (int)str2flags(unlinkat_flags, STR(2)));
680 rval = mkdir(STR(0), (mode_t)NUM(1));
683 rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
686 rval = rmdir(STR(0));
689 rval = link(STR(0), STR(1));
692 rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
693 (int)str2flags(linkat_flags, STR(4)));
696 rval = symlink(STR(0), STR(1));
698 case ACTION_SYMLINKAT:
699 rval = symlinkat(STR(0), NUM(1), STR(2));
702 rval = rename(STR(0), STR(1));
704 case ACTION_RENAMEAT:
705 rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
708 rval = mkfifo(STR(0), (mode_t)NUM(1));
710 case ACTION_MKFIFOAT:
711 rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
720 switch (scall->sd_action) {
731 dev = makedev(NUM(fa + 3), NUM(fa + 4));
732 if (strcmp(STR(fa + 1), "c") == 0) /* character device */
734 else if (strcmp(STR(fa + 1), "b") == 0) /* block device */
736 else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */
738 else if (strcmp(STR(fa + 1), "d") == 0) /* directory */
740 else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */
743 fprintf(stderr, "wrong argument 1\n");
746 switch (scall->sd_action) {
748 rval = mknod(STR(0), ntype | NUM(2), dev);
751 rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
760 struct sockaddr_un sunx;
762 sunx.sun_family = AF_UNIX;
763 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
764 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
765 rval = socket(AF_UNIX, SOCK_STREAM, 0);
768 rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
774 struct sockaddr_un sunx;
776 sunx.sun_family = AF_UNIX;
777 strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
778 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
779 rval = socket(AF_UNIX, SOCK_STREAM, 0);
782 rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
789 struct sockaddr_un sunx;
791 sunx.sun_family = AF_UNIX;
792 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
793 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
794 rval = socket(AF_UNIX, SOCK_STREAM, 0);
797 rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
801 case ACTION_CONNECTAT:
803 struct sockaddr_un sunx;
805 sunx.sun_family = AF_UNIX;
806 strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
807 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
808 rval = socket(AF_UNIX, SOCK_STREAM, 0);
811 rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
817 rval = chmod(STR(0), (mode_t)NUM(1));
820 rval = fchmod(NUM(0), (mode_t)NUM(1));
824 rval = lchmod(STR(0), (mode_t)NUM(1));
827 case ACTION_FCHMODAT:
828 rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
829 str2flags(fchmodat_flags, STR(3)));
832 rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
835 rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
838 rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
840 case ACTION_FCHOWNAT:
841 rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
842 (int)str2flags(fchownat_flags, STR(4)));
846 rval = chflags(STR(0),
847 (unsigned long)str2flags(chflags_flags, STR(1)));
851 case ACTION_FCHFLAGS:
852 rval = fchflags(NUM(0),
853 (unsigned long)str2flags(chflags_flags, STR(1)));
857 case ACTION_CHFLAGSAT:
858 rval = chflagsat(NUM(0), STR(1),
859 (unsigned long)str2flags(chflags_flags, STR(2)),
860 (int)str2flags(chflagsat_flags, STR(3)));
864 case ACTION_LCHFLAGS:
865 rval = lchflags(STR(0),
866 (unsigned long)str2flags(chflags_flags, STR(1)));
869 case ACTION_TRUNCATE:
870 rval = truncate64(STR(0), NUM(1));
872 case ACTION_FTRUNCATE:
873 rval = ftruncate64(NUM(0), NUM(1));
876 rval = stat64(STR(0), &sb);
878 show_stats(&sb, STR(1));
883 rval = fstat64(NUM(0), &sb);
885 show_stats(&sb, STR(1));
890 rval = lstat64(STR(0), &sb);
892 show_stats(&sb, STR(1));
897 rval = fstatat(NUM(0), STR(1), &sb,
898 (int)str2flags(fstatat_flags, STR(2)));
900 show_stats(&sb, STR(3));
904 case ACTION_PATHCONF:
905 case ACTION_FPATHCONF:
907 case ACTION_LPATHCONF:
912 name = str2name(pathconf_names, STR(1));
914 fprintf(stderr, "unknown name %s", STR(1));
918 switch (scall->sd_action) {
919 case ACTION_PATHCONF:
920 lrval = pathconf(STR(0), name);
922 case ACTION_FPATHCONF:
923 lrval = fpathconf(NUM(0), name);
926 case ACTION_LPATHCONF:
927 lrval = lpathconf(STR(0), name);
933 if (lrval == -1 && errno == 0) {
934 printf("unlimited\n");
936 } else if (lrval >= 0) {
937 printf("%ld\n", lrval);
943 #ifdef HAS_FREEBSD_ACL
944 case ACTION_PREPENDACL:
947 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
951 newacl = acl_from_text(STR(1));
955 while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
956 entry_id = ACL_NEXT_ENTRY;
958 if (acl_create_entry_np(&acl, &entry, 0))
961 if (acl_copy_entry(entry, newentry))
965 rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
968 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
976 rval = write(NUM(0), STR(1), strlen(STR(1)));
979 fprintf(stderr, "unsupported syscall\n");
987 serrno = err2str(errno);
988 fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
989 printf("%s\n", serrno);
1004 ngroups = sysconf(_SC_NGROUPS_MAX);
1005 assert(ngroups > 0);
1006 gidset = malloc(sizeof(*gidset) * ngroups);
1007 assert(gidset != NULL);
1008 for (i = 0, g = strtok(gids, ","); g != NULL;
1009 g = strtok(NULL, ","), i++) {
1011 fprintf(stderr, "too many gids\n");
1014 gidset[i] = strtol(g, &endp, 0);
1015 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1016 fprintf(stderr, "invalid gid '%s' - number expected\n",
1021 if (setgroups(i, gidset) < 0) {
1022 fprintf(stderr, "cannot change groups: %s\n", strerror(errno));
1025 if (setegid(gidset[0]) < 0) {
1026 fprintf(stderr, "cannot change effective gid: %s\n",
1034 main(int argc, char *argv[])
1036 struct syscall_desc *scall;
1045 while ((ch = getopt(argc, argv, "g:u:U:")) != -1) {
1051 uid = (int)strtol(optarg, &endp, 0);
1052 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1053 fprintf(stderr, "invalid uid '%s' - number "
1054 "expected\n", optarg);
1059 umsk = (int)strtol(optarg, &endp, 0);
1060 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1061 fprintf(stderr, "invalid umask '%s' - number "
1062 "expected\n", optarg);
1074 fprintf(stderr, "too few arguments\n");
1079 fprintf(stderr, "changing groups to %s\n", gids);
1083 fprintf(stderr, "changing uid to %d\n", uid);
1084 if (setuid(uid) < 0) {
1085 fprintf(stderr, "cannot change uid: %s\n",
1091 /* Change umask to requested value or to 0, if not requested. */
1095 scall = find_syscall(argv[0]);
1096 if (scall == NULL) {
1097 fprintf(stderr, "syscall '%s' not supported\n",
1103 n = call_syscall(scall, argv);
1106 if (argv[0] == NULL)
1118 static char errnum[8];
1263 return ("EINPROGRESS");
1267 return ("EALREADY");
1271 return ("ENOTSOCK");
1275 return ("EDESTADDRREQ");
1279 return ("EMSGSIZE");
1283 return ("EPROTOTYPE");
1287 return ("ENOPROTOOPT");
1289 #ifdef EPROTONOSUPPORT
1290 case EPROTONOSUPPORT:
1291 return ("EPROTONOSUPPORT");
1293 #ifdef ESOCKTNOSUPPORT
1294 case ESOCKTNOSUPPORT:
1295 return ("ESOCKTNOSUPPORT");
1299 return ("EOPNOTSUPP");
1303 return ("EPFNOSUPPORT");
1307 return ("EAFNOSUPPORT");
1311 return ("EADDRINUSE");
1313 #ifdef EADDRNOTAVAIL
1315 return ("EADDRNOTAVAIL");
1319 return ("ENETDOWN");
1323 return ("ENETUNREACH");
1327 return ("ENETRESET");
1331 return ("ECONNABORTED");
1335 return ("ECONNRESET");
1347 return ("ENOTCONN");
1351 return ("ESHUTDOWN");
1355 return ("ETOOMANYREFS");
1359 return ("ETIMEDOUT");
1363 return ("ECONNREFUSED");
1371 return ("ENAMETOOLONG");
1375 return ("EHOSTDOWN");
1379 return ("EHOSTUNREACH");
1383 return ("ENOTEMPTY");
1387 return ("EPROCLIM");
1411 return ("ERPCMISMATCH");
1415 return ("EPROGUNAVAIL");
1417 #ifdef EPROGMISMATCH
1419 return ("EPROGMISMATCH");
1423 return ("EPROCUNAVAIL");
1443 return ("ENEEDAUTH");
1455 return ("EOVERFLOW");
1459 return ("ECANCELED");
1479 return ("EMULTIHOP");
1490 snprintf(errnum, sizeof(errnum), "%d", error);