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