1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 * Copyright (c) Red Hat Inc., 2007
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 * the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /*
22 * NAME
23 * sendfile07.c
24 *
25 * DESCRIPTION
26 * Testcase to test that sendfile(2) system call returns EAGAIN
27 * when passing blocked out_fd. Here out_fd is opend with O_NONBLOCK.
28 *
29 * ALGORITHM
30 * 1. Make sockets with socketpair(&p). Use p[1] as out_fd.
31 * 2. Set O_NONBLOCK flag of out_fd on.
32 * 3. Write much datum to out_fd till write() returns EAGAIN.
33 * 4. Call sendfile with out_fd, and expect EAGAIN.
34 *
35 * USAGE: <for command-line>
36 * sendfile07 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
37 * where, -c n : Run n copies concurrently.
38 * -e : Turn on errno logging.
39 * -i n : Execute test n times.
40 * -I x : Execute test for x seconds.
41 * -P x : Pause for x seconds between iterations.
42 * -t : Turn on syscall timing.
43 *
44 * HISTORY
45 * 12/2007 Copyed from sendfile03.c by Masatake YAMATO
46 *
47 * RESTRICTIONS
48 * NONE
49 */
50
51 #include <stdio.h>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <sys/sendfile.h>
55 #include <sys/socket.h>
56 #include "test.h"
57
58 #ifndef OFF_T
59 #define OFF_T off_t
60 #endif /* Not def: OFF_T */
61
62 TCID_DEFINE(sendfile07);
63 int TST_TOTAL = 1;
64
65 int in_fd, out_fd = 0, ignored_fd = 0;
66 char in_file[100];
67
68 /* To make out_fd overflow, write much chars
69 to out_fd. MAX_FILL_DATA_LENGTH defines the `much'. */
70 #define MAX_FILL_DATA_LENGTH 0xFFFFFFF
71
72 void cleanup(void);
73 void setup(void);
74
main(int ac,char ** av)75 int main(int ac, char **av)
76 {
77 int lc;
78
79 tst_parse_opts(ac, av, NULL, NULL);
80
81 setup();
82
83 /*
84 * The following loop checks looping state if -c option given
85 */
86 for (lc = 0; TEST_LOOPING(lc); lc++) {
87 tst_count = 0;
88
89 TEST(sendfile(out_fd, in_fd, NULL, 1));
90
91 if (TEST_RETURN != -1) {
92 tst_resm(TFAIL, "call succeeded unexpectedly");
93 continue;
94 }
95
96 if (TEST_ERRNO != EAGAIN) {
97 tst_resm(TFAIL, "sendfile returned unexpected "
98 "errno, expected: %d, got: %d",
99 EAGAIN, TEST_ERRNO);
100 } else {
101 tst_resm(TPASS, "sendfile() returned %d : %s",
102 TEST_ERRNO, strerror(TEST_ERRNO));
103 }
104 }
105
106 cleanup();
107 tst_exit();
108
109 }
110
111 /*
112 * setup() - performs all ONE TIME setup for this test.
113 */
setup(void)114 void setup(void)
115 {
116 char buf[100];
117 int p[2];
118 int i, r;
119
120 tst_sig(NOFORK, DEF_HANDLER, cleanup);
121
122 TEST_PAUSE;
123
124 /* make a temporary directory and cd to it */
125 tst_tmpdir();
126
127 sprintf(in_file, "in.%d", getpid());
128 if ((in_fd = creat(in_file, 00700)) < 0) {
129 tst_brkm(TBROK, cleanup, "creat failed in setup, errno: %d",
130 errno);
131 }
132 sprintf(buf, "abcdefghijklmnopqrstuvwxyz");
133 if (write(in_fd, buf, strlen(buf)) < 0) {
134 tst_brkm(TBROK, cleanup, "write failed, errno: %d", errno);
135 }
136 close(in_fd);
137 if ((in_fd = open(in_file, O_RDONLY)) < 0) {
138 tst_brkm(TBROK, cleanup, "open failed, errno: %d", errno);
139 }
140
141 /* Make fulfilled out_fd. */
142 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, p) < 0) {
143 tst_brkm(TBROK, cleanup, "socketpair failed, errno: %d", errno);
144 }
145
146 /* Don't close.
147 You cannot write nothing on out_fd if ignored_fd is closed. */
148 ignored_fd = p[0];
149 out_fd = p[1];
150 if (fcntl(out_fd, F_SETFL, O_WRONLY | O_NONBLOCK) < 0) {
151 tst_brkm(TBROK, cleanup, "fcntl failed, errno: %d", errno);
152 }
153
154 i = MAX_FILL_DATA_LENGTH;
155 while (i > 0) {
156 r = write(out_fd, buf, 1);
157 if (r < 0) {
158 if (errno == EAGAIN) {
159 break;
160 } else {
161 tst_brkm(TBROK, cleanup,
162 "write failed to fill out_fd, errno: %d",
163 errno);
164 }
165 }
166 i--;
167 }
168 if (i == 0) {
169 tst_brkm(TBROK, cleanup,
170 "fail to fill out_fd, write %d bytes but EAGAIN it not returned.",
171 MAX_FILL_DATA_LENGTH);
172 }
173 }
174
175 /*
176 * cleanup() - performs all ONE TIME cleanup for this test at
177 * completion or premature exit.
178 */
cleanup(void)179 void cleanup(void)
180 {
181 /*
182 * print timing stats if that option was specified.
183 * print errno log if that option was specified.
184 */
185 if (out_fd)
186 close(out_fd);
187 if (ignored_fd)
188 close(ignored_fd);
189 close(in_fd);
190
191 /* delete the test directory created in setup() */
192 tst_rmdir();
193
194 }
195