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
usage(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
str2flags(struct flag * tflags,char * sflags)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 *
flags2str(struct flag * tflags,long long flags)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
str2name(struct name * names,char * name)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 *
find_syscall(const char * name)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
show_stat(struct stat64 * sp,const char * what)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
show_stats(struct stat64 * sp,char * what)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
descriptor_add(int fd)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
descriptor_get(int pos)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
call_syscall(struct syscall_desc * scall,char * argv[])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
set_gids(char * gids)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
main(int argc,char * argv[])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 *
err2str(int error)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 }
1494