xref: /linux/tools/testing/selftests/filesystems/openat2/emptypath_test.c (revision 056a5087d87ead77dedbe9cf5bde53b7cd4b4651)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 #define _GNU_SOURCE
4 #define __SANE_USERSPACE_TYPES__
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <errno.h>
8 #include <string.h>
9 #include <sys/stat.h>
10 
11 #include "kselftest_harness.h"
12 
13 #ifndef O_EMPTYPATH
14 #define O_EMPTYPATH	(1 << 26)
15 #endif
16 
17 #define EMPTYPATH_TEST_FILE "/tmp/emptypath_test"
18 
19 FIXTURE(emptypath) {
20 	int opath_fd;
21 };
22 
23 FIXTURE_SETUP(emptypath)
24 {
25 	int fd;
26 
27 	self->opath_fd = -1;
28 
29 	fd = open(EMPTYPATH_TEST_FILE, O_CREAT | O_WRONLY, S_IRWXU);
30 	ASSERT_GE(fd, 0) {
31 		TH_LOG("create %s: %s", EMPTYPATH_TEST_FILE, strerror(errno));
32 	}
33 	close(fd);
34 
35 	self->opath_fd = open(EMPTYPATH_TEST_FILE, O_PATH);
36 	ASSERT_GE(self->opath_fd, 0) {
37 		TH_LOG("open %s O_PATH: %s", EMPTYPATH_TEST_FILE, strerror(errno));
38 	}
39 }
40 
41 FIXTURE_TEARDOWN(emptypath)
42 {
43 	if (self->opath_fd >= 0)
44 		close(self->opath_fd);
45 	unlink(EMPTYPATH_TEST_FILE);
46 }
47 
48 /* An empty path is rejected with ENOENT unless O_EMPTYPATH is set. */
49 TEST_F(emptypath, without_flag_returns_enoent)
50 {
51 	int fd = openat(self->opath_fd, "", O_RDONLY);
52 
53 	if (fd >= 0)
54 		close(fd);
55 	ASSERT_LT(fd, 0) {
56 		TH_LOG("empty path without O_EMPTYPATH unexpectedly succeeded");
57 	}
58 	EXPECT_EQ(errno, ENOENT) {
59 		TH_LOG("expected ENOENT, got %s", strerror(errno));
60 	}
61 }
62 
63 /* O_EMPTYPATH reopens the O_PATH fd through an empty path. */
64 TEST_F(emptypath, reopens_opath_fd)
65 {
66 	int fd = openat(self->opath_fd, "", O_RDONLY | O_EMPTYPATH);
67 
68 	if (fd < 0 && errno == EINVAL)
69 		SKIP(return, "O_EMPTYPATH not supported");
70 
71 	ASSERT_GE(fd, 0) {
72 		TH_LOG("O_EMPTYPATH failed: %s", strerror(errno));
73 	}
74 	close(fd);
75 }
76 
77 TEST_HARNESS_MAIN
78