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