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 Description:
22 * Verify that,
23 * 1) pwrite() fails when attempted to write to an unnamed pipe,
24 * returns ESPIPE.
25 * 2) pwrite() fails if the specified offset position was invalid,
26 * returns EINVAL.
27 * 3) pwrite() fails if fd is not a valid file descriptor,
28 * returns EBADF.
29 * 4) pwrite() fails if fd is not open for writing, return EBADF.
30 * 5) pwrite() fails when attempted to write with buf outside
31 * accessible address space, returns EFAULT.
32 */
33
34 #define _XOPEN_SOURCE 500
35
36 #include <errno.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39
40 #include "test.h"
41 #include "safe_macros.h"
42
43 #define TEMPFILE "pwrite_file"
44 #define K1 1024
45
46 TCID_DEFINE(pwrite02);
47
48 static char write_buf[K1];
49
50 static void setup(void);
51 static void cleanup(void);
52
53 static void test_espipe(void);
54 static void test_einval(void);
55 static void test_ebadf1(void);
56 static void test_ebadf2(void);
57
58 #if !defined(UCLINUX)
59 static void test_efault(void);
60 #endif
61
62 static void (*testfunc[])(void) = {
63 test_espipe, test_einval, test_ebadf1, test_ebadf2,
64 #if !defined(UCLINUX)
65 test_efault
66 #endif
67 };
68
69 int TST_TOTAL = ARRAY_SIZE(testfunc);
70
main(int ac,char ** av)71 int main(int ac, char **av)
72 {
73 int i, lc;
74
75 tst_parse_opts(ac, av, NULL, NULL);
76
77 setup();
78
79 for (lc = 0; TEST_LOOPING(lc); lc++) {
80 tst_count = 0;
81
82 for (i = 0; i < TST_TOTAL; i++)
83 (*testfunc[i])();
84 }
85
86 cleanup();
87 tst_exit();
88 }
89
90 /*
91 * sighandler - handle SIGXFSZ
92 *
93 * This is here to start looking at a failure in test case #2. This
94 * test case passes on a machine running RedHat 6.2 but it will fail
95 * on a machine running RedHat 7.1.
96 */
sighandler(int sig)97 static void sighandler(int sig)
98 {
99 int ret;
100
101 if (sig != SIGXFSZ) {
102 ret = write(STDOUT_FILENO, "get wrong signal\n",
103 sizeof("get wrong signal\n"));
104 } else {
105 ret = write(STDOUT_FILENO, "caught SIGXFSZ\n",
106 sizeof("caught SIGXFSZ\n"));
107 }
108
109 (void)ret;
110 }
111
setup(void)112 static void setup(void)
113 {
114 tst_sig(NOFORK, DEF_HANDLER, cleanup);
115
116 /* see the comment in the sighandler() function */
117 /* call signal() to trap the signal generated */
118 if (signal(SIGXFSZ, sighandler) == SIG_ERR)
119 tst_brkm(TBROK, cleanup, "signal() failed");
120
121 TEST_PAUSE;
122
123 tst_tmpdir();
124
125 memset(write_buf, 'a', K1);
126 }
127
print_test_result(int err,int exp_errno)128 static void print_test_result(int err, int exp_errno)
129 {
130 if (err == 0) {
131 tst_resm(TFAIL, "call succeeded unexpectedly");
132 return;
133 }
134
135 if (err == exp_errno) {
136 tst_resm(TPASS, "pwrite failed as expected: %d - %s",
137 err, strerror(err));
138 } else {
139 tst_resm(TFAIL, "pwrite failed unexpectedly; expected: %d - %s"
140 "return: %d - %s", exp_errno, strerror(exp_errno),
141 err, strerror(err));
142 }
143 }
144
test_espipe(void)145 static void test_espipe(void)
146 {
147 int pipe_fds[2];
148
149 SAFE_PIPE(cleanup, pipe_fds);
150
151 TEST(pwrite(pipe_fds[1], write_buf, K1, 0));
152
153 print_test_result(errno, ESPIPE);
154
155 SAFE_CLOSE(cleanup, pipe_fds[0]);
156 SAFE_CLOSE(cleanup, pipe_fds[1]);
157 }
158
test_einval(void)159 static void test_einval(void)
160 {
161 int fd;
162
163 fd = SAFE_OPEN(cleanup, TEMPFILE, O_RDWR | O_CREAT, 0666);
164
165 /* the specified offset was invalid */
166 TEST(pwrite(fd, write_buf, K1, -1));
167
168 print_test_result(errno, EINVAL);
169
170 SAFE_CLOSE(cleanup, fd);
171 }
172
test_ebadf1(void)173 static void test_ebadf1(void)
174 {
175 int fd = -1;
176
177 TEST(pwrite(fd, write_buf, K1, 0));
178
179 print_test_result(errno, EBADF);
180 }
181
test_ebadf2(void)182 static void test_ebadf2(void)
183 {
184 int fd;
185
186 fd = SAFE_OPEN(cleanup, TEMPFILE, O_RDONLY | O_CREAT, 0666);
187
188 TEST(pwrite(fd, write_buf, K1, 0));
189
190 print_test_result(errno, EBADF);
191
192 SAFE_CLOSE(cleanup, fd);
193 }
194
195 #if !defined(UCLINUX)
test_efault(void)196 static void test_efault(void)
197 {
198 int fd;
199 char *buf = sbrk(0);
200
201 fd = SAFE_OPEN(cleanup, TEMPFILE, O_RDWR | O_CREAT, 0666);
202
203 TEST(pwrite(fd, buf, K1, 0));
204
205 print_test_result(errno, EFAULT);
206
207 SAFE_CLOSE(cleanup, fd);
208 }
209 #endif
210
cleanup(void)211 static void cleanup(void)
212 {
213 tst_rmdir();
214 }
215