1 /*
2 * Copyright (c) 2014 Fujitsu Ltd.
3 * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20 /*
21 * Test Description:
22 * Verify that,
23 * 1. bufsiz is 0, EINVAL should be returned.
24 * 2. The named file is not a symbolic link, EINVAL should be returned.
25 * 3. The component of the path prefix is not a directory, ENOTDIR should be
26 * returned.
27 * 4. pathname is relative and dirfd is a file descriptor referring to a file
28 * other than a directory, ENOTDIR should be returned.
29 */
30
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <errno.h>
34
35 #include "test.h"
36 #include "safe_macros.h"
37 #include "lapi/readlinkat.h"
38 #include "lapi/syscalls.h"
39
40 #define TEST_FILE "test_file"
41 #define SYMLINK_FILE "symlink_file"
42 #define BUFF_SIZE 256
43
44 static int file_fd, dir_fd;
45
46 static struct test_case_t {
47 int *dirfd;
48 const char *pathname;
49 size_t bufsiz;
50 int exp_errno;
51 } test_cases[] = {
52 {&dir_fd, SYMLINK_FILE, 0, EINVAL},
53 {&dir_fd, TEST_FILE, BUFF_SIZE, EINVAL},
54 {&file_fd, SYMLINK_FILE, BUFF_SIZE, ENOTDIR},
55 {&dir_fd, "test_file/test_file", BUFF_SIZE, ENOTDIR},
56 };
57
58 char *TCID = "readlinkat02";
59 int TST_TOTAL = ARRAY_SIZE(test_cases);
60 static void setup(void);
61 static void cleanup(void);
62 static void readlinkat_verify(const struct test_case_t *);
63
main(int argc,char ** argv)64 int main(int argc, char **argv)
65 {
66 int i, lc;
67
68 tst_parse_opts(argc, argv, NULL, NULL);
69
70 setup();
71
72 for (lc = 0; TEST_LOOPING(lc); lc++) {
73 tst_count = 0;
74 for (i = 0; i < TST_TOTAL; i++)
75 readlinkat_verify(&test_cases[i]);
76 }
77
78 cleanup();
79 tst_exit();
80 }
81
setup(void)82 static void setup(void)
83 {
84 tst_sig(NOFORK, DEF_HANDLER, cleanup);
85
86 TEST_PAUSE;
87
88 tst_tmpdir();
89
90 dir_fd = SAFE_OPEN(cleanup, "./", O_RDONLY);
91
92 file_fd = SAFE_OPEN(cleanup, TEST_FILE, O_RDWR | O_CREAT, 0644);
93
94 SAFE_SYMLINK(cleanup, TEST_FILE, SYMLINK_FILE);
95 }
96
readlinkat_verify(const struct test_case_t * test)97 static void readlinkat_verify(const struct test_case_t *test)
98 {
99 char buf[BUFF_SIZE];
100 TEST(readlinkat(*test->dirfd, test->pathname, buf, test->bufsiz));
101
102 if (TEST_RETURN != -1) {
103 tst_resm(TFAIL, "readlinkat succeeded unexpectedly");
104 return;
105 }
106
107 if (TEST_ERRNO == test->exp_errno) {
108 tst_resm(TPASS | TTERRNO, "readlinkat failed as expected");
109 } else {
110 tst_resm(TFAIL | TTERRNO,
111 "readlinkat failed unexpectedly; expected: %d - %s",
112 test->exp_errno, strerror(test->exp_errno));
113 }
114 }
115
cleanup(void)116 static void cleanup(void)
117 {
118 close(dir_fd);
119 close(file_fd);
120
121 tst_rmdir();
122 }
123