getdents02.c revision e906e333cd046ba387579e8bb52c5a8a2d617cb9
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@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 "usctest.h" 45#include "getdents.h" 46#include "safe_macros.h" 47 48#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ 49 S_IXGRP|S_IROTH|S_IXOTH) 50#define TEST_DIR "test_dir" 51 52static void cleanup(void); 53static void setup(void); 54static void print_test_result(int err, int exp_errno); 55 56char *TCID = "getdents02"; 57 58static int exp_enos[] = { EBADF, EINVAL, ENOTDIR, ENOENT, 0 }; 59 60static void test_ebadf(void); 61static void test_einval(void); 62static void test_enotdir(void); 63static void test_enoent(void); 64 65static void (*testfunc[])(void) = { test_ebadf, test_einval, 66 test_enotdir, test_enoent }; 67 68int TST_TOTAL = ARRAY_SIZE(testfunc); 69 70static int longsyscall; 71 72option_t options[] = { 73 /* -l long option. Tests getdents64 */ 74 {"l", &longsyscall, NULL}, 75 {NULL, NULL, NULL} 76}; 77 78static void help(void) 79{ 80 printf(" -l Test the getdents64 system call\n"); 81} 82 83int main(int ac, char **av) 84{ 85 int lc, i; 86 char *msg; 87 88 if ((msg = parse_opts(ac, av, options, &help)) != NULL) 89 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); 90 91 setup(); 92 93 for (lc = 0; TEST_LOOPING(lc); lc++) { 94 tst_count = 0; 95 96 for (i = 0; i < TST_TOTAL; i++) 97 (*testfunc[i])(); 98 } 99 100 cleanup(); 101 tst_exit(); 102} 103 104static void setup(void) 105{ 106 tst_sig(NOFORK, DEF_HANDLER, cleanup); 107 108 tst_tmpdir(); 109 110 TEST_EXP_ENOS(exp_enos); 111 112 TEST_PAUSE; 113} 114 115static void print_test_result(int err, int exp_errno) 116{ 117 TEST_ERROR_LOG(err); 118 if (err == 0) { 119 tst_resm(TFAIL, "call succeeded unexpectedly"); 120 } else if (err == exp_errno) { 121 tst_resm(TPASS, "getdents failed as expected: %s", 122 strerror(err)); 123 } else if (err == ENOSYS) { 124 tst_resm(TCONF, "syscall not implemented"); 125 } else { 126 tst_resm(TFAIL, "getdents failed unexpectedly: %s", 127 strerror(err)); 128 } 129} 130 131static void test_ebadf(void) 132{ 133 int fd = -5; 134 struct linux_dirent64 dirp64; 135 struct linux_dirent dirp; 136 137 if (longsyscall) 138 getdents64(fd, &dirp64, sizeof(dirp64)); 139 else 140 getdents(fd, &dirp, sizeof(dirp)); 141 142 print_test_result(errno, EBADF); 143} 144 145static void test_einval(void) 146{ 147 int fd; 148 char buf[1]; 149 150 fd = SAFE_OPEN(cleanup, ".", O_RDONLY); 151 152 /* Pass one byte long buffer. The result should be EINVAL */ 153 if (longsyscall) 154 getdents64(fd, (void *)buf, sizeof(buf)); 155 else 156 getdents(fd, (void *)buf, sizeof(buf)); 157 158 print_test_result(errno, EINVAL); 159 160 SAFE_CLOSE(cleanup, fd); 161} 162 163static void test_enotdir(void) 164{ 165 int fd; 166 struct linux_dirent64 dir64; 167 struct linux_dirent dir; 168 169 fd = SAFE_OPEN(cleanup, "test", O_CREAT | O_RDWR); 170 171 if (longsyscall) 172 getdents64(fd, &dir64, sizeof(dir64)); 173 else 174 getdents(fd, &dir, sizeof(dir)); 175 176 print_test_result(errno, ENOTDIR); 177 178 SAFE_CLOSE(cleanup, fd); 179} 180 181static void test_enoent(void) 182{ 183 int fd; 184 struct linux_dirent64 dir64; 185 struct linux_dirent dir; 186 187 SAFE_MKDIR(cleanup, TEST_DIR, DIR_MODE); 188 189 fd = SAFE_OPEN(cleanup, TEST_DIR, O_DIRECTORY); 190 if (rmdir(TEST_DIR) == -1) { 191 tst_brkm(TBROK | TERRNO, cleanup, 192 "rmdir(%s) failed", TEST_DIR); 193 } 194 195 if (longsyscall) 196 getdents64(fd, &dir64, sizeof(dir64)); 197 else 198 getdents(fd, &dir, sizeof(dir)); 199 200 print_test_result(errno, ENOENT); 201 202 SAFE_CLOSE(cleanup, fd); 203} 204 205static void cleanup(void) 206{ 207 TEST_CLEANUP; 208 209 tst_rmdir(); 210} 211