1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * written by Wayne Boyer 4 * Copyright (c) 2013 Markos Chandras 5 * Copyright (c) 2013 Cyril Hrubis <chrubis (at) suse.cz> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15 * the GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 /* 23 * Test Description: 24 * Verify that, 25 * 1. getdents() fails with -1 return value and sets errno to EBADF 26 * if file descriptor fd is invalid. 27 * 2. getdents() fails with -1 return value and sets errno to EINVAL 28 * if result buffer is too small. 29 * 3. getdents() fails with -1 return value and sets errno to ENOTDIR 30 * if file descriptor does not refer to a directory. 31 * 4. getdents() fails with -1 return value and sets errno to ENOENT 32 * if there is no such directory. 33 * 34 */ 35 36 #define _GNU_SOURCE 37 #include <stdio.h> 38 #include <errno.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <fcntl.h> 42 43 #include "test.h" 44 #include "getdents.h" 45 #include "safe_macros.h" 46 47 #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ 48 S_IXGRP|S_IROTH|S_IXOTH) 49 #define TEST_DIR "test_dir" 50 51 static void cleanup(void); 52 static void setup(void); 53 static void print_test_result(int err, int exp_errno); 54 55 char *TCID = "getdents02"; 56 57 static void test_ebadf(void); 58 static void test_einval(void); 59 static void test_enotdir(void); 60 static void test_enoent(void); 61 62 static void (*testfunc[])(void) = { test_ebadf, test_einval, 63 test_enotdir, test_enoent }; 64 65 int TST_TOTAL = ARRAY_SIZE(testfunc); 66 67 static int longsyscall; 68 69 option_t options[] = { 70 /* -l long option. Tests getdents64 */ 71 {"l", &longsyscall, NULL}, 72 {NULL, NULL, NULL} 73 }; 74 75 static void help(void) 76 { 77 printf(" -l Test the getdents64 system call\n"); 78 } 79 80 int main(int ac, char **av) 81 { 82 int lc, i; 83 84 tst_parse_opts(ac, av, options, &help); 85 86 setup(); 87 88 for (lc = 0; TEST_LOOPING(lc); lc++) { 89 tst_count = 0; 90 91 for (i = 0; i < TST_TOTAL; i++) 92 (*testfunc[i])(); 93 } 94 95 cleanup(); 96 tst_exit(); 97 } 98 99 static void setup(void) 100 { 101 tst_sig(NOFORK, DEF_HANDLER, cleanup); 102 103 tst_tmpdir(); 104 105 TEST_PAUSE; 106 } 107 108 static void print_test_result(int err, int exp_errno) 109 { 110 if (err == 0) { 111 tst_resm(TFAIL, "call succeeded unexpectedly"); 112 } else if (err == exp_errno) { 113 tst_resm(TPASS, "getdents failed as expected: %s", 114 strerror(err)); 115 } else if (err == ENOSYS) { 116 tst_resm(TCONF, "syscall not implemented"); 117 } else { 118 tst_resm(TFAIL, "getdents failed unexpectedly: %s", 119 strerror(err)); 120 } 121 } 122 123 static void test_ebadf(void) 124 { 125 int fd = -5; 126 struct linux_dirent64 dirp64; 127 struct linux_dirent dirp; 128 129 if (longsyscall) 130 getdents64(fd, &dirp64, sizeof(dirp64)); 131 else 132 getdents(fd, &dirp, sizeof(dirp)); 133 134 print_test_result(errno, EBADF); 135 } 136 137 static void test_einval(void) 138 { 139 int fd; 140 char buf[1]; 141 142 fd = SAFE_OPEN(cleanup, ".", O_RDONLY); 143 144 /* Pass one byte long buffer. The result should be EINVAL */ 145 if (longsyscall) 146 getdents64(fd, (void *)buf, sizeof(buf)); 147 else 148 getdents(fd, (void *)buf, sizeof(buf)); 149 150 print_test_result(errno, EINVAL); 151 152 SAFE_CLOSE(cleanup, fd); 153 } 154 155 static void test_enotdir(void) 156 { 157 int fd; 158 struct linux_dirent64 dir64; 159 struct linux_dirent dir; 160 161 fd = SAFE_OPEN(cleanup, "test", O_CREAT | O_RDWR); 162 163 if (longsyscall) 164 getdents64(fd, &dir64, sizeof(dir64)); 165 else 166 getdents(fd, &dir, sizeof(dir)); 167 168 print_test_result(errno, ENOTDIR); 169 170 SAFE_CLOSE(cleanup, fd); 171 } 172 173 static void test_enoent(void) 174 { 175 int fd; 176 struct linux_dirent64 dir64; 177 struct linux_dirent dir; 178 179 SAFE_MKDIR(cleanup, TEST_DIR, DIR_MODE); 180 181 fd = SAFE_OPEN(cleanup, TEST_DIR, O_DIRECTORY); 182 SAFE_RMDIR(cleanup, TEST_DIR); 183 184 if (longsyscall) 185 getdents64(fd, &dir64, sizeof(dir64)); 186 else 187 getdents(fd, &dir, sizeof(dir)); 188 189 print_test_result(errno, ENOENT); 190 191 SAFE_CLOSE(cleanup, fd); 192 } 193 194 static void cleanup(void) 195 { 196 tst_rmdir(); 197 } 198