1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Internstional Business Machines Corp., 2006
4 * Author: Yi Yang <yyangcdl@cn.ibm.com>
5 * Copyright (c) Cyril Hrubis 2014 <chrubis@suse.cz>
6 */
7
8 /*\
9 * [Description]
10 *
11 * This test case will verify basic function of openat.
12 *
13 * - pathname is relative, then it is interpreted relative to the directory
14 * referred to by the file descriptor dirfd
15 *
16 * - pathname is absolute, then dirfd is ignored
17 *
18 * - ENODIR pathname is a relative pathname and dirfd is a file
19 * descriptor referring to a file other than a directory
20 *
21 * - EBADF dirfd is not a valid file descriptor
22 *
23 * - pathname is relative and dirfd is the special value AT_FDCWD, then pathname
24 * is interpreted relative to the current working directory of the calling
25 * process
26 */
27
28 #define _GNU_SOURCE
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include "tst_test.h"
36
37 #define TEST_FILE "test_file"
38 #define TEST_DIR "test_dir/"
39
40 static int dir_fd, fd;
41 static int fd_invalid = 100;
42 static int fd_atcwd = AT_FDCWD;
43 static char glob_path[256];
44
45 static struct test_case {
46 int *dir_fd;
47 const char *pathname;
48 int exp_ret;
49 int exp_errno;
50 } test_cases[] = {
51 {&dir_fd, TEST_FILE, 0, 0},
52 {&dir_fd, glob_path, 0, 0},
53 {&fd, TEST_FILE, -1, ENOTDIR},
54 {&fd_invalid, TEST_FILE, -1, EBADF},
55 {&fd_atcwd, TEST_DIR TEST_FILE, 0, 0}
56 };
57
verify_openat(unsigned int n)58 static void verify_openat(unsigned int n)
59 {
60 struct test_case *tc = &test_cases[n];
61
62 if (tc->exp_ret) {
63 if (tc->exp_errno == ENOTDIR) {
64 TST_EXP_FAIL2(openat(*tc->dir_fd, tc->pathname, O_RDWR, 0600),
65 ENOTDIR, "openat with a filefd instead of dirfd");
66 } else {
67 TST_EXP_FAIL2(openat(*tc->dir_fd, tc->pathname, O_RDWR, 0600),
68 EBADF, "openat with invalid fd");
69 }
70 } else {
71 TST_EXP_FD(openat(*tc->dir_fd, tc->pathname, O_RDWR, 0600));
72 }
73
74 if (TST_RET > 0)
75 SAFE_CLOSE(TST_RET);
76 }
77
setup(void)78 static void setup(void)
79 {
80 char buf[PATH_MAX];
81
82 SAFE_GETCWD(buf, PATH_MAX);
83 SAFE_MKDIR(TEST_DIR, 0700);
84 dir_fd = SAFE_OPEN(TEST_DIR, O_DIRECTORY);
85 fd = SAFE_OPEN(TEST_DIR TEST_FILE, O_CREAT | O_RDWR, 0600);
86
87 snprintf(glob_path, sizeof(glob_path), "%s/" TEST_DIR TEST_FILE, buf);
88 }
89
cleanup(void)90 static void cleanup(void)
91 {
92 if (fd > 0)
93 SAFE_CLOSE(fd);
94 if (dir_fd > 0)
95 SAFE_CLOSE(dir_fd);
96 }
97
98 static struct tst_test test = {
99 .setup = setup,
100 .cleanup = cleanup,
101 .test = verify_openat,
102 .tcnt = ARRAY_SIZE(test_cases),
103 .needs_tmpdir = 1,
104 };
105