getdents02.c revision d6d11d08678aac1ed2c370ea8e42e5f45aea07be
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 "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 51static void cleanup(void); 52static void setup(void); 53static void print_test_result(int err, int exp_errno); 54 55char *TCID = "getdents02"; 56 57static void test_ebadf(void); 58static void test_einval(void); 59static void test_enotdir(void); 60static void test_enoent(void); 61 62static void (*testfunc[])(void) = { test_ebadf, test_einval, 63 test_enotdir, test_enoent }; 64 65int TST_TOTAL = ARRAY_SIZE(testfunc); 66 67static int longsyscall; 68 69option_t options[] = { 70 /* -l long option. Tests getdents64 */ 71 {"l", &longsyscall, NULL}, 72 {NULL, NULL, NULL} 73}; 74 75static void help(void) 76{ 77 printf(" -l Test the getdents64 system call\n"); 78} 79 80int 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 99static void setup(void) 100{ 101 tst_sig(NOFORK, DEF_HANDLER, cleanup); 102 103 tst_tmpdir(); 104 105 TEST_PAUSE; 106} 107 108static 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 123static 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 137static 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 155static 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 173static 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 if (rmdir(TEST_DIR) == -1) { 183 tst_brkm(TBROK | TERRNO, cleanup, 184 "rmdir(%s) failed", TEST_DIR); 185 } 186 187 if (longsyscall) 188 getdents64(fd, &dir64, sizeof(dir64)); 189 else 190 getdents(fd, &dir, sizeof(dir)); 191 192 print_test_result(errno, ENOENT); 193 194 SAFE_CLOSE(cleanup, fd); 195} 196 197static void cleanup(void) 198{ 199 tst_rmdir(); 200} 201