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)
123 #ifdef HAS_FREEBSD_ACL
130 #define TYPE_NONE 0x0000
131 #define TYPE_STRING 0x0001
132 #define TYPE_NUMBER 0x0002
133 #define TYPE_DESCRIPTOR 0x0003
134 #define TYPE_MASK 0x000f
136 #define TYPE_OPTIONAL 0x0100
140 struct syscall_desc {
142 enum action sd_action;
143 int sd_args[MAX_ARGS];
146 static struct syscall_desc syscalls[] = {
147 { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
148 { "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
149 { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
150 { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } },
151 { "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
152 { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
153 { "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
154 { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } },
155 { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
156 { "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
157 { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
158 { "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
159 { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
160 { "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
161 { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
162 { "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
163 { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
164 { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
165 { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } },
167 { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
169 { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } },
171 { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
173 { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
174 { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
176 { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
178 { "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
179 { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
180 { "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
181 { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
182 { "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
184 { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
187 { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
190 { "chflagsat", ACTION_CHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
193 { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
195 { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
196 { "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
197 { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
198 { "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
199 { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
200 { "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
201 { "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
202 { "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
203 { "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
204 #ifdef HAS_FREEBSD_ACL
205 { "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
206 { "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } },
208 { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
209 { NULL, -1, { TYPE_NONE } }
217 static struct flag open_flags[] = {
219 { O_RDONLY, "O_RDONLY" },
222 { O_WRONLY, "O_WRONLY" },
225 { O_RDWR, "O_RDWR" },
228 { O_NONBLOCK, "O_NONBLOCK" },
231 { O_APPEND, "O_APPEND" },
234 { O_CREAT, "O_CREAT" },
237 { O_TRUNC, "O_TRUNC" },
240 { O_EXCL, "O_EXCL" },
243 { O_SHLOCK, "O_SHLOCK" },
246 { O_EXLOCK, "O_EXLOCK" },
249 { O_DIRECT, "O_DIRECT" },
252 { O_FSYNC, "O_FSYNC" },
255 { O_SYNC, "O_SYNC" },
258 { O_NOFOLLOW, "O_NOFOLLOW" },
261 { O_NOCTTY, "O_NOCTTY" },
264 { O_DIRECTORY, "O_DIRECTORY" },
270 static struct flag chflags_flags[] = {
272 { UF_NODUMP, "UF_NODUMP" },
275 { UF_IMMUTABLE, "UF_IMMUTABLE" },
278 { UF_APPEND, "UF_APPEND" },
281 { UF_NOUNLINK, "UF_NOUNLINK" },
284 { UF_OPAQUE, "UF_OPAQUE" },
287 { SF_ARCHIVED, "SF_ARCHIVED" },
290 { SF_IMMUTABLE, "SF_IMMUTABLE" },
293 { SF_APPEND, "SF_APPEND" },
296 { SF_NOUNLINK, "SF_NOUNLINK" },
299 { SF_SNAPSHOT, "SF_SNAPSHOT" },
305 static struct flag unlinkat_flags[] = {
306 { AT_REMOVEDIR, "AT_REMOVEDIR" },
310 static struct flag linkat_flags[] = {
311 { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" },
315 static struct flag chflagsat_flags[] = {
316 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
320 static struct flag fchmodat_flags[] = {
321 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
325 static struct flag fchownat_flags[] = {
326 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
330 static struct flag fstatat_flags[] = {
331 { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
340 static struct name pathconf_names[] = {
342 { _PC_LINK_MAX, "_PC_LINK_MAX" },
345 { _PC_NAME_MAX, "_PC_NAME_MAX" },
348 { _PC_PATH_MAX, "_PC_PATH_MAX" },
350 #ifdef _PC_SYMLINK_MAX
351 { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" },
356 static const char *err2str(int error);
358 static int *descriptors;
359 static int ndescriptors;
365 fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n");
370 str2flags(struct flag *tflags, char *sflags)
376 /* 'none' or '0' means no flags */
377 if (strcmp(sflags, "none") == 0 || strcmp(sflags, "0") == 0)
379 for (f = strtok(sflags, ",|"); f != NULL; f = strtok(NULL, ",|")) {
380 for (i = 0; tflags[i].f_str != NULL; i++) {
381 if (strcmp(tflags[i].f_str, f) == 0)
384 if (tflags[i].f_str == NULL) {
385 fprintf(stderr, "unknown flag '%s'\n", f);
388 flags |= tflags[i].f_flag;
395 flags2str(struct flag *tflags, long long flags)
397 static char sflags[1024];
401 for (i = 0; tflags[i].f_str != NULL; i++) {
402 if (flags & tflags[i].f_flag) {
403 if (sflags[0] != '\0')
404 strlcat(sflags, ",", sizeof(sflags));
405 strlcat(sflags, tflags[i].f_str, sizeof(sflags));
408 if (sflags[0] == '\0')
409 strlcpy(sflags, "none", sizeof(sflags));
415 str2name(struct name *names, char *name)
419 for (i = 0; names[i].n_str != NULL; i++) {
420 if (strcmp(names[i].n_str, name) == 0)
421 return (names[i].n_name);
426 static struct syscall_desc *
427 find_syscall(const char *name)
431 for (i = 0; syscalls[i].sd_name != NULL; i++) {
432 if (strcmp(syscalls[i].sd_name, name) == 0)
433 return (&syscalls[i]);
439 show_stat(struct stat64 *sp, const char *what)
442 if (strcmp(what, "mode") == 0)
443 printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS));
444 else if (strcmp(what, "inode") == 0)
445 printf("%lld", (long long)sp->st_ino);
446 else if (strcmp(what, "nlink") == 0)
447 printf("%lld", (long long)sp->st_nlink);
448 else if (strcmp(what, "uid") == 0)
449 printf("%d", (int)sp->st_uid);
450 else if (strcmp(what, "gid") == 0)
451 printf("%d", (int)sp->st_gid);
452 else if (strcmp(what, "size") == 0)
453 printf("%lld", (long long)sp->st_size);
454 else if (strcmp(what, "blocks") == 0)
455 printf("%lld", (long long)sp->st_blocks);
456 else if (strcmp(what, "atime") == 0)
457 printf("%lld", (long long)sp->st_atime);
458 else if (strcmp(what, "mtime") == 0)
459 printf("%lld", (long long)sp->st_mtime);
460 else if (strcmp(what, "ctime") == 0)
461 printf("%lld", (long long)sp->st_ctime);
463 else if (strcmp(what, "flags") == 0)
464 printf("%s", flags2str(chflags_flags, (long long)sp->st_flags));
466 else if (strcmp(what, "major") == 0)
467 printf("%u", (unsigned int)major(sp->st_rdev));
468 else if (strcmp(what, "minor") == 0)
469 printf("%u", (unsigned int)minor(sp->st_rdev));
470 else if (strcmp(what, "type") == 0) {
471 switch (sp->st_mode & S_IFMT) {
503 show_stats(struct stat64 *sp, char *what)
508 for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) {
517 descriptor_add(int fd)
521 if (descriptors == NULL) {
522 descriptors = malloc(sizeof(descriptors[0]) * ndescriptors);
524 descriptors = realloc(descriptors,
525 sizeof(descriptors[0]) * ndescriptors);
527 assert(descriptors != NULL);
528 descriptors[ndescriptors - 1] = fd;
532 descriptor_get(int pos)
535 if (pos < 0 || pos >= ndescriptors) {
536 fprintf(stderr, "invalid descriptor %d\n", pos);
540 return (descriptors[pos]);
544 call_syscall(struct syscall_desc *scall, char *argv[])
555 #ifdef HAS_FREEBSD_ACL
556 int entry_id = ACL_FIRST_ENTRY;
558 acl_entry_t entry, newentry;
562 * Verify correctness of the arguments.
564 for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
565 if (scall->sd_args[i] == TYPE_NONE) {
566 if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
568 fprintf(stderr, "too many arguments [%s]\n", argv[i]);
571 if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
572 if (scall->sd_args[i] & TYPE_OPTIONAL)
574 fprintf(stderr, "too few arguments\n");
577 if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
578 if (strcmp(argv[i], "NULL") == 0)
580 else if (strcmp(argv[i], "DEADCODE") == 0)
581 args[i].str = (void *)0xdeadc0de;
583 args[i].str = argv[i];
584 } else if ((scall->sd_args[i] & TYPE_MASK) ==
586 args[i].num = strtoll(argv[i], &endp, 0);
588 !isspace((unsigned char)*endp)) {
590 "invalid argument %u, number expected [%s]\n",
594 } else if ((scall->sd_args[i] & TYPE_MASK) ==
596 if (strcmp(argv[i], "AT_FDCWD") == 0) {
597 args[i].num = AT_FDCWD;
598 } else if (strcmp(argv[i], "BADFD") == 0) {
599 /* In case AT_FDCWD is -1 on some systems... */
607 pos = strtoll(argv[i], &endp, 0);
609 !isspace((unsigned char)*endp)) {
611 "invalid argument %u, number expected [%s]\n",
615 args[i].num = descriptor_get(pos);
621 * Call the given syscall.
623 #define NUM(n) (args[(n)].num)
624 #define STR(n) (args[(n)].str)
625 switch (scall->sd_action) {
627 flags = str2flags(open_flags, STR(1));
628 if (flags & O_CREAT) {
630 fprintf(stderr, "too few arguments\n");
633 rval = open(STR(0), (int)flags, (mode_t)NUM(2));
636 fprintf(stderr, "too many arguments\n");
639 rval = open(STR(0), (int)flags);
642 descriptor_add(rval);
645 flags = str2flags(open_flags, STR(2));
646 if (flags & O_CREAT) {
648 fprintf(stderr, "too few arguments\n");
651 rval = openat(NUM(0), STR(1), (int)flags,
655 fprintf(stderr, "too many arguments\n");
658 rval = openat(NUM(0), STR(1), (int)flags);
661 descriptor_add(rval);
664 rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
669 rval = unlink(STR(0));
671 case ACTION_UNLINKAT:
672 rval = unlinkat(NUM(0), STR(1),
673 (int)str2flags(unlinkat_flags, STR(2)));
676 rval = mkdir(STR(0), (mode_t)NUM(1));
679 rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
682 rval = rmdir(STR(0));
685 rval = link(STR(0), STR(1));
688 rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
689 (int)str2flags(linkat_flags, STR(4)));
692 rval = symlink(STR(0), STR(1));
694 case ACTION_SYMLINKAT:
695 rval = symlinkat(STR(0), NUM(1), STR(2));
698 rval = rename(STR(0), STR(1));
700 case ACTION_RENAMEAT:
701 rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
704 rval = mkfifo(STR(0), (mode_t)NUM(1));
706 case ACTION_MKFIFOAT:
707 rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
716 switch (scall->sd_action) {
727 dev = makedev(NUM(fa + 3), NUM(fa + 4));
728 if (strcmp(STR(fa + 1), "c") == 0) /* character device */
730 else if (strcmp(STR(fa + 1), "b") == 0) /* block device */
732 else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */
734 else if (strcmp(STR(fa + 1), "d") == 0) /* directory */
736 else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */
739 fprintf(stderr, "wrong argument 1\n");
742 switch (scall->sd_action) {
744 rval = mknod(STR(0), ntype | NUM(2), dev);
747 rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
756 struct sockaddr_un sunx;
758 sunx.sun_family = AF_UNIX;
759 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
760 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
761 rval = socket(AF_UNIX, SOCK_STREAM, 0);
764 rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
770 struct sockaddr_un sunx;
772 sunx.sun_family = AF_UNIX;
773 strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
774 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
775 rval = socket(AF_UNIX, SOCK_STREAM, 0);
778 rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
785 struct sockaddr_un sunx;
787 sunx.sun_family = AF_UNIX;
788 strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
789 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
790 rval = socket(AF_UNIX, SOCK_STREAM, 0);
793 rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
797 case ACTION_CONNECTAT:
799 struct sockaddr_un sunx;
801 sunx.sun_family = AF_UNIX;
802 strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
803 sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
804 rval = socket(AF_UNIX, SOCK_STREAM, 0);
807 rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
813 rval = chmod(STR(0), (mode_t)NUM(1));
816 rval = fchmod(NUM(0), (mode_t)NUM(1));
820 rval = lchmod(STR(0), (mode_t)NUM(1));
823 case ACTION_FCHMODAT:
824 rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
825 str2flags(fchmodat_flags, STR(3)));
828 rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
831 rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
834 rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
836 case ACTION_FCHOWNAT:
837 rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
838 (int)str2flags(fchownat_flags, STR(4)));
842 rval = chflags(STR(0),
843 (unsigned long)str2flags(chflags_flags, STR(1)));
847 case ACTION_FCHFLAGS:
848 rval = fchflags(NUM(0),
849 (unsigned long)str2flags(chflags_flags, STR(1)));
853 case ACTION_CHFLAGSAT:
854 rval = chflagsat(NUM(0), STR(1),
855 (unsigned long)str2flags(chflags_flags, STR(2)),
856 (int)str2flags(chflagsat_flags, STR(3)));
860 case ACTION_LCHFLAGS:
861 rval = lchflags(STR(0),
862 (unsigned long)str2flags(chflags_flags, STR(1)));
865 case ACTION_TRUNCATE:
866 rval = truncate64(STR(0), NUM(1));
868 case ACTION_FTRUNCATE:
869 rval = ftruncate64(NUM(0), NUM(1));
872 rval = stat64(STR(0), &sb);
874 show_stats(&sb, STR(1));
879 rval = fstat64(NUM(0), &sb);
881 show_stats(&sb, STR(1));
886 rval = lstat64(STR(0), &sb);
888 show_stats(&sb, STR(1));
893 rval = fstatat(NUM(0), STR(1), &sb,
894 (int)str2flags(fstatat_flags, STR(2)));
896 show_stats(&sb, STR(3));
900 case ACTION_PATHCONF:
901 case ACTION_FPATHCONF:
902 case ACTION_LPATHCONF:
906 name = str2name(pathconf_names, STR(1));
908 fprintf(stderr, "unknown name %s", STR(1));
912 switch (scall->sd_action) {
913 case ACTION_PATHCONF:
914 lrval = pathconf(STR(0), name);
916 case ACTION_FPATHCONF:
917 lrval = fpathconf(NUM(0), name);
919 case ACTION_LPATHCONF:
920 lrval = lpathconf(STR(0), name);
925 if (lrval == -1 && errno == 0) {
926 printf("unlimited\n");
928 } else if (lrval >= 0) {
929 printf("%ld\n", lrval);
935 #ifdef HAS_FREEBSD_ACL
936 case ACTION_PREPENDACL:
939 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
943 newacl = acl_from_text(STR(1));
947 while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
948 entry_id = ACL_NEXT_ENTRY;
950 if (acl_create_entry_np(&acl, &entry, 0))
953 if (acl_copy_entry(entry, newentry))
957 rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
960 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
968 rval = write(NUM(0), STR(1), strlen(STR(1)));
971 fprintf(stderr, "unsupported syscall\n");
979 serrno = err2str(errno);
980 fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
981 printf("%s\n", serrno);
996 ngroups = sysconf(_SC_NGROUPS_MAX);
998 gidset = malloc(sizeof(*gidset) * ngroups);
999 assert(gidset != NULL);
1000 for (i = 0, g = strtok(gids, ","); g != NULL;
1001 g = strtok(NULL, ","), i++) {
1003 fprintf(stderr, "too many gids\n");
1006 gidset[i] = strtol(g, &endp, 0);
1007 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1008 fprintf(stderr, "invalid gid '%s' - number expected\n",
1013 if (setgroups(i, gidset) < 0) {
1014 fprintf(stderr, "cannot change groups: %s\n", strerror(errno));
1017 if (setegid(gidset[0]) < 0) {
1018 fprintf(stderr, "cannot change effective gid: %s\n",
1026 main(int argc, char *argv[])
1028 struct syscall_desc *scall;
1037 while ((ch = getopt(argc, argv, "g:u:U:")) != -1) {
1043 uid = (int)strtol(optarg, &endp, 0);
1044 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1045 fprintf(stderr, "invalid uid '%s' - number "
1046 "expected\n", optarg);
1051 umsk = (int)strtol(optarg, &endp, 0);
1052 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1053 fprintf(stderr, "invalid umask '%s' - number "
1054 "expected\n", optarg);
1066 fprintf(stderr, "too few arguments\n");
1071 fprintf(stderr, "changing groups to %s\n", gids);
1075 fprintf(stderr, "changing uid to %d\n", uid);
1076 if (setuid(uid) < 0) {
1077 fprintf(stderr, "cannot change uid: %s\n",
1083 /* Change umask to requested value or to 0, if not requested. */
1087 scall = find_syscall(argv[0]);
1088 if (scall == NULL) {
1089 fprintf(stderr, "syscall '%s' not supported\n",
1095 n = call_syscall(scall, argv);
1098 if (argv[0] == NULL)
1110 static char errnum[8];
1255 return ("EINPROGRESS");
1259 return ("EALREADY");
1263 return ("ENOTSOCK");
1267 return ("EDESTADDRREQ");
1271 return ("EMSGSIZE");
1275 return ("EPROTOTYPE");
1279 return ("ENOPROTOOPT");
1281 #ifdef EPROTONOSUPPORT
1282 case EPROTONOSUPPORT:
1283 return ("EPROTONOSUPPORT");
1285 #ifdef ESOCKTNOSUPPORT
1286 case ESOCKTNOSUPPORT:
1287 return ("ESOCKTNOSUPPORT");
1291 return ("EOPNOTSUPP");
1295 return ("EPFNOSUPPORT");
1299 return ("EAFNOSUPPORT");
1303 return ("EADDRINUSE");
1305 #ifdef EADDRNOTAVAIL
1307 return ("EADDRNOTAVAIL");
1311 return ("ENETDOWN");
1315 return ("ENETUNREACH");
1319 return ("ENETRESET");
1323 return ("ECONNABORTED");
1327 return ("ECONNRESET");
1339 return ("ENOTCONN");
1343 return ("ESHUTDOWN");
1347 return ("ETOOMANYREFS");
1351 return ("ETIMEDOUT");
1355 return ("ECONNREFUSED");
1363 return ("ENAMETOOLONG");
1367 return ("EHOSTDOWN");
1371 return ("EHOSTUNREACH");
1375 return ("ENOTEMPTY");
1379 return ("EPROCLIM");
1403 return ("ERPCMISMATCH");
1407 return ("EPROGUNAVAIL");
1409 #ifdef EPROGMISMATCH
1411 return ("EPROGMISMATCH");
1415 return ("EPROCUNAVAIL");
1435 return ("ENEEDAUTH");
1447 return ("EOVERFLOW");
1451 return ("ECANCELED");
1471 return ("EMULTIHOP");
1482 snprintf(errnum, sizeof(errnum), "%d", error);