1 /* 2 * Copyright (c) 2014 Fujitsu Ltd. 3 * Author: Zeng Linggang <zenglg.jy (at) 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 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 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 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 116 static void cleanup(void) 117 { 118 close(dir_fd); 119 close(file_fd); 120 121 tst_rmdir(); 122 } 123