• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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