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
main(int ac,char ** av)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 */
setup(void)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 */
no_setup(void)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 */
setup1(void)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 */
setup2(void)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 */
init_buffers(void)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 */
cleanup(void)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