1*36626562SRobert Mustacchi /*
2*36626562SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*36626562SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*36626562SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*36626562SRobert Mustacchi * 1.0 of the CDDL.
6*36626562SRobert Mustacchi *
7*36626562SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*36626562SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*36626562SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*36626562SRobert Mustacchi */
11*36626562SRobert Mustacchi
12*36626562SRobert Mustacchi /*
13*36626562SRobert Mustacchi * Copyright 2020 Robert Mustacchi
14*36626562SRobert Mustacchi */
15*36626562SRobert Mustacchi
16*36626562SRobert Mustacchi /*
17*36626562SRobert Mustacchi * Test different O_DIRECTORY open cases.
18*36626562SRobert Mustacchi */
19*36626562SRobert Mustacchi
20*36626562SRobert Mustacchi #include <sys/types.h>
21*36626562SRobert Mustacchi #include <sys/stat.h>
22*36626562SRobert Mustacchi #include <fcntl.h>
23*36626562SRobert Mustacchi #include <stdio.h>
24*36626562SRobert Mustacchi #include <errno.h>
25*36626562SRobert Mustacchi #include <unistd.h>
26*36626562SRobert Mustacchi #include <err.h>
27*36626562SRobert Mustacchi #include <string.h>
28*36626562SRobert Mustacchi #include <stdlib.h>
29*36626562SRobert Mustacchi #include <limits.h>
30*36626562SRobert Mustacchi #include <door.h>
31*36626562SRobert Mustacchi #include <stropts.h>
32*36626562SRobert Mustacchi #include <sys/socket.h>
33*36626562SRobert Mustacchi
34*36626562SRobert Mustacchi static uint_t odir_failures;
35*36626562SRobert Mustacchi static char odir_fpath[PATH_MAX];
36*36626562SRobert Mustacchi static char odir_dpath[PATH_MAX];
37*36626562SRobert Mustacchi static char odir_doorpath[PATH_MAX];
38*36626562SRobert Mustacchi static char odir_enoent[PATH_MAX];
39*36626562SRobert Mustacchi static char odir_udspath[PATH_MAX];
40*36626562SRobert Mustacchi static int odir_did = -1;
41*36626562SRobert Mustacchi static int odir_uds = -1;
42*36626562SRobert Mustacchi
43*36626562SRobert Mustacchi static void
odir_test_one(const char * test,const char * path,int flags,int err)44*36626562SRobert Mustacchi odir_test_one(const char *test, const char *path, int flags, int err)
45*36626562SRobert Mustacchi {
46*36626562SRobert Mustacchi int fd = open(path, flags | O_DIRECTORY | O_RDONLY, 0644);
47*36626562SRobert Mustacchi if (fd >= 0) {
48*36626562SRobert Mustacchi (void) close(fd);
49*36626562SRobert Mustacchi if (err != 0) {
50*36626562SRobert Mustacchi odir_failures++;
51*36626562SRobert Mustacchi warnx("TEST FAILED: %s: opened %s, but expected error: "
52*36626562SRobert Mustacchi "%d", test, path, err);
53*36626562SRobert Mustacchi }
54*36626562SRobert Mustacchi } else {
55*36626562SRobert Mustacchi if (err == 0) {
56*36626562SRobert Mustacchi odir_failures++;
57*36626562SRobert Mustacchi warnx("TEST FAILED: %s: failed to open %s, error: %d",
58*36626562SRobert Mustacchi test, path, err);
59*36626562SRobert Mustacchi } else if (err != errno) {
60*36626562SRobert Mustacchi odir_failures++;
61*36626562SRobert Mustacchi warnx("TEST FAILED: %s: wrong error for path %s, "
62*36626562SRobert Mustacchi "found %d, expected %d", test, path, errno, err);
63*36626562SRobert Mustacchi }
64*36626562SRobert Mustacchi }
65*36626562SRobert Mustacchi }
66*36626562SRobert Mustacchi
67*36626562SRobert Mustacchi static void
odir_door_server(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t ndesc)68*36626562SRobert Mustacchi odir_door_server(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
69*36626562SRobert Mustacchi uint_t ndesc)
70*36626562SRobert Mustacchi {
71*36626562SRobert Mustacchi (void) door_return(NULL, 0, NULL, 0);
72*36626562SRobert Mustacchi }
73*36626562SRobert Mustacchi
74*36626562SRobert Mustacchi static boolean_t
odir_setup(void)75*36626562SRobert Mustacchi odir_setup(void)
76*36626562SRobert Mustacchi {
77*36626562SRobert Mustacchi int fd;
78*36626562SRobert Mustacchi struct stat st;
79*36626562SRobert Mustacchi struct sockaddr_un un;
80*36626562SRobert Mustacchi pid_t pid = getpid();
81*36626562SRobert Mustacchi
82*36626562SRobert Mustacchi (void) snprintf(odir_fpath, sizeof (odir_fpath),
83*36626562SRobert Mustacchi "/tmp/odir.%d.file", pid);
84*36626562SRobert Mustacchi if ((fd = creat(odir_fpath, 0644)) < 0) {
85*36626562SRobert Mustacchi warn("failed to create temp file %s", odir_fpath);
86*36626562SRobert Mustacchi odir_fpath[0] = '\0';
87*36626562SRobert Mustacchi return (B_FALSE);
88*36626562SRobert Mustacchi }
89*36626562SRobert Mustacchi (void) close(fd);
90*36626562SRobert Mustacchi
91*36626562SRobert Mustacchi (void) snprintf(odir_dpath, sizeof (odir_dpath),
92*36626562SRobert Mustacchi "/tmp/odir.%d.dir", pid);
93*36626562SRobert Mustacchi if (mkdir(odir_dpath, 0755) != 0) {
94*36626562SRobert Mustacchi warn("failed to create temp directory %s", odir_dpath);
95*36626562SRobert Mustacchi odir_dpath[0] = '\0';
96*36626562SRobert Mustacchi return (B_FALSE);
97*36626562SRobert Mustacchi }
98*36626562SRobert Mustacchi
99*36626562SRobert Mustacchi odir_did = door_create(odir_door_server, NULL, 0);
100*36626562SRobert Mustacchi if (odir_did == -1) {
101*36626562SRobert Mustacchi warnx("failed to create door");
102*36626562SRobert Mustacchi return (B_FALSE);
103*36626562SRobert Mustacchi }
104*36626562SRobert Mustacchi (void) snprintf(odir_doorpath, sizeof (odir_doorpath),
105*36626562SRobert Mustacchi "/tmp/odir.%d.door", pid);
106*36626562SRobert Mustacchi if ((fd = creat(odir_doorpath, 0644)) < 0) {
107*36626562SRobert Mustacchi warn("failed to create %s", odir_doorpath);
108*36626562SRobert Mustacchi odir_doorpath[0] = '\0';
109*36626562SRobert Mustacchi return (B_FALSE);
110*36626562SRobert Mustacchi }
111*36626562SRobert Mustacchi (void) close(fd);
112*36626562SRobert Mustacchi if (fattach(odir_did, odir_doorpath) != 0) {
113*36626562SRobert Mustacchi warn("failed to attach door to %s", odir_doorpath);
114*36626562SRobert Mustacchi (void) unlink(odir_doorpath);
115*36626562SRobert Mustacchi odir_doorpath[0] = '\0';
116*36626562SRobert Mustacchi return (B_FALSE);
117*36626562SRobert Mustacchi }
118*36626562SRobert Mustacchi
119*36626562SRobert Mustacchi (void) snprintf(odir_enoent, sizeof (odir_enoent),
120*36626562SRobert Mustacchi "/tmp/odir.%d.enoent", pid);
121*36626562SRobert Mustacchi if (stat(odir_enoent, &st) == 0) {
122*36626562SRobert Mustacchi warnx("somehow random file %s exists!", odir_enoent);
123*36626562SRobert Mustacchi }
124*36626562SRobert Mustacchi
125*36626562SRobert Mustacchi odir_uds = socket(PF_UNIX, SOCK_STREAM, 0);
126*36626562SRobert Mustacchi if (odir_uds == -1) {
127*36626562SRobert Mustacchi warn("failed to create UDS");
128*36626562SRobert Mustacchi return (B_FALSE);
129*36626562SRobert Mustacchi }
130*36626562SRobert Mustacchi (void) snprintf(odir_udspath, sizeof (odir_udspath),
131*36626562SRobert Mustacchi "/tmp/odir.%d.uds", pid);
132*36626562SRobert Mustacchi (void) memset(&un, '\0', sizeof (un));
133*36626562SRobert Mustacchi un.sun_family = AF_UNIX;
134*36626562SRobert Mustacchi if (strlcpy(un.sun_path, odir_udspath, sizeof (un.sun_path)) >=
135*36626562SRobert Mustacchi sizeof (un.sun_path)) {
136*36626562SRobert Mustacchi warnx("%s overflows AF_UNIX path", odir_udspath);
137*36626562SRobert Mustacchi odir_udspath[0] = '\0';
138*36626562SRobert Mustacchi return (B_FALSE);
139*36626562SRobert Mustacchi }
140*36626562SRobert Mustacchi
141*36626562SRobert Mustacchi if (bind(odir_uds, (struct sockaddr *)&un, SUN_LEN(&un)) != 0) {
142*36626562SRobert Mustacchi warn("failed to bind %s", odir_udspath);
143*36626562SRobert Mustacchi odir_udspath[0] = '\0';
144*36626562SRobert Mustacchi return (B_FALSE);
145*36626562SRobert Mustacchi }
146*36626562SRobert Mustacchi
147*36626562SRobert Mustacchi if (listen(odir_uds, 1) != 0) {
148*36626562SRobert Mustacchi warn("failed to listen on %s", odir_udspath);
149*36626562SRobert Mustacchi return (B_FALSE);
150*36626562SRobert Mustacchi }
151*36626562SRobert Mustacchi
152*36626562SRobert Mustacchi return (B_TRUE);
153*36626562SRobert Mustacchi }
154*36626562SRobert Mustacchi
155*36626562SRobert Mustacchi static void
odir_verify_enoent(void)156*36626562SRobert Mustacchi odir_verify_enoent(void)
157*36626562SRobert Mustacchi {
158*36626562SRobert Mustacchi struct stat st;
159*36626562SRobert Mustacchi
160*36626562SRobert Mustacchi if (stat(odir_enoent, &st) == 0) {
161*36626562SRobert Mustacchi warnx("TEST FAILED: %s was created", odir_enoent);
162*36626562SRobert Mustacchi odir_failures++;
163*36626562SRobert Mustacchi } else if (errno != ENOENT) {
164*36626562SRobert Mustacchi warn("TEST FAILED: stat on %s failed", odir_enoent);
165*36626562SRobert Mustacchi odir_failures++;
166*36626562SRobert Mustacchi }
167*36626562SRobert Mustacchi }
168*36626562SRobert Mustacchi
169*36626562SRobert Mustacchi static void
odir_cleanup(void)170*36626562SRobert Mustacchi odir_cleanup(void)
171*36626562SRobert Mustacchi {
172*36626562SRobert Mustacchi if (odir_udspath[0] != '\0') {
173*36626562SRobert Mustacchi if (unlink(odir_udspath) != 0) {
174*36626562SRobert Mustacchi warn("failed to unlink %s", odir_udspath);
175*36626562SRobert Mustacchi }
176*36626562SRobert Mustacchi }
177*36626562SRobert Mustacchi
178*36626562SRobert Mustacchi if (odir_uds != -1) {
179*36626562SRobert Mustacchi if (close(odir_uds) != 0) {
180*36626562SRobert Mustacchi warn("failed to close UDS");
181*36626562SRobert Mustacchi }
182*36626562SRobert Mustacchi }
183*36626562SRobert Mustacchi
184*36626562SRobert Mustacchi if (odir_doorpath[0] != '\0') {
185*36626562SRobert Mustacchi if (fdetach(odir_doorpath) != 0) {
186*36626562SRobert Mustacchi warn("failed to detach door %s", odir_doorpath);
187*36626562SRobert Mustacchi }
188*36626562SRobert Mustacchi }
189*36626562SRobert Mustacchi
190*36626562SRobert Mustacchi if (odir_did != -1) {
191*36626562SRobert Mustacchi if (door_revoke(odir_did) != 0) {
192*36626562SRobert Mustacchi warn("failed to revoke door");
193*36626562SRobert Mustacchi }
194*36626562SRobert Mustacchi }
195*36626562SRobert Mustacchi
196*36626562SRobert Mustacchi if (odir_dpath[0] != '\0') {
197*36626562SRobert Mustacchi if (rmdir(odir_dpath) != 0) {
198*36626562SRobert Mustacchi warn("failed to clean up %s", odir_dpath);
199*36626562SRobert Mustacchi }
200*36626562SRobert Mustacchi }
201*36626562SRobert Mustacchi
202*36626562SRobert Mustacchi if (odir_fpath[0] != '\0') {
203*36626562SRobert Mustacchi if (unlink(odir_fpath) != 0) {
204*36626562SRobert Mustacchi warn("failed to clean up %s", odir_fpath);
205*36626562SRobert Mustacchi }
206*36626562SRobert Mustacchi }
207*36626562SRobert Mustacchi }
208*36626562SRobert Mustacchi
209*36626562SRobert Mustacchi int
main(void)210*36626562SRobert Mustacchi main(void)
211*36626562SRobert Mustacchi {
212*36626562SRobert Mustacchi if (!odir_setup()) {
213*36626562SRobert Mustacchi odir_cleanup();
214*36626562SRobert Mustacchi return (EXIT_FAILURE);
215*36626562SRobert Mustacchi }
216*36626562SRobert Mustacchi
217*36626562SRobert Mustacchi odir_test_one("regular file", odir_fpath, 0, ENOTDIR);
218*36626562SRobert Mustacchi odir_test_one("directory", odir_dpath, 0, 0);
219*36626562SRobert Mustacchi odir_test_one("character device", "/dev/null", 0, ENOTDIR);
220*36626562SRobert Mustacchi odir_test_one("door server", odir_doorpath, 0, ENOTDIR);
221*36626562SRobert Mustacchi odir_test_one("missing file", odir_enoent, 0, ENOENT);
222*36626562SRobert Mustacchi odir_test_one("UDS", odir_udspath, 0, ENOTDIR);
223*36626562SRobert Mustacchi
224*36626562SRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY on a regular file", odir_fpath,
225*36626562SRobert Mustacchi O_CREAT, ENOTDIR);
226*36626562SRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY | O_EXCL on a regular file",
227*36626562SRobert Mustacchi odir_fpath, O_CREAT | O_EXCL, EINVAL);
228*36626562SRobert Mustacchi
229*36626562SRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY on a directory", odir_dpath,
230*36626562SRobert Mustacchi O_CREAT, 0);
231*36626562SRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY | O_EXCL on a directory",
232*36626562SRobert Mustacchi odir_dpath, O_CREAT | O_EXCL, EINVAL);
233*36626562SRobert Mustacchi
234*36626562SRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY on a missing file", odir_enoent,
235*36626562SRobert Mustacchi O_CREAT, ENOENT);
236*36626562SRobert Mustacchi odir_verify_enoent();
237*36626562SRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY | O_EXCL on a missing file",
238*36626562SRobert Mustacchi odir_enoent, O_CREAT | O_EXCL, EINVAL);
239*36626562SRobert Mustacchi odir_verify_enoent();
240*36626562SRobert Mustacchi
241*36626562SRobert Mustacchi odir_cleanup();
242*36626562SRobert Mustacchi if (odir_failures > 0) {
243*36626562SRobert Mustacchi warnx("%u tests failed", odir_failures);
244*36626562SRobert Mustacchi }
245*36626562SRobert Mustacchi
246*36626562SRobert Mustacchi return (odir_failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
247*36626562SRobert Mustacchi }
248