• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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