1/* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 07/2001 Ported by Wayne Boyer 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 13 * the GNU 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19/* 20 * DESCRIPTION 21 * test 1: 22 * Read with an invalid file descriptor, and expect an EBADF. 23 * 24 * test 2: 25 * The parameter passed to read is a directory, check if the errno is 26 * set to EISDIR. 27 * 28 * test 3: 29 * Buf is outside the accessible address space, expect an EFAULT. 30 * 31 * test 4: 32 * The file was opened with the O_DIRECT flag, and transfer sizes was not 33 * multiples of the logical block size of the file system, expect an 34 * EINVAL. 35 * 36 * test 5: 37 * The file was opened with the O_DIRECT flag, and the alignment of the 38 * user buffer was not multiples of the logical block size of the file 39 * system, expect an EINVAL. 40 */ 41 42#define _GNU_SOURCE 43 44#include <stdio.h> 45#include <errno.h> 46#include <unistd.h> 47#include <fcntl.h> 48#include <sys/mman.h> 49#include "test.h" 50#include "safe_macros.h" 51 52char *TCID = "read02"; 53 54static int badfd = -1; 55static int fd2, fd3, fd4 = -1; 56static char buf[BUFSIZ]; 57static void *outside_buf = (void *)-1; 58static void *addr4; 59static void *addr5; 60 61static long fs_type; 62 63static struct test_case_t { 64 int *fd; 65 void **buf; 66 size_t count; 67 int exp_error; 68} TC[] = { 69 {&badfd, (void **)&buf, 1, EBADF}, 70 {&fd2, (void **)&buf, 1, EISDIR}, 71#ifndef UCLINUX 72 {&fd3, &outside_buf, 1, EFAULT}, 73#endif 74 {&fd4, &addr4, 1, EINVAL}, 75 {&fd4, &addr5, 4096, EINVAL}, 76}; 77 78int TST_TOTAL = ARRAY_SIZE(TC); 79static void setup(void); 80static void cleanup(void); 81static void read_verify(const struct test_case_t *); 82 83int main(int ac, char **av) 84{ 85 int i; 86 int lc; 87 88 tst_parse_opts(ac, av, NULL, NULL); 89 90 setup(); 91 92 for (lc = 0; TEST_LOOPING(lc); lc++) { 93 tst_count = 0; 94 for (i = 0; i < TST_TOTAL; i++) 95 read_verify(&TC[i]); 96 } 97 cleanup(); 98 tst_exit(); 99} 100 101static void setup(void) 102{ 103 tst_sig(NOFORK, DEF_HANDLER, cleanup); 104 105 TEST_PAUSE; 106 107 tst_tmpdir(); 108 109 fd2 = SAFE_OPEN(cleanup, ".", O_DIRECTORY); 110 111 SAFE_FILE_PRINTF(cleanup, "test_file", "A"); 112 113 fd3 = SAFE_OPEN(cleanup, "test_file", O_RDWR); 114 115#if !defined(UCLINUX) 116 outside_buf = SAFE_MMAP(cleanup, 0, 1, PROT_NONE, 117 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 118#endif 119 120 addr4 = SAFE_MEMALIGN(cleanup, getpagesize(), (4096 * 10)); 121 addr5 = addr4 + 1; 122 123 fs_type = tst_fs_type(cleanup, "."); 124 if (fs_type != TST_TMPFS_MAGIC) 125 fd4 = SAFE_OPEN(cleanup, "test_file", O_RDWR | O_DIRECT); 126} 127 128static void read_verify(const struct test_case_t *test) 129{ 130 if (test->fd == &fd4 && *test->fd == -1) { 131 tst_resm(TCONF, "O_DIRECT not supported on %s filesystem", 132 tst_fs_type_name(fs_type)); 133 return; 134 } 135 136 TEST(read(*test->fd, *test->buf, test->count)); 137 138 if (*test->fd == fd4 && TEST_RETURN >= 0) { 139 tst_resm(TPASS, 140 "O_DIRECT unaligned reads fallbacks to buffered I/O"); 141 return; 142 } 143 144 if (TEST_RETURN != -1) { 145 tst_resm(TFAIL, "call succeeded unexpectedly"); 146 return; 147 } 148 149 if (TEST_ERRNO == test->exp_error) { 150 tst_resm(TPASS | TTERRNO, "expected failure"); 151 } else { 152 tst_resm(TFAIL | TTERRNO, "unexpected error expected %d", 153 test->exp_error); 154 } 155} 156 157static void cleanup(void) 158{ 159 free(addr4); 160 161 if (fd4 > 0) 162 close(fd4); 163 164 if (fd3 > 0) 165 close(fd3); 166 167 if (fd2 > 0) 168 close(fd2); 169 170 tst_rmdir(); 171} 172