blob: 68f7ad34077c2f44eee0b6aef931e3a2d2008339 [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
plars865695b2001-08-27 22:15:12 +000049 *
50 * Restrictions
51 * None
52 */
53
54#include <errno.h>
55#include <stdio.h>
56#include <sys/wait.h>
57#include "test.h"
58#include "usctest.h"
59
60void setup(void);
61void cleanup(void);
62
63/* 0 terminated list of expected errnos */
64int exp_enos[] = {9,14,32,0};
65
nstrazfa31d552002-05-14 16:50:06 +000066char *TCID = "write05"; /* Test program identifier */
plars865695b2001-08-27 22:15:12 +000067int TST_TOTAL = 1; /* Total number of test cases */
68extern int Tst_count;
69char filename[100];
70
71main(int argc, char **argv)
72{
73 int lc; /* loop counter */
74 char *msg; /* message returned from parse_opts */
75
76 char pbuf[BUFSIZ];
77 int pipefildes[2];
78 int status, pid, fd;
79
80 /* parse standard options */
81 if ((msg = parse_opts(argc, argv, (option_t *)NULL, NULL)) !=
82 (char *) NULL) {
83 tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
84 /*NOTREACHED*/
85 }
86
87 /* global setup */
88 setup();
89
90 /* The following loop checks looping state if -i option given */
91 for (lc = 0; TEST_LOOPING(lc); lc++) {
92
93 /* reset Tst_count in case we are looping */
94 Tst_count = 0;
95
96block1:
97 tst_resm(TINFO, "Enter Block 1: test with bad fd");
98 if (write(-1, pbuf, 1) != -1) {
99 tst_resm(TFAIL, "write of invalid fd passed");
100 } else {
101 TEST_ERROR_LOG(errno);
102 if (errno != EBADF) {
103 tst_resm(TFAIL, "expected EBADF got %d", errno);
104 }
105 tst_resm(TPASS, "received EBADF as expected.");
106 }
107 tst_resm(TINFO, "Exit Block 1");
108
109block2:
110 tst_resm(TINFO, "Enter Block 2: test with a bad address");
111 fd = creat(filename, 0644);
112 if (fd < 0) {
113 tst_resm(TFAIL, "creating a new file failed");
114 cleanup();
115 /*NOTREACHED*/
116 }
117 if (write(fd, (void *)-1, 10) != -1) {
118 tst_resm(TFAIL, "write() on an invalid buffer "
119 "succeeded, but should have failed");
120 cleanup();
121 /*NOTREACHED*/
122 } else {
123 TEST_ERROR_LOG(errno);
124 if (errno != EFAULT) {
125 tst_resm(TFAIL, "write() returned illegal "
126 "errno: expected EFAULT, got %d",
127 errno);
128 cleanup();
129 /*NOTREACHED*/
130 }
131 tst_resm(TPASS, "received EFAULT as expected.");
132 }
133 tst_resm(TINFO, "Exit Block 2");
134
135block3:
136 tst_resm(TINFO, "Enter Block 3: test with invalid pipe");
137 if ((pid = fork()) == 0) { /* child */
robbiew4644c7e2002-04-26 14:33:32 +0000138 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
139 tst_resm(TINFO, "signal failed");
plars865695b2001-08-27 22:15:12 +0000140 }
141 if (pipe(pipefildes) == -1) {
142 tst_brkm(TBROK, NULL, "can't open pipe");
143 exit(errno);
144 }
145 close(pipefildes[0]);
146 if (write(pipefildes[1], pbuf, 1) != -1) {
147 tst_resm(TFAIL, "write on read-closed"
148 "pipe succeeded");
149 exit(-1);
150 } else {
151 if (errno != EPIPE) {
152 tst_resm(TFAIL, "write() failed to set"
153 " errno to EPIPE, got: %d",
154 errno);
155 exit(errno);
156 }
157 exit(0);
158 }
159 } else {
160 if (pid < 0) {
161 tst_resm(TFAIL, "Fork failed");
162 }
163 wait(&status);
164 if (WIFSIGNALED(status) == SIGPIPE) {
165 tst_resm(TFAIL, "child set SIGPIPE in exit");
166 } else if (WEXITSTATUS(status) != 0) {
167 TEST_ERROR_LOG(WEXITSTATUS(status));
168 tst_resm(TFAIL, "exit status from child "
169 "expected 0 got %d", status >> 8);
170 } else {
171 TEST_ERROR_LOG(EPIPE);
172 tst_resm(TPASS, "received EPIPE as expected.");
173 }
174 tst_resm(TINFO, "Exit Block 3");
175 }
176 }
177 cleanup();
178 /*NOTREACHED*/
179}
180
181/*
182 * setup()
183 * performs all ONE TIME setup for this test
184 */
185void
186setup(void)
187{
188 /* capture signals */
189 tst_sig(FORK, DEF_HANDLER, cleanup);
190
191
192 /* Set up the expected error numbers for -e option */
193 TEST_EXP_ENOS(exp_enos);
194
195 /* Pause if that option was specified
196 * TEST_PAUSE contains the code to fork the test with the -i option.
197 * You want to make sure you do this before you create your temporary
198 * directory.
199 */
200 TEST_PAUSE;
201
202 /* Create a unique temporary directory and chdir() to it. */
203 tst_tmpdir();
204
nstrazfa31d552002-05-14 16:50:06 +0000205 sprintf(filename, "write05.%d", getpid());
plars865695b2001-08-27 22:15:12 +0000206}
207
208/*
209 * cleanup()
210 * performs all ONE TIME cleanup for this test at
211 * completion or premature exit
212 */
213void
214cleanup(void)
215{
216 /*
217 * print timing stats if that option was specified.
218 * print errno log if that option was specified.
219 */
220 TEST_CLEANUP;
221
222 unlink(filename);
223 tst_rmdir();
224
225 /* exit with return code appropriate for results */
226 tst_exit();
227 /*NOTREACHED*/
228}