summaryrefslogtreecommitdiffstats
path: root/contrib/pjdfstest/pjdfstest.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pjdfstest/pjdfstest.c')
-rw-r--r--contrib/pjdfstest/pjdfstest.c1493
1 files changed, 1493 insertions, 0 deletions
diff --git a/contrib/pjdfstest/pjdfstest.c b/contrib/pjdfstest/pjdfstest.c
new file mode 100644
index 0000000..046df49
--- /dev/null
+++ b/contrib/pjdfstest/pjdfstest.c
@@ -0,0 +1,1493 @@
+/*-
+ * Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#ifndef makedev
+#include <sys/mkdev.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HAS_TRUNCATE64
+#define truncate64 truncate
+#define ftruncate64 ftruncate
+#endif
+#ifndef HAS_STAT64
+#define stat64 stat
+#define fstat64 fstat
+#define lstat64 lstat
+#endif
+#ifdef HAS_FREEBSD_ACL
+#include <sys/acl.h>
+#endif
+
+#ifndef ALLPERMS
+#define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
+#endif
+
+enum action {
+ ACTION_OPEN,
+ ACTION_OPENAT,
+ ACTION_CREATE,
+ ACTION_UNLINK,
+ ACTION_UNLINKAT,
+ ACTION_MKDIR,
+ ACTION_MKDIRAT,
+ ACTION_RMDIR,
+ ACTION_LINK,
+ ACTION_LINKAT,
+ ACTION_SYMLINK,
+ ACTION_SYMLINKAT,
+ ACTION_RENAME,
+ ACTION_RENAMEAT,
+ ACTION_MKFIFO,
+ ACTION_MKFIFOAT,
+ ACTION_MKNOD,
+ ACTION_MKNODAT,
+ ACTION_BIND,
+#ifdef HAS_BINDAT
+ ACTION_BINDAT,
+#endif
+ ACTION_CONNECT,
+#ifdef HAS_CONNECTAT
+ ACTION_CONNECTAT,
+#endif
+ ACTION_CHMOD,
+ ACTION_FCHMOD,
+#ifdef HAS_LCHMOD
+ ACTION_LCHMOD,
+#endif
+ ACTION_FCHMODAT,
+ ACTION_CHOWN,
+ ACTION_FCHOWN,
+ ACTION_LCHOWN,
+ ACTION_FCHOWNAT,
+#ifdef HAS_CHFLAGS
+ ACTION_CHFLAGS,
+#endif
+#ifdef HAS_FCHFLAGS
+ ACTION_FCHFLAGS,
+#endif
+#ifdef HAS_CHFLAGSAT
+ ACTION_CHFLAGSAT,
+#endif
+#ifdef HAS_LCHFLAGS
+ ACTION_LCHFLAGS,
+#endif
+ ACTION_TRUNCATE,
+ ACTION_FTRUNCATE,
+ ACTION_STAT,
+ ACTION_FSTAT,
+ ACTION_LSTAT,
+ ACTION_FSTATAT,
+ ACTION_PATHCONF,
+ ACTION_FPATHCONF,
+#ifdef HAS_LPATHCONF
+ ACTION_LPATHCONF,
+#endif
+#ifdef HAS_FREEBSD_ACL
+ ACTION_PREPENDACL,
+ ACTION_READACL,
+#endif
+ ACTION_WRITE,
+};
+
+#define TYPE_NONE 0x0000
+#define TYPE_STRING 0x0001
+#define TYPE_NUMBER 0x0002
+#define TYPE_DESCRIPTOR 0x0003
+#define TYPE_MASK 0x000f
+
+#define TYPE_OPTIONAL 0x0100
+
+#define MAX_ARGS 8
+
+struct syscall_desc {
+ const char *sd_name;
+ enum action sd_action;
+ int sd_args[MAX_ARGS];
+};
+
+static struct syscall_desc syscalls[] = {
+ { "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
+ { "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
+ { "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+ { "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } },
+ { "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+ { "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+ { "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } },
+ { "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
+ { "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
+ { "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+ { "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+ { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
+ { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
+ { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } },
+#ifdef HAS_BINDAT
+ { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
+#endif
+ { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } },
+#ifdef HAS_CONNECTAT
+ { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
+#endif
+ { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+ { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
+#ifdef HAS_LCHMOD
+ { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+#endif
+ { "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
+ { "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
+ { "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
+ { "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
+ { "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
+#ifdef HAS_CHFLAGS
+ { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+#endif
+#ifdef HAS_FCHFLAGS
+ { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
+#endif
+#ifdef HAS_CHFLAGSAT
+ { "chflagsat", ACTION_CHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+#endif
+#ifdef HAS_LCHFLAGS
+ { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+#endif
+ { "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+ { "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
+ { "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
+ { "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
+#ifdef HAS_LPATHCONF
+ { "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+#endif
+#ifdef HAS_FREEBSD_ACL
+ { "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } },
+#endif
+ { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
+ { NULL, -1, { TYPE_NONE } }
+};
+
+struct flag {
+ long long f_flag;
+ const char *f_str;
+};
+
+static struct flag open_flags[] = {
+#ifdef O_RDONLY
+ { O_RDONLY, "O_RDONLY" },
+#endif
+#ifdef O_WRONLY
+ { O_WRONLY, "O_WRONLY" },
+#endif
+#ifdef O_RDWR
+ { O_RDWR, "O_RDWR" },
+#endif
+#ifdef O_NONBLOCK
+ { O_NONBLOCK, "O_NONBLOCK" },
+#endif
+#ifdef O_APPEND
+ { O_APPEND, "O_APPEND" },
+#endif
+#ifdef O_CREAT
+ { O_CREAT, "O_CREAT" },
+#endif
+#ifdef O_TRUNC
+ { O_TRUNC, "O_TRUNC" },
+#endif
+#ifdef O_EXCL
+ { O_EXCL, "O_EXCL" },
+#endif
+#ifdef O_SHLOCK
+ { O_SHLOCK, "O_SHLOCK" },
+#endif
+#ifdef O_EXLOCK
+ { O_EXLOCK, "O_EXLOCK" },
+#endif
+#ifdef O_DIRECT
+ { O_DIRECT, "O_DIRECT" },
+#endif
+#ifdef O_FSYNC
+ { O_FSYNC, "O_FSYNC" },
+#endif
+#ifdef O_SYNC
+ { O_SYNC, "O_SYNC" },
+#endif
+#ifdef O_NOFOLLOW
+ { O_NOFOLLOW, "O_NOFOLLOW" },
+#endif
+#ifdef O_NOCTTY
+ { O_NOCTTY, "O_NOCTTY" },
+#endif
+#ifdef O_DIRECTORY
+ { O_DIRECTORY, "O_DIRECTORY" },
+#endif
+ { 0, NULL }
+};
+
+#ifdef HAS_CHFLAGS
+static struct flag chflags_flags[] = {
+#ifdef UF_NODUMP
+ { UF_NODUMP, "UF_NODUMP" },
+#endif
+#ifdef UF_IMMUTABLE
+ { UF_IMMUTABLE, "UF_IMMUTABLE" },
+#endif
+#ifdef UF_APPEND
+ { UF_APPEND, "UF_APPEND" },
+#endif
+#ifdef UF_NOUNLINK
+ { UF_NOUNLINK, "UF_NOUNLINK" },
+#endif
+#ifdef UF_OPAQUE
+ { UF_OPAQUE, "UF_OPAQUE" },
+#endif
+#ifdef SF_ARCHIVED
+ { SF_ARCHIVED, "SF_ARCHIVED" },
+#endif
+#ifdef SF_IMMUTABLE
+ { SF_IMMUTABLE, "SF_IMMUTABLE" },
+#endif
+#ifdef SF_APPEND
+ { SF_APPEND, "SF_APPEND" },
+#endif
+#ifdef SF_NOUNLINK
+ { SF_NOUNLINK, "SF_NOUNLINK" },
+#endif
+#ifdef SF_SNAPSHOT
+ { SF_SNAPSHOT, "SF_SNAPSHOT" },
+#endif
+ { 0, NULL }
+};
+#endif
+
+static struct flag unlinkat_flags[] = {
+ { AT_REMOVEDIR, "AT_REMOVEDIR" },
+ { 0, NULL }
+};
+
+static struct flag linkat_flags[] = {
+ { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" },
+ { 0, NULL }
+};
+
+static struct flag chflagsat_flags[] = {
+ { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
+ { 0, NULL }
+};
+
+static struct flag fchmodat_flags[] = {
+ { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
+ { 0, NULL }
+};
+
+static struct flag fchownat_flags[] = {
+ { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
+ { 0, NULL }
+};
+
+static struct flag fstatat_flags[] = {
+ { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
+ { 0, NULL }
+};
+
+struct name {
+ int n_name;
+ const char *n_str;
+};
+
+static struct name pathconf_names[] = {
+#ifdef _PC_LINK_MAX
+ { _PC_LINK_MAX, "_PC_LINK_MAX" },
+#endif
+#ifdef _PC_NAME_MAX
+ { _PC_NAME_MAX, "_PC_NAME_MAX" },
+#endif
+#ifdef _PC_PATH_MAX
+ { _PC_PATH_MAX, "_PC_PATH_MAX" },
+#endif
+#ifdef _PC_SYMLINK_MAX
+ { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" },
+#endif
+ { 0, NULL }
+};
+
+static const char *err2str(int error);
+
+static int *descriptors;
+static int ndescriptors;
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n");
+ exit(1);
+}
+
+static long long
+str2flags(struct flag *tflags, char *sflags)
+{
+ long long flags = 0;
+ unsigned int i;
+ char *f;
+
+ /* 'none' or '0' means no flags */
+ if (strcmp(sflags, "none") == 0 || strcmp(sflags, "0") == 0)
+ return (0);
+ for (f = strtok(sflags, ",|"); f != NULL; f = strtok(NULL, ",|")) {
+ for (i = 0; tflags[i].f_str != NULL; i++) {
+ if (strcmp(tflags[i].f_str, f) == 0)
+ break;
+ }
+ if (tflags[i].f_str == NULL) {
+ fprintf(stderr, "unknown flag '%s'\n", f);
+ exit(1);
+ }
+ flags |= tflags[i].f_flag;
+ }
+ return (flags);
+}
+
+#ifdef HAS_CHFLAGS
+static char *
+flags2str(struct flag *tflags, long long flags)
+{
+ static char sflags[1024];
+ unsigned int i;
+
+ sflags[0] = '\0';
+ for (i = 0; tflags[i].f_str != NULL; i++) {
+ if (flags & tflags[i].f_flag) {
+ if (sflags[0] != '\0')
+ strlcat(sflags, ",", sizeof(sflags));
+ strlcat(sflags, tflags[i].f_str, sizeof(sflags));
+ }
+ }
+ if (sflags[0] == '\0')
+ strlcpy(sflags, "none", sizeof(sflags));
+ return (sflags);
+}
+#endif
+
+static int
+str2name(struct name *names, char *name)
+{
+ unsigned int i;
+
+ for (i = 0; names[i].n_str != NULL; i++) {
+ if (strcmp(names[i].n_str, name) == 0)
+ return (names[i].n_name);
+ }
+ return (-1);
+}
+
+static struct syscall_desc *
+find_syscall(const char *name)
+{
+ int i;
+
+ for (i = 0; syscalls[i].sd_name != NULL; i++) {
+ if (strcmp(syscalls[i].sd_name, name) == 0)
+ return (&syscalls[i]);
+ }
+ return (NULL);
+}
+
+static void
+show_stat(struct stat64 *sp, const char *what)
+{
+
+ if (strcmp(what, "mode") == 0)
+ printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS));
+ else if (strcmp(what, "inode") == 0)
+ printf("%lld", (long long)sp->st_ino);
+ else if (strcmp(what, "nlink") == 0)
+ printf("%lld", (long long)sp->st_nlink);
+ else if (strcmp(what, "uid") == 0)
+ printf("%d", (int)sp->st_uid);
+ else if (strcmp(what, "gid") == 0)
+ printf("%d", (int)sp->st_gid);
+ else if (strcmp(what, "size") == 0)
+ printf("%lld", (long long)sp->st_size);
+ else if (strcmp(what, "blocks") == 0)
+ printf("%lld", (long long)sp->st_blocks);
+ else if (strcmp(what, "atime") == 0)
+ printf("%lld", (long long)sp->st_atime);
+ else if (strcmp(what, "mtime") == 0)
+ printf("%lld", (long long)sp->st_mtime);
+ else if (strcmp(what, "ctime") == 0)
+ printf("%lld", (long long)sp->st_ctime);
+#ifdef HAS_CHFLAGS
+ else if (strcmp(what, "flags") == 0)
+ printf("%s", flags2str(chflags_flags, (long long)sp->st_flags));
+#endif
+ else if (strcmp(what, "major") == 0)
+ printf("%u", (unsigned int)major(sp->st_rdev));
+ else if (strcmp(what, "minor") == 0)
+ printf("%u", (unsigned int)minor(sp->st_rdev));
+ else if (strcmp(what, "type") == 0) {
+ switch (sp->st_mode & S_IFMT) {
+ case S_IFIFO:
+ printf("fifo");
+ break;
+ case S_IFCHR:
+ printf("char");
+ break;
+ case S_IFDIR:
+ printf("dir");
+ break;
+ case S_IFBLK:
+ printf("block");
+ break;
+ case S_IFREG:
+ printf("regular");
+ break;
+ case S_IFLNK:
+ printf("symlink");
+ break;
+ case S_IFSOCK:
+ printf("socket");
+ break;
+ default:
+ printf("unknown");
+ break;
+ }
+ } else {
+ printf("unknown");
+ }
+}
+
+static void
+show_stats(struct stat64 *sp, char *what)
+{
+ const char *s = "";
+ char *w;
+
+ for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) {
+ printf("%s", s);
+ show_stat(sp, w);
+ s = ",";
+ }
+ printf("\n");
+}
+
+static void
+descriptor_add(int fd)
+{
+
+ ndescriptors++;
+ if (descriptors == NULL) {
+ descriptors = malloc(sizeof(descriptors[0]) * ndescriptors);
+ } else {
+ descriptors = realloc(descriptors,
+ sizeof(descriptors[0]) * ndescriptors);
+ }
+ assert(descriptors != NULL);
+ descriptors[ndescriptors - 1] = fd;
+}
+
+static int
+descriptor_get(int pos)
+{
+
+ if (pos < 0 || pos >= ndescriptors) {
+ fprintf(stderr, "invalid descriptor %d\n", pos);
+ exit(1);
+ }
+
+ return (descriptors[pos]);
+}
+
+static unsigned int
+call_syscall(struct syscall_desc *scall, char *argv[])
+{
+ struct stat64 sb;
+ long long flags;
+ unsigned int i;
+ char *endp;
+ int name, rval;
+ union {
+ char *str;
+ long long num;
+ } args[MAX_ARGS];
+#ifdef HAS_FREEBSD_ACL
+ int entry_id = ACL_FIRST_ENTRY;
+ acl_t acl, newacl;
+ acl_entry_t entry, newentry;
+#endif
+
+ /*
+ * Verify correctness of the arguments.
+ */
+ for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
+ if (scall->sd_args[i] == TYPE_NONE) {
+ if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
+ break;
+ fprintf(stderr, "too many arguments [%s]\n", argv[i]);
+ exit(1);
+ } else {
+ if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
+ if (scall->sd_args[i] & TYPE_OPTIONAL)
+ break;
+ fprintf(stderr, "too few arguments\n");
+ exit(1);
+ }
+ if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
+ if (strcmp(argv[i], "NULL") == 0)
+ args[i].str = NULL;
+ else if (strcmp(argv[i], "DEADCODE") == 0)
+ args[i].str = (void *)0xdeadc0de;
+ else
+ args[i].str = argv[i];
+ } else if ((scall->sd_args[i] & TYPE_MASK) ==
+ TYPE_NUMBER) {
+ args[i].num = strtoll(argv[i], &endp, 0);
+ if (*endp != '\0' &&
+ !isspace((unsigned char)*endp)) {
+ fprintf(stderr,
+ "invalid argument %u, number expected [%s]\n",
+ i, endp);
+ exit(1);
+ }
+ } else if ((scall->sd_args[i] & TYPE_MASK) ==
+ TYPE_DESCRIPTOR) {
+ if (strcmp(argv[i], "AT_FDCWD") == 0) {
+ args[i].num = AT_FDCWD;
+ } else if (strcmp(argv[i], "BADFD") == 0) {
+ /* In case AT_FDCWD is -1 on some systems... */
+ if (AT_FDCWD == -1)
+ args[i].num = -2;
+ else
+ args[i].num = -1;
+ } else {
+ int pos;
+
+ pos = strtoll(argv[i], &endp, 0);
+ if (*endp != '\0' &&
+ !isspace((unsigned char)*endp)) {
+ fprintf(stderr,
+ "invalid argument %u, number expected [%s]\n",
+ i, endp);
+ exit(1);
+ }
+ args[i].num = descriptor_get(pos);
+ }
+ }
+ }
+ }
+ /*
+ * Call the given syscall.
+ */
+#define NUM(n) (args[(n)].num)
+#define STR(n) (args[(n)].str)
+ switch (scall->sd_action) {
+ case ACTION_OPEN:
+ flags = str2flags(open_flags, STR(1));
+ if (flags & O_CREAT) {
+ if (i == 2) {
+ fprintf(stderr, "too few arguments\n");
+ exit(1);
+ }
+ rval = open(STR(0), (int)flags, (mode_t)NUM(2));
+ } else {
+ if (i == 3) {
+ fprintf(stderr, "too many arguments\n");
+ exit(1);
+ }
+ rval = open(STR(0), (int)flags);
+ }
+ if (rval >= 0)
+ descriptor_add(rval);
+ break;
+ case ACTION_OPENAT:
+ flags = str2flags(open_flags, STR(2));
+ if (flags & O_CREAT) {
+ if (i == 3) {
+ fprintf(stderr, "too few arguments\n");
+ exit(1);
+ }
+ rval = openat(NUM(0), STR(1), (int)flags,
+ (mode_t)NUM(3));
+ } else {
+ if (i == 4) {
+ fprintf(stderr, "too many arguments\n");
+ exit(1);
+ }
+ rval = openat(NUM(0), STR(1), (int)flags);
+ }
+ if (rval >= 0)
+ descriptor_add(rval);
+ break;
+ case ACTION_CREATE:
+ rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
+ if (rval >= 0)
+ close(rval);
+ break;
+ case ACTION_UNLINK:
+ rval = unlink(STR(0));
+ break;
+ case ACTION_UNLINKAT:
+ rval = unlinkat(NUM(0), STR(1),
+ (int)str2flags(unlinkat_flags, STR(2)));
+ break;
+ case ACTION_MKDIR:
+ rval = mkdir(STR(0), (mode_t)NUM(1));
+ break;
+ case ACTION_MKDIRAT:
+ rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
+ break;
+ case ACTION_RMDIR:
+ rval = rmdir(STR(0));
+ break;
+ case ACTION_LINK:
+ rval = link(STR(0), STR(1));
+ break;
+ case ACTION_LINKAT:
+ rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
+ (int)str2flags(linkat_flags, STR(4)));
+ break;
+ case ACTION_SYMLINK:
+ rval = symlink(STR(0), STR(1));
+ break;
+ case ACTION_SYMLINKAT:
+ rval = symlinkat(STR(0), NUM(1), STR(2));
+ break;
+ case ACTION_RENAME:
+ rval = rename(STR(0), STR(1));
+ break;
+ case ACTION_RENAMEAT:
+ rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
+ break;
+ case ACTION_MKFIFO:
+ rval = mkfifo(STR(0), (mode_t)NUM(1));
+ break;
+ case ACTION_MKFIFOAT:
+ rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
+ break;
+ case ACTION_MKNOD:
+ case ACTION_MKNODAT:
+ {
+ mode_t ntype;
+ dev_t dev;
+ int fa;
+
+ switch (scall->sd_action) {
+ case ACTION_MKNOD:
+ fa = 0;
+ break;
+ case ACTION_MKNODAT:
+ fa = 1;
+ break;
+ default:
+ abort();
+ }
+
+ dev = makedev(NUM(fa + 3), NUM(fa + 4));
+ if (strcmp(STR(fa + 1), "c") == 0) /* character device */
+ ntype = S_IFCHR;
+ else if (strcmp(STR(fa + 1), "b") == 0) /* block device */
+ ntype = S_IFBLK;
+ else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */
+ ntype = S_IFIFO;
+ else if (strcmp(STR(fa + 1), "d") == 0) /* directory */
+ ntype = S_IFDIR;
+ else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */
+ ntype = S_IFREG;
+ else {
+ fprintf(stderr, "wrong argument 1\n");
+ exit(1);
+ }
+ switch (scall->sd_action) {
+ case ACTION_MKNOD:
+ rval = mknod(STR(0), ntype | NUM(2), dev);
+ break;
+ case ACTION_MKNODAT:
+ rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
+ break;
+ default:
+ abort();
+ }
+ break;
+ }
+ case ACTION_BIND:
+ {
+ struct sockaddr_un sunx;
+
+ sunx.sun_family = AF_UNIX;
+ strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
+ sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
+ rval = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (rval < 0)
+ break;
+ rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
+ break;
+ }
+#ifdef HAS_BINDAT
+ case ACTION_BINDAT:
+ {
+ struct sockaddr_un sunx;
+
+ sunx.sun_family = AF_UNIX;
+ strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
+ sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
+ rval = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (rval < 0)
+ break;
+ rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
+ sizeof(sunx));
+ break;
+ }
+#endif
+ case ACTION_CONNECT:
+ {
+ struct sockaddr_un sunx;
+
+ sunx.sun_family = AF_UNIX;
+ strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
+ sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
+ rval = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (rval < 0)
+ break;
+ rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
+ break;
+ }
+#ifdef HAS_CONNECTAT
+ case ACTION_CONNECTAT:
+ {
+ struct sockaddr_un sunx;
+
+ sunx.sun_family = AF_UNIX;
+ strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
+ sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
+ rval = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (rval < 0)
+ break;
+ rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
+ sizeof(sunx));
+ break;
+ }
+#endif
+ case ACTION_CHMOD:
+ rval = chmod(STR(0), (mode_t)NUM(1));
+ break;
+ case ACTION_FCHMOD:
+ rval = fchmod(NUM(0), (mode_t)NUM(1));
+ break;
+#ifdef HAS_LCHMOD
+ case ACTION_LCHMOD:
+ rval = lchmod(STR(0), (mode_t)NUM(1));
+ break;
+#endif
+ case ACTION_FCHMODAT:
+ rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
+ str2flags(fchmodat_flags, STR(3)));
+ break;
+ case ACTION_CHOWN:
+ rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
+ break;
+ case ACTION_FCHOWN:
+ rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
+ break;
+ case ACTION_LCHOWN:
+ rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
+ break;
+ case ACTION_FCHOWNAT:
+ rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
+ (int)str2flags(fchownat_flags, STR(4)));
+ break;
+#ifdef HAS_CHFLAGS
+ case ACTION_CHFLAGS:
+ rval = chflags(STR(0),
+ (unsigned long)str2flags(chflags_flags, STR(1)));
+ break;
+#endif
+#ifdef HAS_FCHFLAGS
+ case ACTION_FCHFLAGS:
+ rval = fchflags(NUM(0),
+ (unsigned long)str2flags(chflags_flags, STR(1)));
+ break;
+#endif
+#ifdef HAS_CHFLAGSAT
+ case ACTION_CHFLAGSAT:
+ rval = chflagsat(NUM(0), STR(1),
+ (unsigned long)str2flags(chflags_flags, STR(2)),
+ (int)str2flags(chflagsat_flags, STR(3)));
+ break;
+#endif
+#ifdef HAS_LCHFLAGS
+ case ACTION_LCHFLAGS:
+ rval = lchflags(STR(0),
+ (unsigned long)str2flags(chflags_flags, STR(1)));
+ break;
+#endif
+ case ACTION_TRUNCATE:
+ rval = truncate64(STR(0), NUM(1));
+ break;
+ case ACTION_FTRUNCATE:
+ rval = ftruncate64(NUM(0), NUM(1));
+ break;
+ case ACTION_STAT:
+ rval = stat64(STR(0), &sb);
+ if (rval == 0) {
+ show_stats(&sb, STR(1));
+ return (i);
+ }
+ break;
+ case ACTION_FSTAT:
+ rval = fstat64(NUM(0), &sb);
+ if (rval == 0) {
+ show_stats(&sb, STR(1));
+ return (i);
+ }
+ break;
+ case ACTION_LSTAT:
+ rval = lstat64(STR(0), &sb);
+ if (rval == 0) {
+ show_stats(&sb, STR(1));
+ return (i);
+ }
+ break;
+ case ACTION_FSTATAT:
+ rval = fstatat(NUM(0), STR(1), &sb,
+ (int)str2flags(fstatat_flags, STR(2)));
+ if (rval == 0) {
+ show_stats(&sb, STR(3));
+ return (i);
+ }
+ break;
+ case ACTION_PATHCONF:
+ case ACTION_FPATHCONF:
+#ifdef HAS_LPATHCONF
+ case ACTION_LPATHCONF:
+#endif
+ {
+ long lrval;
+
+ name = str2name(pathconf_names, STR(1));
+ if (name == -1) {
+ fprintf(stderr, "unknown name %s", STR(1));
+ exit(1);
+ }
+ errno = 0;
+ switch (scall->sd_action) {
+ case ACTION_PATHCONF:
+ lrval = pathconf(STR(0), name);
+ break;
+ case ACTION_FPATHCONF:
+ lrval = fpathconf(NUM(0), name);
+ break;
+#ifdef HAS_LPATHCONF
+ case ACTION_LPATHCONF:
+ lrval = lpathconf(STR(0), name);
+ break;
+#endif
+ default:
+ abort();
+ }
+ if (lrval == -1 && errno == 0) {
+ printf("unlimited\n");
+ return (i);
+ } else if (lrval >= 0) {
+ printf("%ld\n", lrval);
+ return (i);
+ }
+ rval = -1;
+ break;
+ }
+#ifdef HAS_FREEBSD_ACL
+ case ACTION_PREPENDACL:
+ rval = -1;
+
+ acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
+ if (acl == NULL)
+ break;
+
+ newacl = acl_from_text(STR(1));
+ if (acl == NULL)
+ break;
+
+ while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+
+ if (acl_create_entry_np(&acl, &entry, 0))
+ break;
+
+ if (acl_copy_entry(entry, newentry))
+ break;
+ }
+
+ rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
+ break;
+ case ACTION_READACL:
+ acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
+ if (acl == NULL)
+ rval = -1;
+ else
+ rval = 0;
+ break;
+#endif
+ case ACTION_WRITE:
+ rval = write(NUM(0), STR(1), strlen(STR(1)));
+ break;
+ default:
+ fprintf(stderr, "unsupported syscall\n");
+ exit(1);
+ }
+#undef STR
+#undef NUM
+ if (rval < 0) {
+ const char *serrno;
+
+ serrno = err2str(errno);
+ fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
+ printf("%s\n", serrno);
+ exit(1);
+ }
+ printf("0\n");
+ return (i);
+}
+
+static void
+set_gids(char *gids)
+{
+ gid_t *gidset;
+ long ngroups;
+ char *g, *endp;
+ unsigned i;
+
+ ngroups = sysconf(_SC_NGROUPS_MAX);
+ assert(ngroups > 0);
+ gidset = malloc(sizeof(*gidset) * ngroups);
+ assert(gidset != NULL);
+ for (i = 0, g = strtok(gids, ","); g != NULL;
+ g = strtok(NULL, ","), i++) {
+ if (i >= ngroups) {
+ fprintf(stderr, "too many gids\n");
+ exit(1);
+ }
+ gidset[i] = strtol(g, &endp, 0);
+ if (*endp != '\0' && !isspace((unsigned char)*endp)) {
+ fprintf(stderr, "invalid gid '%s' - number expected\n",
+ g);
+ exit(1);
+ }
+ }
+ if (setgroups(i, gidset) < 0) {
+ fprintf(stderr, "cannot change groups: %s\n", strerror(errno));
+ exit(1);
+ }
+ if (setegid(gidset[0]) < 0) {
+ fprintf(stderr, "cannot change effective gid: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ free(gidset);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct syscall_desc *scall;
+ unsigned int n;
+ char *gids, *endp;
+ int uid, umsk, ch;
+
+ uid = -1;
+ gids = NULL;
+ umsk = 0;
+
+ while ((ch = getopt(argc, argv, "g:u:U:")) != -1) {
+ switch(ch) {
+ case 'g':
+ gids = optarg;
+ break;
+ case 'u':
+ uid = (int)strtol(optarg, &endp, 0);
+ if (*endp != '\0' && !isspace((unsigned char)*endp)) {
+ fprintf(stderr, "invalid uid '%s' - number "
+ "expected\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'U':
+ umsk = (int)strtol(optarg, &endp, 0);
+ if (*endp != '\0' && !isspace((unsigned char)*endp)) {
+ fprintf(stderr, "invalid umask '%s' - number "
+ "expected\n", optarg);
+ exit(1);
+ }
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ fprintf(stderr, "too few arguments\n");
+ usage();
+ }
+
+ if (gids != NULL) {
+ fprintf(stderr, "changing groups to %s\n", gids);
+ set_gids(gids);
+ }
+ if (uid != -1) {
+ fprintf(stderr, "changing uid to %d\n", uid);
+ if (setuid(uid) < 0) {
+ fprintf(stderr, "cannot change uid: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
+
+ /* Change umask to requested value or to 0, if not requested. */
+ umask(umsk);
+
+ for (;;) {
+ scall = find_syscall(argv[0]);
+ if (scall == NULL) {
+ fprintf(stderr, "syscall '%s' not supported\n",
+ argv[0]);
+ exit(1);
+ }
+ argc++;
+ argv++;
+ n = call_syscall(scall, argv);
+ argc += n;
+ argv += n;
+ if (argv[0] == NULL)
+ break;
+ argc++;
+ argv++;
+ }
+
+ exit(0);
+}
+
+static const char *
+err2str(int error)
+{
+ static char errnum[8];
+
+ switch (error) {
+#ifdef EPERM
+ case EPERM:
+ return ("EPERM");
+#endif
+#ifdef ENOENT
+ case ENOENT:
+ return ("ENOENT");
+#endif
+#ifdef ESRCH
+ case ESRCH:
+ return ("ESRCH");
+#endif
+#ifdef EINTR
+ case EINTR:
+ return ("EINTR");
+#endif
+#ifdef EIO
+ case EIO:
+ return ("EIO");
+#endif
+#ifdef ENXIO
+ case ENXIO:
+ return ("ENXIO");
+#endif
+#ifdef E2BIG
+ case E2BIG:
+ return ("E2BIG");
+#endif
+#ifdef ENOEXEC
+ case ENOEXEC:
+ return ("ENOEXEC");
+#endif
+#ifdef EBADF
+ case EBADF:
+ return ("EBADF");
+#endif
+#ifdef ECHILD
+ case ECHILD:
+ return ("ECHILD");
+#endif
+#ifdef EDEADLK
+ case EDEADLK:
+ return ("EDEADLK");
+#endif
+#ifdef ENOMEM
+ case ENOMEM:
+ return ("ENOMEM");
+#endif
+#ifdef EACCES
+ case EACCES:
+ return ("EACCES");
+#endif
+#ifdef EFAULT
+ case EFAULT:
+ return ("EFAULT");
+#endif
+#ifdef ENOTBLK
+ case ENOTBLK:
+ return ("ENOTBLK");
+#endif
+#ifdef EBUSY
+ case EBUSY:
+ return ("EBUSY");
+#endif
+#ifdef EEXIST
+ case EEXIST:
+ return ("EEXIST");
+#endif
+#ifdef EXDEV
+ case EXDEV:
+ return ("EXDEV");
+#endif
+#ifdef ENODEV
+ case ENODEV:
+ return ("ENODEV");
+#endif
+#ifdef ENOTDIR
+ case ENOTDIR:
+ return ("ENOTDIR");
+#endif
+#ifdef EISDIR
+ case EISDIR:
+ return ("EISDIR");
+#endif
+#ifdef EINVAL
+ case EINVAL:
+ return ("EINVAL");
+#endif
+#ifdef ENFILE
+ case ENFILE:
+ return ("ENFILE");
+#endif
+#ifdef EMFILE
+ case EMFILE:
+ return ("EMFILE");
+#endif
+#ifdef ENOTTY
+ case ENOTTY:
+ return ("ENOTTY");
+#endif
+#ifdef ETXTBSY
+ case ETXTBSY:
+ return ("ETXTBSY");
+#endif
+#ifdef EFBIG
+ case EFBIG:
+ return ("EFBIG");
+#endif
+#ifdef ENOSPC
+ case ENOSPC:
+ return ("ENOSPC");
+#endif
+#ifdef ESPIPE
+ case ESPIPE:
+ return ("ESPIPE");
+#endif
+#ifdef EROFS
+ case EROFS:
+ return ("EROFS");
+#endif
+#ifdef EMLINK
+ case EMLINK:
+ return ("EMLINK");
+#endif
+#ifdef EPIPE
+ case EPIPE:
+ return ("EPIPE");
+#endif
+#ifdef EDOM
+ case EDOM:
+ return ("EDOM");
+#endif
+#ifdef ERANGE
+ case ERANGE:
+ return ("ERANGE");
+#endif
+#ifdef EAGAIN
+ case EAGAIN:
+ return ("EAGAIN");
+#endif
+#ifdef EINPROGRESS
+ case EINPROGRESS:
+ return ("EINPROGRESS");
+#endif
+#ifdef EALREADY
+ case EALREADY:
+ return ("EALREADY");
+#endif
+#ifdef ENOTSOCK
+ case ENOTSOCK:
+ return ("ENOTSOCK");
+#endif
+#ifdef EDESTADDRREQ
+ case EDESTADDRREQ:
+ return ("EDESTADDRREQ");
+#endif
+#ifdef EMSGSIZE
+ case EMSGSIZE:
+ return ("EMSGSIZE");
+#endif
+#ifdef EPROTOTYPE
+ case EPROTOTYPE:
+ return ("EPROTOTYPE");
+#endif
+#ifdef ENOPROTOOPT
+ case ENOPROTOOPT:
+ return ("ENOPROTOOPT");
+#endif
+#ifdef EPROTONOSUPPORT
+ case EPROTONOSUPPORT:
+ return ("EPROTONOSUPPORT");
+#endif
+#ifdef ESOCKTNOSUPPORT
+ case ESOCKTNOSUPPORT:
+ return ("ESOCKTNOSUPPORT");
+#endif
+#ifdef EOPNOTSUPP
+ case EOPNOTSUPP:
+ return ("EOPNOTSUPP");
+#endif
+#ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT:
+ return ("EPFNOSUPPORT");
+#endif
+#ifdef EAFNOSUPPORT
+ case EAFNOSUPPORT:
+ return ("EAFNOSUPPORT");
+#endif
+#ifdef EADDRINUSE
+ case EADDRINUSE:
+ return ("EADDRINUSE");
+#endif
+#ifdef EADDRNOTAVAIL
+ case EADDRNOTAVAIL:
+ return ("EADDRNOTAVAIL");
+#endif
+#ifdef ENETDOWN
+ case ENETDOWN:
+ return ("ENETDOWN");
+#endif
+#ifdef ENETUNREACH
+ case ENETUNREACH:
+ return ("ENETUNREACH");
+#endif
+#ifdef ENETRESET
+ case ENETRESET:
+ return ("ENETRESET");
+#endif
+#ifdef ECONNABORTED
+ case ECONNABORTED:
+ return ("ECONNABORTED");
+#endif
+#ifdef ECONNRESET
+ case ECONNRESET:
+ return ("ECONNRESET");
+#endif
+#ifdef ENOBUFS
+ case ENOBUFS:
+ return ("ENOBUFS");
+#endif
+#ifdef EISCONN
+ case EISCONN:
+ return ("EISCONN");
+#endif
+#ifdef ENOTCONN
+ case ENOTCONN:
+ return ("ENOTCONN");
+#endif
+#ifdef ESHUTDOWN
+ case ESHUTDOWN:
+ return ("ESHUTDOWN");
+#endif
+#ifdef ETOOMANYREFS
+ case ETOOMANYREFS:
+ return ("ETOOMANYREFS");
+#endif
+#ifdef ETIMEDOUT
+ case ETIMEDOUT:
+ return ("ETIMEDOUT");
+#endif
+#ifdef ECONNREFUSED
+ case ECONNREFUSED:
+ return ("ECONNREFUSED");
+#endif
+#ifdef ELOOP
+ case ELOOP:
+ return ("ELOOP");
+#endif
+#ifdef ENAMETOOLONG
+ case ENAMETOOLONG:
+ return ("ENAMETOOLONG");
+#endif
+#ifdef EHOSTDOWN
+ case EHOSTDOWN:
+ return ("EHOSTDOWN");
+#endif
+#ifdef EHOSTUNREACH
+ case EHOSTUNREACH:
+ return ("EHOSTUNREACH");
+#endif
+#ifdef ENOTEMPTY
+ case ENOTEMPTY:
+ return ("ENOTEMPTY");
+#endif
+#ifdef EPROCLIM
+ case EPROCLIM:
+ return ("EPROCLIM");
+#endif
+#ifdef EUSERS
+ case EUSERS:
+ return ("EUSERS");
+#endif
+#ifdef EDQUOT
+ case EDQUOT:
+ return ("EDQUOT");
+#endif
+#ifdef ESTALE
+ case ESTALE:
+ return ("ESTALE");
+#endif
+#ifdef EREMOTE
+ case EREMOTE:
+ return ("EREMOTE");
+#endif
+#ifdef EBADRPC
+ case EBADRPC:
+ return ("EBADRPC");
+#endif
+#ifdef ERPCMISMATCH
+ case ERPCMISMATCH:
+ return ("ERPCMISMATCH");
+#endif
+#ifdef EPROGUNAVAIL
+ case EPROGUNAVAIL:
+ return ("EPROGUNAVAIL");
+#endif
+#ifdef EPROGMISMATCH
+ case EPROGMISMATCH:
+ return ("EPROGMISMATCH");
+#endif
+#ifdef EPROCUNAVAIL
+ case EPROCUNAVAIL:
+ return ("EPROCUNAVAIL");
+#endif
+#ifdef ENOLCK
+ case ENOLCK:
+ return ("ENOLCK");
+#endif
+#ifdef ENOSYS
+ case ENOSYS:
+ return ("ENOSYS");
+#endif
+#ifdef EFTYPE
+ case EFTYPE:
+ return ("EFTYPE");
+#endif
+#ifdef EAUTH
+ case EAUTH:
+ return ("EAUTH");
+#endif
+#ifdef ENEEDAUTH
+ case ENEEDAUTH:
+ return ("ENEEDAUTH");
+#endif
+#ifdef EIDRM
+ case EIDRM:
+ return ("EIDRM");
+#endif
+#ifdef ENOMSG
+ case ENOMSG:
+ return ("ENOMSG");
+#endif
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ return ("EOVERFLOW");
+#endif
+#ifdef ECANCELED
+ case ECANCELED:
+ return ("ECANCELED");
+#endif
+#ifdef EILSEQ
+ case EILSEQ:
+ return ("EILSEQ");
+#endif
+#ifdef ENOATTR
+ case ENOATTR:
+ return ("ENOATTR");
+#endif
+#ifdef EDOOFUS
+ case EDOOFUS:
+ return ("EDOOFUS");
+#endif
+#ifdef EBADMSG
+ case EBADMSG:
+ return ("EBADMSG");
+#endif
+#ifdef EMULTIHOP
+ case EMULTIHOP:
+ return ("EMULTIHOP");
+#endif
+#ifdef ENOLINK
+ case ENOLINK:
+ return ("ENOLINK");
+#endif
+#ifdef EPROTO
+ case EPROTO:
+ return ("EPROTO");
+#endif
+ default:
+ snprintf(errnum, sizeof(errnum), "%d", error);
+ return (errnum);
+ }
+}
OpenPOWER on IntegriCloud