1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2001 4 * Ported to LTP: Wayne Boyer 5 * Copyright (c) 2017 Fujitsu Ltd. 6 * 04/2017 Modified by Jinhui Huang 7 */ 8/* 9 * DESCRIPTION 10 * test 1: 11 * Read with an invalid file descriptor, and expect an EBADF. 12 * 13 * test 2: 14 * The parameter passed to read is a directory, check if the errno is 15 * set to EISDIR. 16 * 17 * test 3: 18 * Buf is outside the accessible address space, expect an EFAULT. 19 * 20 * test 4: 21 * The file was opened with the O_DIRECT flag, and transfer sizes was not 22 * multiples of the logical block size of the file system, expect an 23 * EINVAL. 24 * 25 * test 5: 26 * The file was opened with the O_DIRECT flag, and the alignment of the 27 * user buffer was not multiples of the logical block size of the file 28 * system, expect an EINVAL. 29 */ 30 31#define _GNU_SOURCE 32 33#include <stdio.h> 34#include <stdlib.h> 35#include <errno.h> 36#include "tst_test.h" 37 38static int badfd = -1; 39static int fd2, fd3, fd4 = -1; 40static char buf[BUFSIZ]; 41static void *bufaddr = buf; 42static void *outside_buf = (void *)-1; 43static void *addr4; 44static void *addr5; 45static long fs_type; 46 47static struct tcase { 48 int *fd; 49 void **buf; 50 size_t count; 51 int exp_error; 52} tcases[] = { 53 {&badfd, &bufaddr, 1, EBADF}, 54 {&fd2, &bufaddr, 1, EISDIR}, 55#ifndef UCLINUX 56 {&fd3, &outside_buf, 1, EFAULT}, 57#endif 58 {&fd4, &addr4, 1, EINVAL}, 59 {&fd4, &addr5, 4096, EINVAL}, 60}; 61 62static void verify_read(unsigned int n) 63{ 64 struct tcase *tc = &tcases[n]; 65 66 if (tc->fd == &fd4 && *tc->fd == -1) { 67 tst_res(TCONF, "O_DIRECT not supported on %s filesystem", 68 tst_fs_type_name(fs_type)); 69 return; 70 } 71 72 TEST(read(*tc->fd, *tc->buf, tc->count)); 73 74 if (*tc->fd == fd4 && TST_RET >= 0) { 75 tst_res(TPASS, 76 "O_DIRECT unaligned reads fallbacks to buffered I/O"); 77 return; 78 } 79 80 if (TST_RET != -1) { 81 tst_res(TFAIL, "read() succeeded unexpectedly"); 82 return; 83 } 84 85 if (TST_ERR == tc->exp_error) { 86 tst_res(TPASS | TTERRNO, "read() failed as expected"); 87 } else { 88 tst_res(TFAIL | TTERRNO, "read() failed unexpectedly, " 89 "expected %s", tst_strerrno(tc->exp_error)); 90 } 91} 92 93static void setup(void) 94{ 95 fd2 = SAFE_OPEN(".", O_DIRECTORY); 96 97 SAFE_FILE_PRINTF("test_file", "A"); 98 99 fd3 = SAFE_OPEN("test_file", O_RDWR); 100 101#if !defined(UCLINUX) 102 outside_buf = SAFE_MMAP(0, 1, PROT_NONE, 103 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 104#endif 105 106 addr4 = SAFE_MEMALIGN(getpagesize(), (4096 * 10)); 107 addr5 = addr4 + 1; 108 109 fs_type = tst_fs_type("."); 110 if (fs_type != TST_TMPFS_MAGIC) 111 fd4 = SAFE_OPEN("test_file", O_RDWR | O_DIRECT); 112} 113 114static void cleanup(void) 115{ 116 free(addr4); 117 118 if (fd4 > 0) 119 SAFE_CLOSE(fd4); 120 121 if (fd3 > 0) 122 SAFE_CLOSE(fd3); 123 124 if (fd2 > 0) 125 SAFE_CLOSE(fd2); 126} 127 128static struct tst_test test = { 129 .tcnt = ARRAY_SIZE(tcases), 130 .test = verify_read, 131 .setup = setup, 132 .cleanup = cleanup, 133 .needs_tmpdir = 1, 134}; 135