xref: /illumos-gate/usr/src/test/util-tests/tests/cpmvln/mkobj.c (revision 1ddc0273b2ca46ac2b55efc357739b7c4f8cafb1)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2024 Oxide Computer Company
14  */
15 
16 /*
17  * This is a utility program for the various cp/mv/ln tests to create file
18  * system objects which are not as simple with basic utilities. In particular we
19  * support creating bound unix domain sockets, doors, and throw in a fifo for
20  * good measure (though that's a bit easier).
21  */
22 
23 #include <err.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <door.h>
30 #include <stropts.h>
31 #include <string.h>
32 #include <sys/socket.h>
33 
34 static void
35 mkobj_server(void *cookie, char *argp, size_t size, door_desc_t *dp,
36     uint_t ndesc)
37 {
38 	(void) door_return(NULL, 0, NULL, 0);
39 }
40 
41 int
42 main(int argc, char *argv[])
43 {
44 	int c;
45 	const char *door = NULL;
46 	const char *fifo = NULL;
47 	const char *uds = NULL;
48 
49 	while ((c = getopt(argc, argv, ":d:f:s:")) != -1) {
50 		switch (c) {
51 		case 'd':
52 			door = optarg;
53 			break;
54 		case 'f':
55 			fifo = optarg;
56 			break;
57 		case 's':
58 			uds = optarg;
59 			break;
60 		case ':':
61 			errx(EXIT_FAILURE, "option -%c requires an operand", c);
62 		case '?':
63 			(void) fprintf(stderr, "unknown option: -%c\n", c);
64 			(void) fprintf(stderr, "mkobj [-d door] [-f fifo] "
65 			    "[-s socket]\n");
66 			exit(EXIT_FAILURE);
67 		}
68 	}
69 
70 	argv += optind;
71 	argc -= optind;
72 
73 	if (argc != 0) {
74 		errx(EXIT_FAILURE, "extraneous arguments starting with %s",
75 		    argv[0]);
76 	}
77 
78 	if (door == NULL && fifo == NULL && uds == NULL) {
79 		errx(EXIT_FAILURE, "at least one of -d, -f and -s must be "
80 		    "specified");
81 	}
82 
83 	if (door != NULL) {
84 		int fd;
85 
86 		if ((fd = open(door, O_CREAT | O_EXCL | O_RDWR, 0666)) < 0) {
87 			err(EXIT_FAILURE, "failed to create file %s for door "
88 			    "server attachment", door);
89 		}
90 
91 		(void) close(fd);
92 
93 		if ((fd = door_create(mkobj_server, NULL, DOOR_REFUSE_DESC |
94 		    DOOR_NO_CANCEL)) < 0) {
95 			err(EXIT_FAILURE, "failed to create door server");
96 		}
97 
98 		if (fattach(fd, door) != 0) {
99 			err(EXIT_FAILURE, "failed to attach door to %s", door);
100 		}
101 	}
102 
103 	if (fifo != NULL) {
104 		if (mkfifo(fifo, 0666) != 0) {
105 			err(EXIT_FAILURE, "failed to make fifo %s", fifo);
106 		}
107 	}
108 
109 	if (uds != NULL) {
110 		int fd;
111 		struct sockaddr_un un;
112 
113 		if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
114 			err(EXIT_FAILURE, "failed to create a unix domain "
115 			    "socket");
116 		}
117 
118 		(void) memset(&un, 0, sizeof (un));
119 		un.sun_family = AF_UNIX;
120 		if (strlcpy(un.sun_path, uds, sizeof (un.sun_path)) >=
121 		    sizeof (un.sun_path)) {
122 			errx(EXIT_FAILURE, "UDS path %s doesn't fit in "
123 			    "sockaddr sun_path", uds);
124 		}
125 
126 		if (bind(fd, (struct sockaddr *)&un, sizeof (un)) != 0) {
127 			errx(EXIT_FAILURE, "failed to bind uds to %s", uds);
128 		}
129 	}
130 
131 	/*
132 	 * Explicitly exit to ensure that we don't end up letting door threads
133 	 * stick around.
134 	 */
135 	exit(EXIT_SUCCESS);
136 }
137