Home | History | Annotate | Download | only in pread
      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