1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 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 /* 21 * Test Name: pread02 22 * 23 * Test Description: 24 * Verify that, 25 * 1) pread() fails when attempted to read from an unnamed pipe. 26 * 2) pread() fails if the specified offset position was invalid. 27 * 28 * Expected Result: 29 * 1) pread() should return -1 and set errno to ESPIPE. 30 * 2) pread() should return -1 and set errno to EINVAL. 31 * 32 * Algorithm: 33 * Setup: 34 * Setup signal handling. 35 * Create a temporary directory. 36 * Pause for SIGUSR1 if option specified. 37 * 38 * Test: 39 * Loop if the proper options are given. 40 * Execute system call 41 * Check return code, if system call failed (return=-1) 42 * if errno set == expected errno 43 * Issue sys call fails with expected return value and errno. 44 * Otherwise, 45 * Issue sys call fails with unexpected errno. 46 * Otherwise, 47 * Issue sys call returns unexpected value. 48 * 49 * Cleanup: 50 * Print errno log and/or timing stats if options given 51 * Delete the temporary directory(s)/file(s) created. 52 * 53 * Usage: <for command-line> 54 * pread02 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 55 * where, -c n : Run n copies concurrently. 56 * -i n : Execute test n times. 57 * -I x : Execute test for x seconds. 58 * -P x : Pause for x seconds between iterations. 59 * -t : Turn on syscall timing. 60 * 61 * HISTORY 62 * 07/2001 Ported by Wayne Boyer 63 * 64 * RESTRICTIONS: 65 * None. 66 */ 67 68 #define _XOPEN_SOURCE 500 69 70 #include <errno.h> 71 #include <unistd.h> 72 #include <fcntl.h> 73 74 #include "test.h" 75 #include "safe_macros.h" 76 77 #define TEMPFILE "pread_file" 78 #define K1 1024 79 #define NBUFS 4 80 81 char *TCID = "pread02"; 82 int TST_TOTAL = 2; 83 84 char *write_buf[NBUFS]; /* buffer to hold data to be written */ 85 char *read_buf[NBUFS]; /* buffer to hold data read from file */ 86 int pfd[2]; /* pair of file descriptors */ 87 int fd1; 88 89 void setup(); /* Main setup function of test */ 90 void cleanup(); /* cleanup function for the test */ 91 int setup1(); /* setup function for test #1 */ 92 int setup2(); /* setup function for test #2 */ 93 int no_setup(); 94 void init_buffers(); /* function to initialize/allocate buffers */ 95 96 struct test_case_t { /* test case struct. to hold ref. test cond's */ 97 int fd; 98 size_t nb; 99 off_t offst; 100 char *desc; 101 int exp_errno; 102 int (*setupfunc) (); 103 } Test_cases[] = { 104 { 105 1, K1, 0, "file descriptor is a PIPE or FIFO", ESPIPE, setup1}, { 106 2, K1, -1, "specified offset is -ve or invalid", EINVAL, setup2}, { 107 0, 0, 0, NULL, 0, no_setup} 108 }; 109 110 int main(int ac, char **av) 111 { 112 int lc; 113 int i; 114 int fildes; /* file descriptor of test file */ 115 size_t nbytes; /* no. of bytes to be written */ 116 off_t offset; /* offset position in the specified file */ 117 char *test_desc; /* test specific error message */ 118 119 tst_parse_opts(ac, av, NULL, NULL); 120 121 setup(); 122 123 for (lc = 0; TEST_LOOPING(lc); lc++) { 124 125 tst_count = 0; 126 127 /* loop through the test cases */ 128 for (i = 0; Test_cases[i].desc != NULL; i++) { 129 fildes = Test_cases[i].fd; 130 test_desc = Test_cases[i].desc; 131 nbytes = Test_cases[i].nb; 132 offset = Test_cases[i].offst; 133 134 if (fildes == 1) { 135 fildes = pfd[0]; 136 } else if (fildes == 2) { 137 fildes = fd1; 138 } 139 140 /* 141 * Call pread() with the specified file descriptor, 142 * no. of bytes to be read from specified offset. 143 * and verify that call should fail with appropriate 144 * errno set. 145 */ 146 TEST(pread(fildes, read_buf[0], nbytes, offset)); 147 148 /* Check for the return code of pread() */ 149 if (TEST_RETURN != -1) { 150 tst_brkm(TFAIL, cleanup, "pread() returned " 151 "%ld, expected -1, errno:%d", 152 TEST_RETURN, Test_cases[i].exp_errno); 153 } 154 155 /* 156 * Verify whether expected errno is set. 157 */ 158 if (TEST_ERRNO == Test_cases[i].exp_errno) { 159 tst_resm(TPASS, "pread() fails, %s, errno:%d", 160 test_desc, TEST_ERRNO); 161 } else { 162 tst_resm(TFAIL, "pread() fails, %s, unexpected " 163 "errno:%d, expected:%d", test_desc, 164 TEST_ERRNO, Test_cases[i].exp_errno); 165 } 166 } 167 } 168 169 cleanup(); 170 171 tst_exit(); 172 } 173 174 /* 175 * setup() - performs all ONE TIME setup for this test. 176 * Initialize/allocate write buffer. 177 * Call individual setup function. 178 */ 179 void setup(void) 180 { 181 int i; 182 183 tst_sig(FORK, DEF_HANDLER, cleanup); 184 185 TEST_PAUSE; 186 187 /* Allocate/Initialize the read/write buffer with known data */ 188 init_buffers(); 189 190 /* Call individual setup functions */ 191 for (i = 0; Test_cases[i].desc != NULL; i++) { 192 Test_cases[i].setupfunc(); 193 } 194 } 195 196 /* 197 * no_setup() - This function simply returns. 198 */ 199 int no_setup(void) 200 { 201 return 0; 202 } 203 204 /* 205 * setup1() - setup function for a test condition for which pread() 206 * returns -ve value and sets errno to ESPIPE. 207 * 208 * Create an unnamed pipe using pipe(). 209 * Write some known data to the write end of the pipe. 210 * return 0. 211 */ 212 int setup1(void) 213 { 214 /* Create a pair of unnamed pipe */ 215 SAFE_PIPE(cleanup, pfd); 216 217 /* Write known data (0's) of K1 bytes */ 218 if (write(pfd[1], write_buf[0], K1) != K1) { 219 tst_brkm(TBROK, cleanup, "write to pipe failed: errno=%d : %s", 220 errno, strerror(errno)); 221 } 222 223 return 0; 224 } 225 226 /* 227 * setup2 - setup function for a test condition for which pread() 228 * returns -ve value and sets errno to EINVAL. 229 * 230 * Create a temporary directory and a file under it. 231 * return 0. 232 */ 233 int setup2(void) 234 { 235 236 tst_tmpdir(); 237 238 /* Creat a temporary file used for mapping */ 239 if ((fd1 = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) { 240 tst_brkm(TBROK, cleanup, "open() on %s Failed, errno=%d : %s", 241 TEMPFILE, errno, strerror(errno)); 242 } 243 244 return 0; 245 } 246 247 /* 248 * init_buffers() - allocate/Initialize write_buf array. 249 * 250 * Allocate read/write buffer. 251 * Fill the write buffer with the following data like, 252 * write_buf[0] has 0's, write_buf[1] has 1's, write_buf[2] has 2's 253 * write_buf[3] has 3's. 254 */ 255 void init_buffers(void) 256 { 257 int count; /* counter variable for loop */ 258 259 /* Allocate and Initialize write buffer with known data */ 260 for (count = 0; count < NBUFS; count++) { 261 write_buf[count] = malloc(K1); 262 read_buf[count] = malloc(K1); 263 264 if ((write_buf[count] == NULL) || (read_buf[count] == NULL)) { 265 tst_brkm(TBROK, NULL, 266 "malloc() failed on read/write buffers"); 267 } 268 memset(write_buf[count], count, K1); 269 } 270 } 271 272 /* 273 * cleanup() - performs all ONE TIME cleanup for this test at 274 * completion or premature exit. 275 * 276 * Deallocate the memory allocated to read/write buffers. 277 * Close the temporary file. 278 * Remove the temporary directory created. 279 */ 280 void cleanup(void) 281 { 282 int count; 283 284 /* Free the memory allocated for the read/write buffer */ 285 for (count = 0; count < NBUFS; count++) { 286 free(write_buf[count]); 287 free(read_buf[count]); 288 } 289 290 /* Close the temporary file created in setup2 */ 291 SAFE_CLOSE(NULL, fd1); 292 293 tst_rmdir(); 294 295 } 296