xref: /openbsd/regress/sys/ffs/fstest.c (revision fc61954a)
1 /*	$OpenBSD: fstest.c,v 1.4 2014/10/18 03:13:04 doug Exp $	*/
2 
3 /*
4  * Copyright (c) 2006-2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/tools/regression/fstest/fstest.c,v 1.1 2007/01/17 01:42:07 pjd Exp $
29  */
30 
31 #include <sys/param.h>
32 #include <sys/stat.h>
33 #include <sys/sysctl.h>
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <grp.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <errno.h>
43 #include <assert.h>
44 
45 enum action {
46 	ACTION_OPEN,
47 	ACTION_CREATE,
48 	ACTION_UNLINK,
49 	ACTION_MKDIR,
50 	ACTION_RMDIR,
51 	ACTION_LINK,
52 	ACTION_SYMLINK,
53 	ACTION_RENAME,
54 	ACTION_MKFIFO,
55 	ACTION_CHMOD,
56 	ACTION_CHOWN,
57 	ACTION_LCHOWN,
58 	ACTION_CHFLAGS,
59 	ACTION_TRUNCATE,
60 	ACTION_STAT,
61 	ACTION_LSTAT,
62 };
63 
64 #define	TYPE_NONE	0x0000
65 #define	TYPE_STRING	0x0001
66 #define	TYPE_NUMBER	0x0002
67 #define	TYPE_OPTIONAL	0x0100
68 #define	MAX_ARGS	8
69 
70 struct syscall_desc {
71 	char *sd_name;
72 	enum action  sd_action;
73 	int sd_args[MAX_ARGS];
74 };
75 
76 static struct syscall_desc syscalls[] = {
77 	{ "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING,
78 				 TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
79 	{ "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
80 	{ "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } },
81 	{ "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
82 	{ "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } },
83 	{ "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
84 	{ "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
85 	{ "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
86 	{ "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
87 	{ "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
88 	{ "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER,
89 				   TYPE_NUMBER, TYPE_NONE } },
90 	{ "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER,
91 				     TYPE_NUMBER, TYPE_NONE } },
92 	{ "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
93 	{ "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER,
94 					 TYPE_NONE } },
95 	{ "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
96 	{ "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
97 	{ NULL, -1, { TYPE_NONE } }
98 };
99 
100 struct flag {
101 	long long f_flag;
102 	char *f_str;
103 };
104 
105 static struct flag open_flags[] = {
106 	{ O_RDONLY, "O_RDONLY" },
107 	{ O_WRONLY, "O_WRONLY" },
108 	{ O_RDWR, "O_RDWR" },
109 	{ O_NONBLOCK, "O_NONBLOCK" },
110 	{ O_APPEND, "O_APPEND" },
111 	{ O_CREAT, "O_CREAT" },
112 	{ O_TRUNC, "O_TRUNC" },
113 	{ O_EXCL, "O_EXCL" },
114 	{ O_SHLOCK, "O_SHLOCK" },
115 	{ O_EXLOCK, "O_EXLOCK" },
116 	{ O_FSYNC, "O_FSYNC" },
117 	{ O_SYNC, "O_SYNC" },
118 	{ O_NOFOLLOW, "O_NOFOLLOW" },
119 	{ O_NOCTTY, "O_NOCTTY" },
120 	{ 0, NULL }
121 };
122 
123 static struct flag chflags_flags[] = {
124 	{ UF_NODUMP, "UF_NODUMP" },
125 	{ UF_IMMUTABLE, "UF_IMMUTABLE" },
126 	{ UF_APPEND, "UF_APPEND" },
127 	{ UF_OPAQUE, "UF_OPAQUE" },
128 	{ SF_ARCHIVED, "SF_ARCHIVED" },
129 	{ SF_IMMUTABLE, "SF_IMMUTABLE" },
130 	{ SF_APPEND, "SF_APPEND" },
131 	{ 0, NULL }
132 };
133 
134 static const char *err2str(int error);
135 int use_appimm;		/* use the SF_APPEND and SF_IMMUTABLE chflags */
136 
137 __dead static void
138 usage(void)
139 {
140 	fprintf(stderr, "usage: fstest [-u uid] [-g gid1[,gid2[...]]] syscall "
141 	    "args ...\n");
142 	exit(1);
143 }
144 
145 static long long
146 str2flags(struct flag *tflags, char *sflags)
147 {
148 	long long flags = 0;
149 	unsigned int i;
150 	char *f;
151 
152 	for (f = strtok(sflags, ","); f != NULL; f = strtok(NULL, ",")) {
153 		/* Support magic 'none' flag which just reset all flags. */
154 		if (strcmp(f, "none") == 0)
155 			return (0);
156 		for (i = 0; tflags[i].f_str != NULL; i++) {
157 			if (strcmp(tflags[i].f_str, f) == 0)
158 				break;
159 		}
160 		if (tflags[i].f_str == NULL) {
161 			fprintf(stderr, "unknown flag '%s'\n", f);
162 			exit(1);
163 		}
164 		flags |= tflags[i].f_flag;
165 	}
166 	return (flags);
167 }
168 
169 static char *
170 flags2str(struct flag *tflags, long long flags)
171 {
172 	static char sflags[1024];
173 	unsigned int i;
174 
175 	sflags[0] = '\0';
176 	for (i = 0; tflags[i].f_str != NULL; i++) {
177 		if (flags & tflags[i].f_flag) {
178 			if (sflags[0] != '\0')
179 				strlcat(sflags, ",", sizeof(sflags));
180 			strlcat(sflags, tflags[i].f_str, sizeof(sflags));
181 		}
182 	}
183 	if (sflags[0] == '\0')
184 		strlcpy(sflags, "none", sizeof(sflags));
185 	return (sflags);
186 }
187 
188 static struct syscall_desc *
189 find_syscall(const char *name)
190 {
191 	int i;
192 
193 	for (i = 0; syscalls[i].sd_name != NULL; i++) {
194 		if (strcmp(syscalls[i].sd_name, name) == 0)
195 			return (&syscalls[i]);
196 	}
197 	return (NULL);
198 }
199 
200 static void
201 show_stat(struct stat *sp, const char *what)
202 {
203 
204 	if (strcmp(what, "mode") == 0)
205 		printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS));
206 	else if (strcmp(what, "inode") == 0)
207 		printf("%llu", (unsigned long long)sp->st_ino);
208 	else if (strcmp(what, "nlink") == 0)
209 		printf("%lld", (long long)sp->st_nlink);
210 	else if (strcmp(what, "uid") == 0)
211 		printf("%d", (int)sp->st_uid);
212 	else if (strcmp(what, "gid") == 0)
213 		printf("%d", (int)sp->st_gid);
214 	else if (strcmp(what, "size") == 0)
215 		printf("%lld", (long long)sp->st_size);
216 	else if (strcmp(what, "blocks") == 0)
217 		printf("%lld", (long long)sp->st_blocks);
218 	else if (strcmp(what, "atime") == 0)
219 		printf("%lld", (long long)sp->st_atime);
220 	else if (strcmp(what, "mtime") == 0)
221 		printf("%lld", (long long)sp->st_mtime);
222 	else if (strcmp(what, "ctime") == 0)
223 		printf("%lld", (long long)sp->st_ctime);
224 	else if (strcmp(what, "flags") == 0)
225 		printf("%s", flags2str(chflags_flags, sp->st_flags));
226 	else if (strcmp(what, "type") == 0) {
227 		switch (sp->st_mode & S_IFMT) {
228 		case S_IFIFO:
229 			printf("fifo");
230 			break;
231 		case S_IFCHR:
232 			printf("char");
233 			break;
234 		case S_IFDIR:
235 			printf("dir");
236 			break;
237 		case S_IFBLK:
238 			printf("block");
239 			break;
240 		case S_IFREG:
241 			printf("regular");
242 			break;
243 		case S_IFLNK:
244 			printf("symlink");
245 			break;
246 		case S_IFSOCK:
247 			printf("socket");
248 			break;
249 		default:
250 			printf("unknown");
251 			break;
252 		}
253 	} else {
254 		printf("unknown");
255 	}
256 }
257 
258 static void
259 show_stats(struct stat *sp, char *what)
260 {
261 	const char *s = "";
262 	char *w;
263 
264 	for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) {
265 		printf("%s", s);
266 		show_stat(sp, w);
267 		s = ",";
268 	}
269 	printf("\n");
270 }
271 
272 static unsigned int
273 call_syscall(struct syscall_desc *scall, char *argv[])
274 {
275 	struct stat sb;
276 	long long flags;
277 	unsigned int i;
278 	char *endp;
279 	int rval;
280 	union {
281 		char *str;
282 		long long num;
283 	} args[MAX_ARGS];
284 	unsigned int ch_flags;
285 
286 	/*
287 	 * Verify correctness of the arguments.
288 	 */
289 	for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
290 		if (scall->sd_args[i] == TYPE_NONE) {
291 			if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
292 				break;
293 			fprintf(stderr, "too many arguments [%s]\n", argv[i]);
294 			exit(1);
295 		} else {
296 			if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
297 				if (scall->sd_args[i] & TYPE_OPTIONAL)
298 					break;
299 				fprintf(stderr, "too few arguments\n");
300 				exit(1);
301 			}
302 			if (scall->sd_args[i] & TYPE_STRING) {
303 				if (strcmp(argv[i], "NULL") == 0)
304 					args[i].str = NULL;
305 				else if (strcmp(argv[i], "DEADCODE") == 0)
306 					args[i].str = (void *)0xdeadc0de;
307 				else
308 					args[i].str = argv[i];
309 			} else if (scall->sd_args[i] & TYPE_NUMBER) {
310 				args[i].num = strtoll(argv[i], &endp, 0);
311 				if (*endp != '\0' &&
312 				    !isspace((unsigned char)*endp)) {
313 					fprintf(stderr, "invalid argument %u, "
314 					    "number expected [%s]\n", i, endp);
315 					exit(1);
316 				}
317 			}
318 		}
319 	}
320 	/*
321 	 * Call the given syscall.
322 	 */
323 #define	NUM(n)	(args[(n)].num)
324 #define	STR(n)	(args[(n)].str)
325 	switch (scall->sd_action) {
326 	case ACTION_OPEN:
327 		flags = str2flags(open_flags, STR(1));
328 		if (flags & O_CREAT) {
329 			if (i == 2) {
330 				fprintf(stderr, "too few arguments\n");
331 				exit(1);
332 			}
333 			rval = open(STR(0), flags, (mode_t)NUM(2));
334 		} else {
335 			if (i == 3) {
336 				fprintf(stderr, "too many arguments\n");
337 				exit(1);
338 			}
339 			rval = open(STR(0), flags);
340 		}
341 		break;
342 	case ACTION_CREATE:
343 		rval = open(STR(0), O_CREAT | O_EXCL, NUM(1));
344 		if (rval >= 0)
345 			close(rval);
346 		break;
347 	case ACTION_UNLINK:
348 		rval = unlink(STR(0));
349 		break;
350 	case ACTION_MKDIR:
351 		rval = mkdir(STR(0), NUM(1));
352 		break;
353 	case ACTION_RMDIR:
354 		rval = rmdir(STR(0));
355 		break;
356 	case ACTION_LINK:
357 		rval = link(STR(0), STR(1));
358 		break;
359 	case ACTION_SYMLINK:
360 		rval = symlink(STR(0), STR(1));
361 		break;
362 	case ACTION_RENAME:
363 		rval = rename(STR(0), STR(1));
364 		break;
365 	case ACTION_MKFIFO:
366 		rval = mkfifo(STR(0), NUM(1));
367 		break;
368 	case ACTION_CHMOD:
369 		rval = chmod(STR(0), NUM(1));
370 		break;
371 	case ACTION_CHOWN:
372 		rval = chown(STR(0), NUM(1), NUM(2));
373 		break;
374 	case ACTION_LCHOWN:
375 		rval = lchown(STR(0), NUM(1), NUM(2));
376 		break;
377 	case ACTION_CHFLAGS:
378 		ch_flags = str2flags(chflags_flags, STR(1));
379 		if (!use_appimm)
380 			ch_flags &= ~(SF_APPEND|SF_IMMUTABLE);
381 
382 		rval = chflags(STR(0), ch_flags);
383 		break;
384 	case ACTION_TRUNCATE:
385 		rval = truncate(STR(0), NUM(1));
386 		break;
387 	case ACTION_STAT:
388 		rval = stat(STR(0), &sb);
389 		if (rval == 0) {
390 			show_stats(&sb, STR(1));
391 			return (i);
392 		}
393 		break;
394 	case ACTION_LSTAT:
395 		rval = lstat(STR(0), &sb);
396 		if (rval == 0) {
397 			show_stats(&sb, STR(1));
398 			return (i);
399 		}
400 		break;
401 	default:
402 		fprintf(stderr, "unsupported syscall\n");
403 		exit(1);
404 	}
405 #undef STR
406 #undef NUM
407 	if (rval < 0) {
408 		const char *serrno;
409 
410 		serrno = err2str(errno);
411 		fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
412 		printf("%s\n", serrno);
413 		exit(1);
414 	}
415 	printf("0\n");
416 	return (i);
417 }
418 
419 static void
420 set_gids(char *gids)
421 {
422 	gid_t *gidset;
423 	long ngroups;
424 	char *g, *endp;
425 	unsigned i;
426 
427 	ngroups = sysconf(_SC_NGROUPS_MAX);
428 	assert(ngroups > 0);
429 	gidset = reallocarray(NULL, ngroups, sizeof(*gidset));
430 	assert(gidset != NULL);
431 	for (i = 0, g = strtok(gids, ","); g != NULL;
432 	    g = strtok(NULL, ","), i++) {
433 		if (i >= ngroups) {
434 			fprintf(stderr, "too many gids\n");
435 			exit(1);
436 		}
437 		gidset[i] = strtol(g, &endp, 0);
438 		if (*endp != '\0' && !isspace((unsigned char)*endp)) {
439 			fprintf(stderr, "invalid gid '%s' - number expected\n",
440 			    g);
441 			exit(1);
442 		}
443 	}
444 	if (setgroups(i, gidset) < 0) {
445 		fprintf(stderr, "cannot change groups: %s\n", strerror(errno));
446 		exit(1);
447 	}
448 	free(gidset);
449 }
450 
451 int
452 main(int argc, char *argv[])
453 {
454 	struct syscall_desc *scall;
455 	unsigned int n;
456 	char *gids, *endp;
457 	int uid, umsk, ch;
458 	int mib[2];
459 	size_t len;
460 	int securelevel;
461 
462 	uid = -1;
463 	gids = NULL;
464 	umsk = 0;
465 
466 	while ((ch = getopt(argc, argv, "g:u:U:")) != -1) {
467 		switch(ch) {
468 		case 'g':
469 			gids = optarg;
470 			break;
471 		case 'u':
472 			uid = (int)strtol(optarg, &endp, 0);
473 			if (*endp != '\0' && !isspace((unsigned char)*endp)) {
474 				fprintf(stderr, "invalid uid '%s' - number "
475 				    "expected\n", optarg);
476 				exit(1);
477 			}
478 			break;
479 		case 'U':
480 			umsk = (int)strtol(optarg, &endp, 0);
481 			if (*endp != '\0' && !isspace((unsigned char)*endp)) {
482 				fprintf(stderr, "invalid umask '%s' - number "
483 				    "expected\n", optarg);
484 				exit(1);
485 			}
486 			break;
487 		default:
488 			usage();
489 		}
490 	}
491 	argc -= optind;
492 	argv += optind;
493 
494 	if (argc < 1) {
495 		fprintf(stderr, "too few arguments\n");
496 		usage();
497 	}
498 
499 	if (gids != NULL) {
500 		fprintf(stderr, "changing groups to %s\n", gids);
501 		set_gids(gids);
502 	}
503 	if (uid != -1) {
504 		fprintf(stderr, "changing uid to %d\n", uid);
505 		if (setuid(uid) < 0) {
506 			fprintf(stderr, "cannot change uid: %s\n",
507 			    strerror(errno));
508 			exit(1);
509 		}
510 	}
511 
512 	/*
513 	 * Find out if we should use the SF_IMMUTABLE and SF_APPEND flags;
514 	 * Since we run by default on kern.securelevel=1 these cause false
515 	 * positives.
516 	 */
517 	mib[0] = CTL_KERN;
518 	mib[1] = KERN_SECURELVL;
519 	len = sizeof(securelevel);
520 	if (sysctl(mib, 2, &securelevel, &len, NULL, 0) == -1) {
521 		fprintf(stderr, "cannot get kernel securelevel\n");
522 		exit(1);
523 	}
524 	if (securelevel == 0 || securelevel == -1)
525 		use_appimm = 1;
526 	else
527 		use_appimm = 0;
528 
529 	/* Change umask to requested value or to 0, if not requested. */
530 	umask(umsk);
531 
532 	for (;;) {
533 		scall = find_syscall(argv[0]);
534 		if (scall == NULL) {
535 			fprintf(stderr, "syscall '%s' not supported\n", argv[0]);
536 			exit(1);
537 		}
538 		argc++;
539 		argv++;
540 		n = call_syscall(scall, argv);
541 		argc += n;
542 		argv += n;
543 		if (argv[0] == NULL)
544 			break;
545 		argc++;
546 		argv++;
547 	}
548 
549 	exit(0);
550 }
551 
552 static const char *
553 err2str(int error)
554 {
555 	static char errnum[8];
556 
557 	switch (error) {
558 	case EPERM:
559 		return ("EPERM");
560 	case ENOENT:
561 		return ("ENOENT");
562 	case ESRCH:
563 		return ("ESRCH");
564 	case EINTR:
565 		return ("EINTR");
566 	case EIO:
567 		return ("EIO");
568 	case ENXIO:
569 		return ("ENXIO");
570 	case E2BIG:
571 		return ("E2BIG");
572 	case ENOEXEC:
573 		return ("ENOEXEC");
574 	case EBADF:
575 		return ("EBADF");
576 	case ECHILD:
577 		return ("ECHILD");
578 	case EDEADLK:
579 		return ("EDEADLK");
580 	case ENOMEM:
581 		return ("ENOMEM");
582 	case EACCES:
583 		return ("EACCES");
584 	case EFAULT:
585 		return ("EFAULT");
586 	case ENOTBLK:
587 		return ("ENOTBLK");
588 	case EBUSY:
589 		return ("EBUSY");
590 	case EEXIST:
591 		return ("EEXIST");
592 	case EXDEV:
593 		return ("EXDEV");
594 	case ENODEV:
595 		return ("ENODEV");
596 	case ENOTDIR:
597 		return ("ENOTDIR");
598 	case EISDIR:
599 		return ("EISDIR");
600 	case EINVAL:
601 		return ("EINVAL");
602 	case ENFILE:
603 		return ("ENFILE");
604 	case EMFILE:
605 		return ("EMFILE");
606 	case ENOTTY:
607 		return ("ENOTTY");
608 	case ETXTBSY:
609 		return ("ETXTBSY");
610 	case EFBIG:
611 		return ("EFBIG");
612 	case ENOSPC:
613 		return ("ENOSPC");
614 	case ESPIPE:
615 		return ("ESPIPE");
616 	case EROFS:
617 		return ("EROFS");
618 	case EMLINK:
619 		return ("EMLINK");
620 	case EPIPE:
621 		return ("EPIPE");
622 	case EDOM:
623 		return ("EDOM");
624 	case ERANGE:
625 		return ("ERANGE");
626 	case EAGAIN:
627 		return ("EAGAIN");
628 	case EINPROGRESS:
629 		return ("EINPROGRESS");
630 	case EALREADY:
631 		return ("EALREADY");
632 	case ENOTSOCK:
633 		return ("ENOTSOCK");
634 	case EDESTADDRREQ:
635 		return ("EDESTADDRREQ");
636 	case EMSGSIZE:
637 		return ("EMSGSIZE");
638 	case EPROTOTYPE:
639 		return ("EPROTOTYPE");
640 	case ENOPROTOOPT:
641 		return ("ENOPROTOOPT");
642 	case EPROTONOSUPPORT:
643 		return ("EPROTONOSUPPORT");
644 	case ESOCKTNOSUPPORT:
645 		return ("ESOCKTNOSUPPORT");
646 	case EOPNOTSUPP:
647 		return ("EOPNOTSUPP");
648 	case EPFNOSUPPORT:
649 		return ("EPFNOSUPPORT");
650 	case EAFNOSUPPORT:
651 		return ("EAFNOSUPPORT");
652 	case EADDRINUSE:
653 		return ("EADDRINUSE");
654 	case EADDRNOTAVAIL:
655 		return ("EADDRNOTAVAIL");
656 	case ENETDOWN:
657 		return ("ENETDOWN");
658 	case ENETUNREACH:
659 		return ("ENETUNREACH");
660 	case ENETRESET:
661 		return ("ENETRESET");
662 	case ECONNABORTED:
663 		return ("ECONNABORTED");
664 	case ECONNRESET:
665 		return ("ECONNRESET");
666 	case ENOBUFS:
667 		return ("ENOBUFS");
668 	case EISCONN:
669 		return ("EISCONN");
670 	case ENOTCONN:
671 		return ("ENOTCONN");
672 	case ESHUTDOWN:
673 		return ("ESHUTDOWN");
674 	case ETOOMANYREFS:
675 		return ("ETOOMANYREFS");
676 	case ETIMEDOUT:
677 		return ("ETIMEDOUT");
678 	case ECONNREFUSED:
679 		return ("ECONNREFUSED");
680 	case ELOOP:
681 		return ("ELOOP");
682 	case ENAMETOOLONG:
683 		return ("ENAMETOOLONG");
684 	case EHOSTDOWN:
685 		return ("EHOSTDOWN");
686 	case EHOSTUNREACH:
687 		return ("EHOSTUNREACH");
688 	case ENOTEMPTY:
689 		return ("ENOTEMPTY");
690 	case EPROCLIM:
691 		return ("EPROCLIM");
692 	case EUSERS:
693 		return ("EUSERS");
694 	case EDQUOT:
695 		return ("EDQUOT");
696 	case ESTALE:
697 		return ("ESTALE");
698 	case EREMOTE:
699 		return ("EREMOTE");
700 	case EBADRPC:
701 		return ("EBADRPC");
702 	case ERPCMISMATCH:
703 		return ("ERPCMISMATCH");
704 	case EPROGUNAVAIL:
705 		return ("EPROGUNAVAIL");
706 	case EPROGMISMATCH:
707 		return ("EPROGMISMATCH");
708 	case EPROCUNAVAIL:
709 		return ("EPROCUNAVAIL");
710 	case ENOLCK:
711 		return ("ENOLCK");
712 	case ENOSYS:
713 		return ("ENOSYS");
714 	case EFTYPE:
715 		return ("EFTYPE");
716 	case EAUTH:
717 		return ("EAUTH");
718 	case ENEEDAUTH:
719 		return ("ENEEDAUTH");
720 	case EILSEQ:
721 		return ("EILSEQ");
722 	case ENOATTR:
723 		return ("ENOATTR");
724 	default:
725 		snprintf(errnum, sizeof(errnum), "%d", error);
726 		return (errnum);
727 	}
728 }
729