1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org>
4 *
5 * Basic openat2() test.
6 */
7 #include "tst_test.h"
8 #include "lapi/openat2.h"
9
10 #define TEST_FILE "test_file"
11 #define TEST_DIR "test_dir"
12
13 static struct open_how *how;
14 static struct open_how_pad *phow;
15
16 static int dir_fd = -1, fd_atcwd = AT_FDCWD;
17
18 static struct tcase {
19 int *dfd;
20 const char *pathname;
21 uint64_t flags;
22 uint64_t mode;
23 uint64_t resolve;
24 struct open_how **how;
25 size_t size;
26 } tcases[] = {
27 {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, 0, &how, sizeof(*how)},
28 {&dir_fd, TEST_FILE, O_RDONLY, S_IRUSR, 0, &how, sizeof(*how)},
29 {&dir_fd, TEST_FILE, O_WRONLY, S_IWUSR, 0, &how, sizeof(*how)},
30 {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_XDEV, &how, sizeof(*how)},
31 {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_MAGICLINKS, &how, sizeof(*how)},
32 {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_SYMLINKS, &how, sizeof(*how)},
33 {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_BENEATH, &how, sizeof(*how)},
34 {&dir_fd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_IN_ROOT, &how, sizeof(*how)},
35 {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, 0, &how, sizeof(*how)},
36 {&fd_atcwd, TEST_FILE, O_RDONLY, S_IRUSR, 0, &how, sizeof(*how)},
37 {&fd_atcwd, TEST_FILE, O_WRONLY, S_IWUSR, 0, &how, sizeof(*how)},
38 {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_XDEV, &how, sizeof(*how)},
39 {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_MAGICLINKS, &how, sizeof(*how)},
40 {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_NO_SYMLINKS, &how, sizeof(*how)},
41 {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_BENEATH, &how, sizeof(*how)},
42 {&fd_atcwd, TEST_FILE, O_RDWR, S_IRWXU, RESOLVE_IN_ROOT, (struct open_how **)&phow, sizeof(*how) + 8},
43 };
44
cleanup(void)45 static void cleanup(void)
46 {
47 if (dir_fd != -1)
48 SAFE_CLOSE(dir_fd);
49 }
50
setup(void)51 static void setup(void)
52 {
53 openat2_supported_by_kernel();
54
55 phow->pad = 0x00;
56 SAFE_MKDIR(TEST_DIR, 0700);
57 dir_fd = SAFE_OPEN(TEST_DIR, O_DIRECTORY);
58 }
59
run(unsigned int n)60 static void run(unsigned int n)
61 {
62 int fd;
63 struct stat file_stat;
64 struct tcase *tc = &tcases[n];
65 struct open_how *myhow = *tc->how;
66
67 myhow->flags = tc->flags | O_CREAT;
68 myhow->mode = tc->mode;
69 myhow->resolve = tc->resolve;
70
71 TEST(fd = openat2(*tc->dfd, tc->pathname, myhow, tc->size));
72 if (fd < 0) {
73 tst_res(TFAIL | TTERRNO, "openat2() failed (%d)", n);
74 return;
75 }
76
77 SAFE_FSTAT(fd, &file_stat);
78
79 if (file_stat.st_size == 0)
80 tst_res(TPASS, "openat2() passed (%d)", n);
81 else
82 tst_res(TFAIL, "fstat() didn't work as expected (%d)", n);
83
84 SAFE_CLOSE(fd);
85 }
86
87 static struct tst_test test = {
88 .tcnt = ARRAY_SIZE(tcases),
89 .test = run,
90 .setup = setup,
91 .cleanup = cleanup,
92 .needs_tmpdir = 1,
93 .bufs = (struct tst_buffers []) {
94 {&how, .size = sizeof(*how)},
95 {&phow, .size = sizeof(*phow)},
96 {},
97 },
98 };
99