blob: 5ebd922ee76ba917c773686c25e2b20754cb2d5b [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/*
21 * NAME
nstrazfa31d552002-05-14 16:50:06 +000022 * write05.c
plars865695b2001-08-27 22:15:12 +000023 *
24 * DESCRIPTION
25 * Check the return value, and errnos of write(2)
26 * - when the file descriptor is invalid - EBADF
27 * - when the buf parameter is invalid - EFAULT
28 * - on an attempt to write to a pipe that is not open for reading - EPIPE
29 *
30 * ALGORITHM
31 * Attempt to write on a file with negative file descriptor, check for -1
32 * Attempt to write on a file with invalid buffer, check for -1
33 * Open a pipe and close the read end, attempt to write to the write
34 * end, check for -1.
35 *
36 * USAGE: <for command-line>
nstrazfa31d552002-05-14 16:50:06 +000037 * write05 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
plars865695b2001-08-27 22:15:12 +000038 * where, -c n : Run n copies concurrently.
39 * -e : Turn on errno logging.
40 * -i n : Execute test n times.
41 * -I x : Execute test for x seconds.
42 * -P x : Pause for x seconds between iterations.
43 * -t : Turn on syscall timing.
44 *
45 * History
46 * 07/2001 John George
47 * -Ported
robbiew4644c7e2002-04-26 14:33:32 +000048 * 04/2002 wjhuie sigset cleanups
subrata_modak0206d282007-08-06 09:32:49 +000049 * 08/2007 Ricardo Salveti de Araujo <rsalveti@linux.vnet.ibm.com>
50 * - Closing the fd before removing the file
plars865695b2001-08-27 22:15:12 +000051 *
52 * Restrictions
53 * None
54 */
robbiew6ee509b2003-04-01 20:28:41 +000055#include <sys/types.h>
56#include <sys/stat.h>
57#include <fcntl.h>
plars865695b2001-08-27 22:15:12 +000058#include <errno.h>
59#include <stdio.h>
robbiew6ee509b2003-04-01 20:28:41 +000060#include <wait.h>
robbiew37d19bd2003-11-14 16:57:49 +000061#include <sys/mman.h>
plars865695b2001-08-27 22:15:12 +000062#include "test.h"
63#include "usctest.h"
64
robbiew37d19bd2003-11-14 16:57:49 +000065
plars865695b2001-08-27 22:15:12 +000066void setup(void);
67void cleanup(void);
68
69/* 0 terminated list of expected errnos */
70int exp_enos[] = {9,14,32,0};
71
nstrazfa31d552002-05-14 16:50:06 +000072char *TCID = "write05"; /* Test program identifier */
plars865695b2001-08-27 22:15:12 +000073int TST_TOTAL = 1; /* Total number of test cases */
74extern int Tst_count;
75char filename[100];
subrata_modak0206d282007-08-06 09:32:49 +000076int fd;
plars865695b2001-08-27 22:15:12 +000077
robbiew37d19bd2003-11-14 16:57:49 +000078char * bad_addr = 0;
79
robbiew6ee509b2003-04-01 20:28:41 +000080int main(int argc, char **argv)
plars865695b2001-08-27 22:15:12 +000081{
82 int lc; /* loop counter */
83 char *msg; /* message returned from parse_opts */
84
85 char pbuf[BUFSIZ];
86 int pipefildes[2];
subrata_modak0206d282007-08-06 09:32:49 +000087 int status, pid;
plars865695b2001-08-27 22:15:12 +000088
89 /* parse standard options */
90 if ((msg = parse_opts(argc, argv, (option_t *)NULL, NULL)) !=
91 (char *) NULL) {
92 tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
93 /*NOTREACHED*/
94 }
95
96 /* global setup */
97 setup();
98
99 /* The following loop checks looping state if -i option given */
100 for (lc = 0; TEST_LOOPING(lc); lc++) {
101
102 /* reset Tst_count in case we are looping */
103 Tst_count = 0;
104
robbiew6ee509b2003-04-01 20:28:41 +0000105//block1:
plars865695b2001-08-27 22:15:12 +0000106 tst_resm(TINFO, "Enter Block 1: test with bad fd");
107 if (write(-1, pbuf, 1) != -1) {
108 tst_resm(TFAIL, "write of invalid fd passed");
109 } else {
110 TEST_ERROR_LOG(errno);
111 if (errno != EBADF) {
112 tst_resm(TFAIL, "expected EBADF got %d", errno);
113 }
114 tst_resm(TPASS, "received EBADF as expected.");
115 }
116 tst_resm(TINFO, "Exit Block 1");
117
robbiew6ee509b2003-04-01 20:28:41 +0000118//block2:
plars865695b2001-08-27 22:15:12 +0000119 tst_resm(TINFO, "Enter Block 2: test with a bad address");
120 fd = creat(filename, 0644);
121 if (fd < 0) {
122 tst_resm(TFAIL, "creating a new file failed");
123 cleanup();
124 /*NOTREACHED*/
125 }
robbiew37d19bd2003-11-14 16:57:49 +0000126 if (write(fd, bad_addr, 10) != -1) {
plars865695b2001-08-27 22:15:12 +0000127 tst_resm(TFAIL, "write() on an invalid buffer "
128 "succeeded, but should have failed");
129 cleanup();
130 /*NOTREACHED*/
131 } else {
132 TEST_ERROR_LOG(errno);
133 if (errno != EFAULT) {
134 tst_resm(TFAIL, "write() returned illegal "
135 "errno: expected EFAULT, got %d",
136 errno);
137 cleanup();
138 /*NOTREACHED*/
139 }
140 tst_resm(TPASS, "received EFAULT as expected.");
141 }
142 tst_resm(TINFO, "Exit Block 2");
143
robbiew6ee509b2003-04-01 20:28:41 +0000144//block3:
plars865695b2001-08-27 22:15:12 +0000145 tst_resm(TINFO, "Enter Block 3: test with invalid pipe");
robbiewd34d5812005-07-11 22:28:09 +0000146 if ((pid = FORK_OR_VFORK()) == 0) { /* child */
robbiew4644c7e2002-04-26 14:33:32 +0000147 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
148 tst_resm(TINFO, "signal failed");
plars865695b2001-08-27 22:15:12 +0000149 }
150 if (pipe(pipefildes) == -1) {
151 tst_brkm(TBROK, NULL, "can't open pipe");
152 exit(errno);
153 }
154 close(pipefildes[0]);
155 if (write(pipefildes[1], pbuf, 1) != -1) {
156 tst_resm(TFAIL, "write on read-closed"
157 "pipe succeeded");
158 exit(-1);
159 } else {
160 if (errno != EPIPE) {
161 tst_resm(TFAIL, "write() failed to set"
162 " errno to EPIPE, got: %d",
163 errno);
164 exit(errno);
165 }
166 exit(0);
167 }
168 } else {
169 if (pid < 0) {
170 tst_resm(TFAIL, "Fork failed");
171 }
172 wait(&status);
173 if (WIFSIGNALED(status) == SIGPIPE) {
174 tst_resm(TFAIL, "child set SIGPIPE in exit");
175 } else if (WEXITSTATUS(status) != 0) {
176 TEST_ERROR_LOG(WEXITSTATUS(status));
177 tst_resm(TFAIL, "exit status from child "
178 "expected 0 got %d", status >> 8);
179 } else {
180 TEST_ERROR_LOG(EPIPE);
181 tst_resm(TPASS, "received EPIPE as expected.");
182 }
183 tst_resm(TINFO, "Exit Block 3");
184 }
subrata_modakdad6e1a2007-10-30 10:46:58 +0000185 close(fd);
plars865695b2001-08-27 22:15:12 +0000186 }
187 cleanup();
188 /*NOTREACHED*/
subrata_modak43337a32009-02-26 11:43:51 +0000189 return 0;
plars865695b2001-08-27 22:15:12 +0000190}
191
192/*
193 * setup()
194 * performs all ONE TIME setup for this test
195 */
196void
197setup(void)
198{
199 /* capture signals */
200 tst_sig(FORK, DEF_HANDLER, cleanup);
201
202
203 /* Set up the expected error numbers for -e option */
204 TEST_EXP_ENOS(exp_enos);
205
206 /* Pause if that option was specified
207 * TEST_PAUSE contains the code to fork the test with the -i option.
208 * You want to make sure you do this before you create your temporary
209 * directory.
210 */
211 TEST_PAUSE;
212
213 /* Create a unique temporary directory and chdir() to it. */
214 tst_tmpdir();
215
nstrazfa31d552002-05-14 16:50:06 +0000216 sprintf(filename, "write05.%d", getpid());
robbiew37d19bd2003-11-14 16:57:49 +0000217
robbiewd34d5812005-07-11 22:28:09 +0000218 bad_addr = mmap(0, 1, PROT_NONE,
219 MAP_PRIVATE_EXCEPT_UCLINUX|MAP_ANONYMOUS, 0, 0);
vapier0722a2b2006-05-12 15:44:11 +0000220 if (bad_addr == MAP_FAILED) {
robbiew37d19bd2003-11-14 16:57:49 +0000221 printf("mmap failed\n");
222 }
223
plars865695b2001-08-27 22:15:12 +0000224}
225
226/*
227 * cleanup()
228 * performs all ONE TIME cleanup for this test at
229 * completion or premature exit
230 */
231void
232cleanup(void)
233{
234 /*
235 * print timing stats if that option was specified.
236 * print errno log if that option was specified.
237 */
238 TEST_CLEANUP;
239
subrata_modak0206d282007-08-06 09:32:49 +0000240 /* Close the file descriptor befor removing the file */
241 close(fd);
242
plars865695b2001-08-27 22:15:12 +0000243 unlink(filename);
244 tst_rmdir();
245
246 /* exit with return code appropriate for results */
247 tst_exit();
248 /*NOTREACHED*/
249}