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