]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/regression/pjdfstest/pjdfstest.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / regression / pjdfstest / pjdfstest.c
1 /*-
2  * Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/socket.h>
33 #include <sys/un.h>
34 #ifndef makedev
35 #include <sys/mkdev.h>
36 #endif
37
38 #include <assert.h>
39 #include <ctype.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <grp.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 #ifndef HAS_TRUNCATE64
49 #define truncate64      truncate
50 #define ftruncate64     ftruncate
51 #endif
52 #ifndef HAS_STAT64
53 #define stat64  stat
54 #define fstat64 fstat
55 #define lstat64 lstat
56 #endif
57 #ifdef HAS_FREEBSD_ACL
58 #include <sys/acl.h>
59 #endif
60
61 #ifndef ALLPERMS
62 #define ALLPERMS        (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
63 #endif
64
65 enum action {
66         ACTION_OPEN,
67         ACTION_OPENAT,
68         ACTION_CREATE,
69         ACTION_UNLINK,
70         ACTION_UNLINKAT,
71         ACTION_MKDIR,
72         ACTION_MKDIRAT,
73         ACTION_RMDIR,
74         ACTION_LINK,
75         ACTION_LINKAT,
76         ACTION_SYMLINK,
77         ACTION_SYMLINKAT,
78         ACTION_RENAME,
79         ACTION_RENAMEAT,
80         ACTION_MKFIFO,
81         ACTION_MKFIFOAT,
82         ACTION_MKNOD,
83         ACTION_MKNODAT,
84         ACTION_BIND,
85 #ifdef HAS_BINDAT
86         ACTION_BINDAT,
87 #endif
88         ACTION_CONNECT,
89 #ifdef HAS_CONNECTAT
90         ACTION_CONNECTAT,
91 #endif
92         ACTION_CHMOD,
93         ACTION_FCHMOD,
94 #ifdef HAS_LCHMOD
95         ACTION_LCHMOD,
96 #endif
97         ACTION_FCHMODAT,
98         ACTION_CHOWN,
99         ACTION_FCHOWN,
100         ACTION_LCHOWN,
101         ACTION_FCHOWNAT,
102 #ifdef HAS_CHFLAGS
103         ACTION_CHFLAGS,
104 #endif
105 #ifdef HAS_FCHFLAGS
106         ACTION_FCHFLAGS,
107 #endif
108 #ifdef HAS_CHFLAGSAT
109         ACTION_CHFLAGSAT,
110 #endif
111 #ifdef HAS_LCHFLAGS
112         ACTION_LCHFLAGS,
113 #endif
114         ACTION_TRUNCATE,
115         ACTION_FTRUNCATE,
116         ACTION_STAT,
117         ACTION_FSTAT,
118         ACTION_LSTAT,
119         ACTION_FSTATAT,
120         ACTION_PATHCONF,
121         ACTION_FPATHCONF,
122         ACTION_LPATHCONF,
123 #ifdef HAS_FREEBSD_ACL
124         ACTION_PREPENDACL,
125         ACTION_READACL,
126 #endif
127         ACTION_WRITE,
128 };
129
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
135
136 #define TYPE_OPTIONAL   0x0100
137
138 #define MAX_ARGS        8
139
140 struct syscall_desc {
141         const char      *sd_name;
142         enum action      sd_action;
143         int              sd_args[MAX_ARGS];
144 };
145
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 } },
166 #ifdef HAS_BINDAT
167         { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
168 #endif
169         { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } },
170 #ifdef HAS_CONNECTAT
171         { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
172 #endif
173         { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
174         { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
175 #ifdef HAS_LCHMOD
176         { "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
177 #endif
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 } },
183 #ifdef HAS_CHFLAGS
184         { "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
185 #endif
186 #ifdef HAS_FCHFLAGS
187         { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
188 #endif
189 #ifdef HAS_CHFLAGSAT
190         { "chflagsat", ACTION_CHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
191 #endif
192 #ifdef HAS_LCHFLAGS
193         { "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
194 #endif
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 } },
207 #endif
208         { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
209         { NULL, -1, { TYPE_NONE } }
210 };
211
212 struct flag {
213         long long        f_flag;
214         const char      *f_str;
215 };
216
217 static struct flag open_flags[] = {
218 #ifdef O_RDONLY
219         { O_RDONLY, "O_RDONLY" },
220 #endif
221 #ifdef O_WRONLY
222         { O_WRONLY, "O_WRONLY" },
223 #endif
224 #ifdef O_RDWR
225         { O_RDWR, "O_RDWR" },
226 #endif
227 #ifdef O_NONBLOCK
228         { O_NONBLOCK, "O_NONBLOCK" },
229 #endif
230 #ifdef O_APPEND
231         { O_APPEND, "O_APPEND" },
232 #endif
233 #ifdef O_CREAT
234         { O_CREAT, "O_CREAT" },
235 #endif
236 #ifdef O_TRUNC
237         { O_TRUNC, "O_TRUNC" },
238 #endif
239 #ifdef O_EXCL
240         { O_EXCL, "O_EXCL" },
241 #endif
242 #ifdef O_SHLOCK
243         { O_SHLOCK, "O_SHLOCK" },
244 #endif
245 #ifdef O_EXLOCK
246         { O_EXLOCK, "O_EXLOCK" },
247 #endif
248 #ifdef O_DIRECT
249         { O_DIRECT, "O_DIRECT" },
250 #endif
251 #ifdef O_FSYNC
252         { O_FSYNC, "O_FSYNC" },
253 #endif
254 #ifdef O_SYNC
255         { O_SYNC, "O_SYNC" },
256 #endif
257 #ifdef O_NOFOLLOW
258         { O_NOFOLLOW, "O_NOFOLLOW" },
259 #endif
260 #ifdef O_NOCTTY
261         { O_NOCTTY, "O_NOCTTY" },
262 #endif
263 #ifdef O_DIRECTORY
264         { O_DIRECTORY, "O_DIRECTORY" },
265 #endif
266         { 0, NULL }
267 };
268
269 #ifdef HAS_CHFLAGS
270 static struct flag chflags_flags[] = {
271 #ifdef UF_NODUMP
272         { UF_NODUMP, "UF_NODUMP" },
273 #endif
274 #ifdef UF_IMMUTABLE
275         { UF_IMMUTABLE, "UF_IMMUTABLE" },
276 #endif
277 #ifdef UF_APPEND
278         { UF_APPEND, "UF_APPEND" },
279 #endif
280 #ifdef UF_NOUNLINK
281         { UF_NOUNLINK, "UF_NOUNLINK" },
282 #endif
283 #ifdef UF_OPAQUE
284         { UF_OPAQUE, "UF_OPAQUE" },
285 #endif
286 #ifdef SF_ARCHIVED
287         { SF_ARCHIVED, "SF_ARCHIVED" },
288 #endif
289 #ifdef SF_IMMUTABLE
290         { SF_IMMUTABLE, "SF_IMMUTABLE" },
291 #endif
292 #ifdef SF_APPEND
293         { SF_APPEND, "SF_APPEND" },
294 #endif
295 #ifdef SF_NOUNLINK
296         { SF_NOUNLINK, "SF_NOUNLINK" },
297 #endif
298 #ifdef SF_SNAPSHOT
299         { SF_SNAPSHOT, "SF_SNAPSHOT" },
300 #endif
301         { 0, NULL }
302 };
303 #endif
304
305 static struct flag unlinkat_flags[] = {
306         { AT_REMOVEDIR, "AT_REMOVEDIR" },
307         { 0, NULL }
308 };
309
310 static struct flag linkat_flags[] = {
311         { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" },
312         { 0, NULL }
313 };
314
315 static struct flag chflagsat_flags[] = {
316         { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
317         { 0, NULL }
318 };
319
320 static struct flag fchmodat_flags[] = {
321         { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
322         { 0, NULL }
323 };
324
325 static struct flag fchownat_flags[] = {
326         { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
327         { 0, NULL }
328 };
329
330 static struct flag fstatat_flags[] = {
331         { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
332         { 0, NULL }
333 };
334
335 struct name {
336         int              n_name;
337         const char      *n_str;
338 };
339
340 static struct name pathconf_names[] = {
341 #ifdef _PC_LINK_MAX
342         { _PC_LINK_MAX, "_PC_LINK_MAX" },
343 #endif
344 #ifdef _PC_NAME_MAX
345         { _PC_NAME_MAX, "_PC_NAME_MAX" },
346 #endif
347 #ifdef _PC_PATH_MAX
348         { _PC_PATH_MAX, "_PC_PATH_MAX" },
349 #endif
350 #ifdef _PC_SYMLINK_MAX
351         { _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" },
352 #endif
353         { 0, NULL }
354 };
355
356 static const char *err2str(int error);
357
358 static int *descriptors;
359 static int ndescriptors;
360
361 static void
362 usage(void)
363 {
364
365         fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n");
366         exit(1);
367 }
368
369 static long long
370 str2flags(struct flag *tflags, char *sflags)
371 {
372         long long flags = 0;
373         unsigned int i;
374         char *f;
375
376         /* 'none' or '0' means no flags */
377         if (strcmp(sflags, "none") == 0 || strcmp(sflags, "0") == 0)
378                 return (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)
382                                 break;
383                 }
384                 if (tflags[i].f_str == NULL) {
385                         fprintf(stderr, "unknown flag '%s'\n", f);
386                         exit(1);
387                 }
388                 flags |= tflags[i].f_flag;
389         }
390         return (flags);
391 }
392
393 #ifdef HAS_CHFLAGS
394 static char *
395 flags2str(struct flag *tflags, long long flags)
396 {
397         static char sflags[1024];
398         unsigned int i;
399
400         sflags[0] = '\0';
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));
406                 }
407         }
408         if (sflags[0] == '\0')
409                 strlcpy(sflags, "none", sizeof(sflags));
410         return (sflags);
411 }
412 #endif
413
414 static int
415 str2name(struct name *names, char *name)
416 {
417         unsigned int i;
418
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);
422         }
423         return (-1);
424 }
425
426 static struct syscall_desc *
427 find_syscall(const char *name)
428 {
429         int i;
430
431         for (i = 0; syscalls[i].sd_name != NULL; i++) {
432                 if (strcmp(syscalls[i].sd_name, name) == 0)
433                         return (&syscalls[i]);
434         }
435         return (NULL);
436 }
437
438 static void
439 show_stat(struct stat64 *sp, const char *what)
440 {
441
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);
462 #ifdef HAS_CHFLAGS
463         else if (strcmp(what, "flags") == 0)
464                 printf("%s", flags2str(chflags_flags, (long long)sp->st_flags));
465 #endif
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) {
472                 case S_IFIFO:
473                         printf("fifo");
474                         break;
475                 case S_IFCHR:
476                         printf("char");
477                         break;
478                 case S_IFDIR:
479                         printf("dir");
480                         break;
481                 case S_IFBLK:
482                         printf("block");
483                         break;
484                 case S_IFREG:
485                         printf("regular");
486                         break;
487                 case S_IFLNK:
488                         printf("symlink");
489                         break;
490                 case S_IFSOCK:
491                         printf("socket");
492                         break;
493                 default:
494                         printf("unknown");
495                         break;
496                 }
497         } else {
498                 printf("unknown");
499         }
500 }
501
502 static void
503 show_stats(struct stat64 *sp, char *what)
504 {
505         const char *s = "";
506         char *w;
507
508         for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) {
509                 printf("%s", s);
510                 show_stat(sp, w);
511                 s = ",";
512         }
513         printf("\n");
514 }
515
516 static void
517 descriptor_add(int fd)
518 {
519
520         ndescriptors++;
521         if (descriptors == NULL) {
522                 descriptors = malloc(sizeof(descriptors[0]) * ndescriptors);
523         } else {
524                 descriptors = realloc(descriptors,
525                     sizeof(descriptors[0]) * ndescriptors);
526         }
527         assert(descriptors != NULL);
528         descriptors[ndescriptors - 1] = fd;
529 }
530
531 static int
532 descriptor_get(int pos)
533 {
534
535         if (pos < 0 || pos >= ndescriptors) {
536                 fprintf(stderr, "invalid descriptor %d\n", pos);
537                 exit(1);
538         }
539
540         return (descriptors[pos]);
541 }
542
543 static unsigned int
544 call_syscall(struct syscall_desc *scall, char *argv[])
545 {
546         struct stat64 sb;
547         long long flags;
548         unsigned int i;
549         char *endp;
550         int name, rval;
551         union {
552                 char *str;
553                 long long num;
554         } args[MAX_ARGS];
555 #ifdef HAS_FREEBSD_ACL
556         int entry_id = ACL_FIRST_ENTRY;
557         acl_t acl, newacl;
558         acl_entry_t entry, newentry;
559 #endif
560
561         /*
562          * Verify correctness of the arguments.
563          */
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)
567                                 break;
568                         fprintf(stderr, "too many arguments [%s]\n", argv[i]);
569                         exit(1);
570                 } else {
571                         if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
572                                 if (scall->sd_args[i] & TYPE_OPTIONAL)
573                                         break;
574                                 fprintf(stderr, "too few arguments\n");
575                                 exit(1);
576                         }
577                         if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
578                                 if (strcmp(argv[i], "NULL") == 0)
579                                         args[i].str = NULL;
580                                 else if (strcmp(argv[i], "DEADCODE") == 0)
581                                         args[i].str = (void *)0xdeadc0de;
582                                 else
583                                         args[i].str = argv[i];
584                         } else if ((scall->sd_args[i] & TYPE_MASK) ==
585                             TYPE_NUMBER) {
586                                 args[i].num = strtoll(argv[i], &endp, 0);
587                                 if (*endp != '\0' &&
588                                     !isspace((unsigned char)*endp)) {
589                                         fprintf(stderr,
590                                             "invalid argument %u, number expected [%s]\n",
591                                             i, endp);
592                                         exit(1);
593                                 }
594                         } else if ((scall->sd_args[i] & TYPE_MASK) ==
595                             TYPE_DESCRIPTOR) {
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... */
600                                         if (AT_FDCWD == -1)
601                                                 args[i].num = -2;
602                                         else
603                                                 args[i].num = -1;
604                                 } else {
605                                         int pos;
606
607                                         pos = strtoll(argv[i], &endp, 0);
608                                         if (*endp != '\0' &&
609                                             !isspace((unsigned char)*endp)) {
610                                                 fprintf(stderr,
611                                                     "invalid argument %u, number expected [%s]\n",
612                                                     i, endp);
613                                                 exit(1);
614                                         }
615                                         args[i].num = descriptor_get(pos);
616                                 }
617                         }
618                 }
619         }
620         /*
621          * Call the given syscall.
622          */
623 #define NUM(n)  (args[(n)].num)
624 #define STR(n)  (args[(n)].str)
625         switch (scall->sd_action) {
626         case ACTION_OPEN:
627                 flags = str2flags(open_flags, STR(1));
628                 if (flags & O_CREAT) {
629                         if (i == 2) {
630                                 fprintf(stderr, "too few arguments\n");
631                                 exit(1);
632                         }
633                         rval = open(STR(0), (int)flags, (mode_t)NUM(2));
634                 } else {
635                         if (i == 3) {
636                                 fprintf(stderr, "too many arguments\n");
637                                 exit(1);
638                         }
639                         rval = open(STR(0), (int)flags);
640                 }
641                 if (rval >= 0)
642                         descriptor_add(rval);
643                 break;
644         case ACTION_OPENAT:
645                 flags = str2flags(open_flags, STR(2));
646                 if (flags & O_CREAT) {
647                         if (i == 3) {
648                                 fprintf(stderr, "too few arguments\n");
649                                 exit(1);
650                         }
651                         rval = openat(NUM(0), STR(1), (int)flags,
652                             (mode_t)NUM(3));
653                 } else {
654                         if (i == 4) {
655                                 fprintf(stderr, "too many arguments\n");
656                                 exit(1);
657                         }
658                         rval = openat(NUM(0), STR(1), (int)flags);
659                 }
660                 if (rval >= 0)
661                         descriptor_add(rval);
662                 break;
663         case ACTION_CREATE:
664                 rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
665                 if (rval >= 0)
666                         close(rval);
667                 break;
668         case ACTION_UNLINK:
669                 rval = unlink(STR(0));
670                 break;
671         case ACTION_UNLINKAT:
672                 rval = unlinkat(NUM(0), STR(1),
673                     (int)str2flags(unlinkat_flags, STR(2)));
674                 break;
675         case ACTION_MKDIR:
676                 rval = mkdir(STR(0), (mode_t)NUM(1));
677                 break;
678         case ACTION_MKDIRAT:
679                 rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
680                 break;
681         case ACTION_RMDIR:
682                 rval = rmdir(STR(0));
683                 break;
684         case ACTION_LINK:
685                 rval = link(STR(0), STR(1));
686                 break;
687         case ACTION_LINKAT:
688                 rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
689                     (int)str2flags(linkat_flags, STR(4)));
690                 break;
691         case ACTION_SYMLINK:
692                 rval = symlink(STR(0), STR(1));
693                 break;
694         case ACTION_SYMLINKAT:
695                 rval = symlinkat(STR(0), NUM(1), STR(2));
696                 break;
697         case ACTION_RENAME:
698                 rval = rename(STR(0), STR(1));
699                 break;
700         case ACTION_RENAMEAT:
701                 rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
702                 break;
703         case ACTION_MKFIFO:
704                 rval = mkfifo(STR(0), (mode_t)NUM(1));
705                 break;
706         case ACTION_MKFIFOAT:
707                 rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
708                 break;
709         case ACTION_MKNOD:
710         case ACTION_MKNODAT:
711             {
712                 mode_t ntype;
713                 dev_t dev;
714                 int fa;
715
716                 switch (scall->sd_action) {
717                 case ACTION_MKNOD:
718                         fa = 0;
719                         break;
720                 case ACTION_MKNODAT:
721                         fa = 1;
722                         break;
723                 default:
724                         abort();
725                 }
726
727                 dev = makedev(NUM(fa + 3), NUM(fa + 4));
728                 if (strcmp(STR(fa + 1), "c") == 0)      /* character device */
729                         ntype = S_IFCHR;
730                 else if (strcmp(STR(fa + 1), "b") == 0) /* block device */
731                         ntype = S_IFBLK;
732                 else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */
733                         ntype = S_IFIFO;
734                 else if (strcmp(STR(fa + 1), "d") == 0) /* directory */
735                         ntype = S_IFDIR;
736                 else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */
737                         ntype = S_IFREG;
738                 else {
739                         fprintf(stderr, "wrong argument 1\n");
740                         exit(1);
741                 }
742                 switch (scall->sd_action) {
743                 case ACTION_MKNOD:
744                         rval = mknod(STR(0), ntype | NUM(2), dev);
745                         break;
746                 case ACTION_MKNODAT:
747                         rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
748                         break;
749                 default:
750                         abort();
751                 }
752                 break;
753             }
754         case ACTION_BIND:
755             {
756                 struct sockaddr_un sunx;
757
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);
762                 if (rval < 0)
763                         break;
764                 rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
765                 break;
766             }
767 #ifdef HAS_BINDAT
768         case ACTION_BINDAT:
769             {
770                 struct sockaddr_un sunx;
771
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);
776                 if (rval < 0)
777                         break;
778                 rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
779                     sizeof(sunx));
780                 break;
781             }
782 #endif
783         case ACTION_CONNECT:
784             {
785                 struct sockaddr_un sunx;
786
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);
791                 if (rval < 0)
792                         break;
793                 rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
794                 break;
795             }
796 #ifdef HAS_CONNECTAT
797         case ACTION_CONNECTAT:
798             {
799                 struct sockaddr_un sunx;
800
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);
805                 if (rval < 0)
806                         break;
807                 rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
808                     sizeof(sunx));
809                 break;
810             }
811 #endif
812         case ACTION_CHMOD:
813                 rval = chmod(STR(0), (mode_t)NUM(1));
814                 break;
815         case ACTION_FCHMOD:
816                 rval = fchmod(NUM(0), (mode_t)NUM(1));
817                 break;
818 #ifdef HAS_LCHMOD
819         case ACTION_LCHMOD:
820                 rval = lchmod(STR(0), (mode_t)NUM(1));
821                 break;
822 #endif
823         case ACTION_FCHMODAT:
824                 rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
825                     str2flags(fchmodat_flags, STR(3)));
826                 break;
827         case ACTION_CHOWN:
828                 rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
829                 break;
830         case ACTION_FCHOWN:
831                 rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
832                 break;
833         case ACTION_LCHOWN:
834                 rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
835                 break;
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)));
839                 break;
840 #ifdef HAS_CHFLAGS
841         case ACTION_CHFLAGS:
842                 rval = chflags(STR(0),
843                     (unsigned long)str2flags(chflags_flags, STR(1)));
844                 break;
845 #endif
846 #ifdef HAS_FCHFLAGS
847         case ACTION_FCHFLAGS:
848                 rval = fchflags(NUM(0),
849                     (unsigned long)str2flags(chflags_flags, STR(1)));
850                 break;
851 #endif
852 #ifdef HAS_CHFLAGSAT
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)));
857                 break;
858 #endif
859 #ifdef HAS_LCHFLAGS
860         case ACTION_LCHFLAGS:
861                 rval = lchflags(STR(0),
862                     (unsigned long)str2flags(chflags_flags, STR(1)));
863                 break;
864 #endif
865         case ACTION_TRUNCATE:
866                 rval = truncate64(STR(0), NUM(1));
867                 break;
868         case ACTION_FTRUNCATE:
869                 rval = ftruncate64(NUM(0), NUM(1));
870                 break;
871         case ACTION_STAT:
872                 rval = stat64(STR(0), &sb);
873                 if (rval == 0) {
874                         show_stats(&sb, STR(1));
875                         return (i);
876                 }
877                 break;
878         case ACTION_FSTAT:
879                 rval = fstat64(NUM(0), &sb);
880                 if (rval == 0) {
881                         show_stats(&sb, STR(1));
882                         return (i);
883                 }
884                 break;
885         case ACTION_LSTAT:
886                 rval = lstat64(STR(0), &sb);
887                 if (rval == 0) {
888                         show_stats(&sb, STR(1));
889                         return (i);
890                 }
891                 break;
892         case ACTION_FSTATAT:
893                 rval = fstatat(NUM(0), STR(1), &sb,
894                     (int)str2flags(fstatat_flags, STR(2)));
895                 if (rval == 0) {
896                         show_stats(&sb, STR(3));
897                         return (i);
898                 }
899                 break;
900         case ACTION_PATHCONF:
901         case ACTION_FPATHCONF:
902         case ACTION_LPATHCONF:
903             {
904                 long lrval;
905
906                 name = str2name(pathconf_names, STR(1));
907                 if (name == -1) {
908                         fprintf(stderr, "unknown name %s", STR(1));
909                         exit(1);
910                 }
911                 errno = 0;
912                 switch (scall->sd_action) {
913                 case ACTION_PATHCONF:
914                         lrval = pathconf(STR(0), name);
915                         break;
916                 case ACTION_FPATHCONF:
917                         lrval = fpathconf(NUM(0), name);
918                         break;
919                 case ACTION_LPATHCONF:
920                         lrval = lpathconf(STR(0), name);
921                         break;
922                 default:
923                         abort();
924                 }
925                 if (lrval == -1 && errno == 0) {
926                         printf("unlimited\n");
927                         return (i);
928                 } else if (lrval >= 0) {
929                         printf("%ld\n", lrval);
930                         return (i);
931                 }
932                 rval = -1;
933                 break;
934             }
935 #ifdef HAS_FREEBSD_ACL
936         case ACTION_PREPENDACL:
937                 rval = -1;
938
939                 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
940                 if (acl == NULL)
941                         break;
942
943                 newacl = acl_from_text(STR(1));
944                 if (acl == NULL)
945                         break;
946
947                 while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
948                         entry_id = ACL_NEXT_ENTRY;
949
950                         if (acl_create_entry_np(&acl, &entry, 0))
951                                 break;
952
953                         if (acl_copy_entry(entry, newentry))
954                                 break;
955                 }
956
957                 rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
958                 break;
959         case ACTION_READACL:
960                 acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
961                 if (acl == NULL)
962                         rval = -1;
963                 else
964                         rval = 0;
965                 break;
966 #endif
967         case ACTION_WRITE:
968                 rval = write(NUM(0), STR(1), strlen(STR(1)));
969                 break;
970         default:
971                 fprintf(stderr, "unsupported syscall\n");
972                 exit(1);
973         }
974 #undef STR
975 #undef NUM
976         if (rval < 0) {
977                 const char *serrno;
978
979                 serrno = err2str(errno);
980                 fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
981                 printf("%s\n", serrno);
982                 exit(1);
983         }
984         printf("0\n");
985         return (i);
986 }
987
988 static void
989 set_gids(char *gids)
990 {
991         gid_t *gidset;
992         long ngroups;
993         char *g, *endp;
994         unsigned i;
995
996         ngroups = sysconf(_SC_NGROUPS_MAX);
997         assert(ngroups > 0);
998         gidset = malloc(sizeof(*gidset) * ngroups);
999         assert(gidset != NULL);
1000         for (i = 0, g = strtok(gids, ","); g != NULL;
1001             g = strtok(NULL, ","), i++) {
1002                 if (i >= ngroups) {
1003                         fprintf(stderr, "too many gids\n");
1004                         exit(1);
1005                 }
1006                 gidset[i] = strtol(g, &endp, 0);
1007                 if (*endp != '\0' && !isspace((unsigned char)*endp)) {
1008                         fprintf(stderr, "invalid gid '%s' - number expected\n",
1009                             g);
1010                         exit(1);
1011                 }
1012         }
1013         if (setgroups(i, gidset) < 0) {
1014                 fprintf(stderr, "cannot change groups: %s\n", strerror(errno));
1015                 exit(1);
1016         }
1017         if (setegid(gidset[0]) < 0) {
1018                 fprintf(stderr, "cannot change effective gid: %s\n",
1019                     strerror(errno));
1020                 exit(1);
1021         }
1022         free(gidset);
1023 }
1024
1025 int
1026 main(int argc, char *argv[])
1027 {
1028         struct syscall_desc *scall;
1029         unsigned int n;
1030         char *gids, *endp;
1031         int uid, umsk, ch;
1032
1033         uid = -1;
1034         gids = NULL;
1035         umsk = 0;
1036
1037         while ((ch = getopt(argc, argv, "g:u:U:")) != -1) {
1038                 switch(ch) {
1039                 case 'g':
1040                         gids = optarg;
1041                         break;
1042                 case 'u':
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);
1047                                 exit(1);
1048                         }
1049                         break;
1050                 case 'U':
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);
1055                                 exit(1);
1056                         }
1057                         break;
1058                 default:
1059                         usage();
1060                 }
1061         }
1062         argc -= optind;
1063         argv += optind;
1064
1065         if (argc < 1) {
1066                 fprintf(stderr, "too few arguments\n");
1067                 usage();
1068         }
1069
1070         if (gids != NULL) {
1071                 fprintf(stderr, "changing groups to %s\n", gids);
1072                 set_gids(gids);
1073         }
1074         if (uid != -1) {
1075                 fprintf(stderr, "changing uid to %d\n", uid);
1076                 if (setuid(uid) < 0) {
1077                         fprintf(stderr, "cannot change uid: %s\n",
1078                             strerror(errno));
1079                         exit(1);
1080                 }
1081         }
1082
1083         /* Change umask to requested value or to 0, if not requested. */
1084         umask(umsk);
1085
1086         for (;;) {
1087                 scall = find_syscall(argv[0]);
1088                 if (scall == NULL) {
1089                         fprintf(stderr, "syscall '%s' not supported\n",
1090                             argv[0]);
1091                         exit(1);
1092                 }
1093                 argc++;
1094                 argv++;
1095                 n = call_syscall(scall, argv);
1096                 argc += n;
1097                 argv += n;
1098                 if (argv[0] == NULL)
1099                         break;
1100                 argc++;
1101                 argv++;
1102         }
1103
1104         exit(0);
1105 }
1106
1107 static const char *
1108 err2str(int error)
1109 {
1110         static char errnum[8];
1111
1112         switch (error) {
1113 #ifdef EPERM
1114         case EPERM:
1115                 return ("EPERM");
1116 #endif
1117 #ifdef ENOENT
1118         case ENOENT:
1119                 return ("ENOENT");
1120 #endif
1121 #ifdef ESRCH
1122         case ESRCH:
1123                 return ("ESRCH");
1124 #endif
1125 #ifdef EINTR
1126         case EINTR:
1127                 return ("EINTR");
1128 #endif
1129 #ifdef EIO
1130         case EIO:
1131                 return ("EIO");
1132 #endif
1133 #ifdef ENXIO
1134         case ENXIO:
1135                 return ("ENXIO");
1136 #endif
1137 #ifdef E2BIG
1138         case E2BIG:
1139                 return ("E2BIG");
1140 #endif
1141 #ifdef ENOEXEC
1142         case ENOEXEC:
1143                 return ("ENOEXEC");
1144 #endif
1145 #ifdef EBADF
1146         case EBADF:
1147                 return ("EBADF");
1148 #endif
1149 #ifdef ECHILD
1150         case ECHILD:
1151                 return ("ECHILD");
1152 #endif
1153 #ifdef EDEADLK
1154         case EDEADLK:
1155                 return ("EDEADLK");
1156 #endif
1157 #ifdef ENOMEM
1158         case ENOMEM:
1159                 return ("ENOMEM");
1160 #endif
1161 #ifdef EACCES
1162         case EACCES:
1163                 return ("EACCES");
1164 #endif
1165 #ifdef EFAULT
1166         case EFAULT:
1167                 return ("EFAULT");
1168 #endif
1169 #ifdef ENOTBLK
1170         case ENOTBLK:
1171                 return ("ENOTBLK");
1172 #endif
1173 #ifdef EBUSY
1174         case EBUSY:
1175                 return ("EBUSY");
1176 #endif
1177 #ifdef EEXIST
1178         case EEXIST:
1179                 return ("EEXIST");
1180 #endif
1181 #ifdef EXDEV
1182         case EXDEV:
1183                 return ("EXDEV");
1184 #endif
1185 #ifdef ENODEV
1186         case ENODEV:
1187                 return ("ENODEV");
1188 #endif
1189 #ifdef ENOTDIR
1190         case ENOTDIR:
1191                 return ("ENOTDIR");
1192 #endif
1193 #ifdef EISDIR
1194         case EISDIR:
1195                 return ("EISDIR");
1196 #endif
1197 #ifdef EINVAL
1198         case EINVAL:
1199                 return ("EINVAL");
1200 #endif
1201 #ifdef ENFILE
1202         case ENFILE:
1203                 return ("ENFILE");
1204 #endif
1205 #ifdef EMFILE
1206         case EMFILE:
1207                 return ("EMFILE");
1208 #endif
1209 #ifdef ENOTTY
1210         case ENOTTY:
1211                 return ("ENOTTY");
1212 #endif
1213 #ifdef ETXTBSY
1214         case ETXTBSY:
1215                 return ("ETXTBSY");
1216 #endif
1217 #ifdef EFBIG
1218         case EFBIG:
1219                 return ("EFBIG");
1220 #endif
1221 #ifdef ENOSPC
1222         case ENOSPC:
1223                 return ("ENOSPC");
1224 #endif
1225 #ifdef ESPIPE
1226         case ESPIPE:
1227                 return ("ESPIPE");
1228 #endif
1229 #ifdef EROFS
1230         case EROFS:
1231                 return ("EROFS");
1232 #endif
1233 #ifdef EMLINK
1234         case EMLINK:
1235                 return ("EMLINK");
1236 #endif
1237 #ifdef EPIPE
1238         case EPIPE:
1239                 return ("EPIPE");
1240 #endif
1241 #ifdef EDOM
1242         case EDOM:
1243                 return ("EDOM");
1244 #endif
1245 #ifdef ERANGE
1246         case ERANGE:
1247                 return ("ERANGE");
1248 #endif
1249 #ifdef EAGAIN
1250         case EAGAIN:
1251                 return ("EAGAIN");
1252 #endif
1253 #ifdef EINPROGRESS
1254         case EINPROGRESS:
1255                 return ("EINPROGRESS");
1256 #endif
1257 #ifdef EALREADY
1258         case EALREADY:
1259                 return ("EALREADY");
1260 #endif
1261 #ifdef ENOTSOCK
1262         case ENOTSOCK:
1263                 return ("ENOTSOCK");
1264 #endif
1265 #ifdef EDESTADDRREQ
1266         case EDESTADDRREQ:
1267                 return ("EDESTADDRREQ");
1268 #endif
1269 #ifdef EMSGSIZE
1270         case EMSGSIZE:
1271                 return ("EMSGSIZE");
1272 #endif
1273 #ifdef EPROTOTYPE
1274         case EPROTOTYPE:
1275                 return ("EPROTOTYPE");
1276 #endif
1277 #ifdef ENOPROTOOPT
1278         case ENOPROTOOPT:
1279                 return ("ENOPROTOOPT");
1280 #endif
1281 #ifdef EPROTONOSUPPORT
1282         case EPROTONOSUPPORT:
1283                 return ("EPROTONOSUPPORT");
1284 #endif
1285 #ifdef ESOCKTNOSUPPORT
1286         case ESOCKTNOSUPPORT:
1287                 return ("ESOCKTNOSUPPORT");
1288 #endif
1289 #ifdef EOPNOTSUPP
1290         case EOPNOTSUPP:
1291                 return ("EOPNOTSUPP");
1292 #endif
1293 #ifdef EPFNOSUPPORT
1294         case EPFNOSUPPORT:
1295                 return ("EPFNOSUPPORT");
1296 #endif
1297 #ifdef EAFNOSUPPORT
1298         case EAFNOSUPPORT:
1299                 return ("EAFNOSUPPORT");
1300 #endif
1301 #ifdef EADDRINUSE
1302         case EADDRINUSE:
1303                 return ("EADDRINUSE");
1304 #endif
1305 #ifdef EADDRNOTAVAIL
1306         case EADDRNOTAVAIL:
1307                 return ("EADDRNOTAVAIL");
1308 #endif
1309 #ifdef ENETDOWN
1310         case ENETDOWN:
1311                 return ("ENETDOWN");
1312 #endif
1313 #ifdef ENETUNREACH
1314         case ENETUNREACH:
1315                 return ("ENETUNREACH");
1316 #endif
1317 #ifdef ENETRESET
1318         case ENETRESET:
1319                 return ("ENETRESET");
1320 #endif
1321 #ifdef ECONNABORTED
1322         case ECONNABORTED:
1323                 return ("ECONNABORTED");
1324 #endif
1325 #ifdef ECONNRESET
1326         case ECONNRESET:
1327                 return ("ECONNRESET");
1328 #endif
1329 #ifdef ENOBUFS
1330         case ENOBUFS:
1331                 return ("ENOBUFS");
1332 #endif
1333 #ifdef EISCONN
1334         case EISCONN:
1335                 return ("EISCONN");
1336 #endif
1337 #ifdef ENOTCONN
1338         case ENOTCONN:
1339                 return ("ENOTCONN");
1340 #endif
1341 #ifdef ESHUTDOWN
1342         case ESHUTDOWN:
1343                 return ("ESHUTDOWN");
1344 #endif
1345 #ifdef ETOOMANYREFS
1346         case ETOOMANYREFS:
1347                 return ("ETOOMANYREFS");
1348 #endif
1349 #ifdef ETIMEDOUT
1350         case ETIMEDOUT:
1351                 return ("ETIMEDOUT");
1352 #endif
1353 #ifdef ECONNREFUSED
1354         case ECONNREFUSED:
1355                 return ("ECONNREFUSED");
1356 #endif
1357 #ifdef ELOOP
1358         case ELOOP:
1359                 return ("ELOOP");
1360 #endif
1361 #ifdef ENAMETOOLONG
1362         case ENAMETOOLONG:
1363                 return ("ENAMETOOLONG");
1364 #endif
1365 #ifdef EHOSTDOWN
1366         case EHOSTDOWN:
1367                 return ("EHOSTDOWN");
1368 #endif
1369 #ifdef EHOSTUNREACH
1370         case EHOSTUNREACH:
1371                 return ("EHOSTUNREACH");
1372 #endif
1373 #ifdef ENOTEMPTY
1374         case ENOTEMPTY:
1375                 return ("ENOTEMPTY");
1376 #endif
1377 #ifdef EPROCLIM
1378         case EPROCLIM:
1379                 return ("EPROCLIM");
1380 #endif
1381 #ifdef EUSERS
1382         case EUSERS:
1383                 return ("EUSERS");
1384 #endif
1385 #ifdef EDQUOT
1386         case EDQUOT:
1387                 return ("EDQUOT");
1388 #endif
1389 #ifdef ESTALE
1390         case ESTALE:
1391                 return ("ESTALE");
1392 #endif
1393 #ifdef EREMOTE
1394         case EREMOTE:
1395                 return ("EREMOTE");
1396 #endif
1397 #ifdef EBADRPC
1398         case EBADRPC:
1399                 return ("EBADRPC");
1400 #endif
1401 #ifdef ERPCMISMATCH
1402         case ERPCMISMATCH:
1403                 return ("ERPCMISMATCH");
1404 #endif
1405 #ifdef EPROGUNAVAIL
1406         case EPROGUNAVAIL:
1407                 return ("EPROGUNAVAIL");
1408 #endif
1409 #ifdef EPROGMISMATCH
1410         case EPROGMISMATCH:
1411                 return ("EPROGMISMATCH");
1412 #endif
1413 #ifdef EPROCUNAVAIL
1414         case EPROCUNAVAIL:
1415                 return ("EPROCUNAVAIL");
1416 #endif
1417 #ifdef ENOLCK
1418         case ENOLCK:
1419                 return ("ENOLCK");
1420 #endif
1421 #ifdef ENOSYS
1422         case ENOSYS:
1423                 return ("ENOSYS");
1424 #endif
1425 #ifdef EFTYPE
1426         case EFTYPE:
1427                 return ("EFTYPE");
1428 #endif
1429 #ifdef EAUTH
1430         case EAUTH:
1431                 return ("EAUTH");
1432 #endif
1433 #ifdef ENEEDAUTH
1434         case ENEEDAUTH:
1435                 return ("ENEEDAUTH");
1436 #endif
1437 #ifdef EIDRM
1438         case EIDRM:
1439                 return ("EIDRM");
1440 #endif
1441 #ifdef ENOMSG
1442         case ENOMSG:
1443                 return ("ENOMSG");
1444 #endif
1445 #ifdef EOVERFLOW
1446         case EOVERFLOW:
1447                 return ("EOVERFLOW");
1448 #endif
1449 #ifdef ECANCELED
1450         case ECANCELED:
1451                 return ("ECANCELED");
1452 #endif
1453 #ifdef EILSEQ
1454         case EILSEQ:
1455                 return ("EILSEQ");
1456 #endif
1457 #ifdef ENOATTR
1458         case ENOATTR:
1459                 return ("ENOATTR");
1460 #endif
1461 #ifdef EDOOFUS
1462         case EDOOFUS:
1463                 return ("EDOOFUS");
1464 #endif
1465 #ifdef EBADMSG
1466         case EBADMSG:
1467                 return ("EBADMSG");
1468 #endif
1469 #ifdef EMULTIHOP
1470         case EMULTIHOP:
1471                 return ("EMULTIHOP");
1472 #endif
1473 #ifdef ENOLINK
1474         case ENOLINK:
1475                 return ("ENOLINK");
1476 #endif
1477 #ifdef EPROTO
1478         case EPROTO:
1479                 return ("EPROTO");
1480 #endif
1481         default:
1482                 snprintf(errnum, sizeof(errnum), "%d", error);
1483                 return (errnum);
1484         }
1485 }