blob: a7c536b1597103074b164b0d1252ebe485e15d88 [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
22 * sendfile02.c
23 *
24 * DESCRIPTION
25 * Testcase to test the basic functionality of the sendfile(2) system call.
26 *
27 * ALGORITHM
28 * 1. call sendfile(2) with offset = 0
29 * 2. call sendfile(2) with offset in the middle of the file
30 *
31 * USAGE: <for command-line>
32 * sendfile02 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
subrata_modak56207ce2009-03-23 13:35:39 +000033 * where,
plars865695b2001-08-27 22:15:12 +000034 * -f : Turn off functionality Testing.
35 * -i n : Execute test n times.
36 * -I x : Execute test for x seconds.
37 * -P x : Pause for x seconds between iterations.
38 * -t : Turn on syscall timing.
39 *
40 * HISTORY
41 * 07/2001 Ported by Wayne Boyer
plars16bfb442002-08-05 22:07:16 +000042 * 08/2002 Make it use a socket so it works with 2.5 kernel
plars865695b2001-08-27 22:15:12 +000043 *
44 * RESTRICTIONS
45 * NONE
46 */
47#include <stdio.h>
48#include <errno.h>
49#include <fcntl.h>
50#include <sys/stat.h>
plars8b6d9bf2002-03-05 13:55:58 +000051#include <sys/sendfile.h>
plars16bfb442002-08-05 22:07:16 +000052#include <sys/types.h>
robbiew31f6f672003-01-28 14:50:49 +000053#include <sys/wait.h>
plars16bfb442002-08-05 22:07:16 +000054#include <sys/socket.h>
55#include <netinet/in.h>
robbiew31f6f672003-01-28 14:50:49 +000056#include <arpa/inet.h>
subrata_modak498546d2007-12-05 08:44:26 +000057#include <unistd.h>
subrata_modak923b23f2009-11-02 13:57:16 +000058#include <inttypes.h>
subrata_modak498546d2007-12-05 08:44:26 +000059
plars865695b2001-08-27 22:15:12 +000060#include "usctest.h"
61#include "test.h"
62
subrata_modakb752e852007-11-28 11:20:03 +000063#ifndef OFF_T
64#define OFF_T off_t
65#endif /* Not def: OFF_T */
66
subrata_modak585950c2008-08-20 10:55:19 +000067TCID_DEFINE(sendfile02);
plars865695b2001-08-27 22:15:12 +000068int TST_TOTAL = 4;
69extern int Tst_count;
70
71char in_file[100];
72char out_file[100];
plars16bfb442002-08-05 22:07:16 +000073int out_fd;
robbiew31f6f672003-01-28 14:50:49 +000074pid_t child_pid;
robbiew98270662003-05-14 14:17:45 +000075static int sockfd, s;
subrata_modak56207ce2009-03-23 13:35:39 +000076static struct sockaddr_in sin1; /* shared between do_child and create_server */
plars865695b2001-08-27 22:15:12 +000077
78void cleanup(void);
robbiewd34d5812005-07-11 22:28:09 +000079void do_child(void);
plars865695b2001-08-27 22:15:12 +000080void setup(void);
plars16bfb442002-08-05 22:07:16 +000081int create_server(void);
plars865695b2001-08-27 22:15:12 +000082
83struct test_case_t {
84 char *desc;
85 int offset;
86 int exp_retval;
subrata_modak498546d2007-12-05 08:44:26 +000087 int exp_updated_offset;
plars865695b2001-08-27 22:15:12 +000088} testcases[] = {
subrata_modak56207ce2009-03-23 13:35:39 +000089 {
90 "Test sendfile(2) with offset = 0", 0, 26, 26}, {
91 "Test sendfile(2) with offset in the middle of file", 2, 24, 26}, {
92 "Test sendfile(2) with offset in the middle of file", 4, 22, 26}, {
93 "Test sendfile(2) with offset in the middle of file", 6, 20, 26}
plars865695b2001-08-27 22:15:12 +000094};
95
robbiewd34d5812005-07-11 22:28:09 +000096#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +000097static char *argv0;
robbiewd34d5812005-07-11 22:28:09 +000098#endif
99
subrata_modakb752e852007-11-28 11:20:03 +0000100void do_sendfile(OFF_T offset, int i)
plars865695b2001-08-27 22:15:12 +0000101{
plars16bfb442002-08-05 22:07:16 +0000102 int in_fd;
plars865695b2001-08-27 22:15:12 +0000103 struct stat sb;
robbiew33b77742002-10-02 14:56:00 +0000104 int wait_status;
robbiew31f6f672003-01-28 14:50:49 +0000105 int wait_stat;
subrata_modak498546d2007-12-05 08:44:26 +0000106 off_t before_pos, after_pos;
107
robbiew31f6f672003-01-28 14:50:49 +0000108 out_fd = create_server();
plars865695b2001-08-27 22:15:12 +0000109
110 if ((in_fd = open(in_file, O_RDONLY)) < 0) {
111 tst_brkm(TBROK, cleanup, "open failed: %d", errno);
Garrett Cooper53740502010-12-16 00:04:01 -0800112 }
plars865695b2001-08-27 22:15:12 +0000113 if (stat(in_file, &sb) < 0) {
114 tst_brkm(TBROK, cleanup, "stat failed: %d", errno);
Garrett Cooper53740502010-12-16 00:04:01 -0800115 }
subrata_modak498546d2007-12-05 08:44:26 +0000116
117 if ((before_pos = lseek(in_fd, 0, SEEK_CUR)) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000118 tst_brkm(TBROK, cleanup,
119 "lseek before invoking sendfile failed: %d", errno);
Garrett Cooper53740502010-12-16 00:04:01 -0800120 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000121
plars865695b2001-08-27 22:15:12 +0000122 TEST(sendfile(out_fd, in_fd, &offset, sb.st_size - offset));
123
subrata_modak498546d2007-12-05 08:44:26 +0000124 if ((after_pos = lseek(in_fd, 0, SEEK_CUR)) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000125 tst_brkm(TBROK, cleanup,
126 "lseek after invoking sendfile failed: %d", errno);
Garrett Cooper53740502010-12-16 00:04:01 -0800127 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000128
plars865695b2001-08-27 22:15:12 +0000129 if (STD_FUNCTIONAL_TEST) {
robbiew98270662003-05-14 14:17:45 +0000130 /* Close the sockets */
131 shutdown(sockfd, SHUT_RDWR);
132 shutdown(s, SHUT_RDWR);
plars865695b2001-08-27 22:15:12 +0000133 if (TEST_RETURN != testcases[i].exp_retval) {
134 tst_resm(TFAIL, "sendfile(2) failed to return "
135 "expected value, expected: %d, "
subrata_modak923b23f2009-11-02 13:57:16 +0000136 "got: %ld", testcases[i].exp_retval,
plars865695b2001-08-27 22:15:12 +0000137 TEST_RETURN);
robbiew31f6f672003-01-28 14:50:49 +0000138 kill(child_pid, SIGKILL);
subrata_modak498546d2007-12-05 08:44:26 +0000139 } else if (offset != testcases[i].exp_updated_offset) {
140 tst_resm(TFAIL, "sendfile(2) failed to update "
141 "OFFSET parameter to expected value, "
subrata_modak923b23f2009-11-02 13:57:16 +0000142 "expected: %d, got: %"PRId64,
143 testcases[i].exp_updated_offset, (int64_t)offset);
subrata_modak498546d2007-12-05 08:44:26 +0000144 } else if (before_pos != after_pos) {
145 tst_resm(TFAIL, "sendfile(2) updated the file position "
subrata_modak923b23f2009-11-02 13:57:16 +0000146 " of in_fd unexpectedly, expected file position: %"PRId64", "
147 " actual file position %"PRId64,
148 (int64_t)before_pos, (int64_t)after_pos);
plars865695b2001-08-27 22:15:12 +0000149 } else {
150 tst_resm(TPASS, "functionality of sendfile() is "
subrata_modak56207ce2009-03-23 13:35:39 +0000151 "correct");
robbiew31f6f672003-01-28 14:50:49 +0000152 wait_status = waitpid(-1, &wait_stat, 0);
subrata_modak56207ce2009-03-23 13:35:39 +0000153 }
plars865695b2001-08-27 22:15:12 +0000154 } else {
155 tst_resm(TPASS, "call succeeded");
robbiew98270662003-05-14 14:17:45 +0000156 /* Close the sockets */
157 shutdown(sockfd, SHUT_RDWR);
158 shutdown(s, SHUT_RDWR);
159 if (TEST_RETURN != testcases[i].exp_retval) {
robbiew31f6f672003-01-28 14:50:49 +0000160 kill(child_pid, SIGKILL);
robbiew98270662003-05-14 14:17:45 +0000161 } else {
robbiew31f6f672003-01-28 14:50:49 +0000162 wait_status = waitpid(-1, &wait_stat, 0);
robbiew98270662003-05-14 14:17:45 +0000163 }
plars865695b2001-08-27 22:15:12 +0000164 }
165
plars865695b2001-08-27 22:15:12 +0000166 close(in_fd);
robbiew33b77742002-10-02 14:56:00 +0000167
plars865695b2001-08-27 22:15:12 +0000168}
169
170/*
robbiewd34d5812005-07-11 22:28:09 +0000171 * do_child
172 */
subrata_modak56207ce2009-03-23 13:35:39 +0000173void do_child()
robbiewd34d5812005-07-11 22:28:09 +0000174{
175 int lc;
vapier1968aef2006-05-26 06:35:43 +0000176 socklen_t length;
robbiewd34d5812005-07-11 22:28:09 +0000177 char rbuf[4096];
178
179 for (lc = 0; TEST_LOOPING(lc); lc++) {
180 length = sizeof(sin1);
subrata_modak56207ce2009-03-23 13:35:39 +0000181 recvfrom(sockfd, rbuf, 4096, 0, (struct sockaddr *)&sin1,
182 &length);
robbiewd34d5812005-07-11 22:28:09 +0000183 }
184 exit(0);
185}
186
187/*
plars865695b2001-08-27 22:15:12 +0000188 * setup() - performs all ONE TIME setup for this test.
189 */
subrata_modak56207ce2009-03-23 13:35:39 +0000190void setup()
plars865695b2001-08-27 22:15:12 +0000191{
192 int fd;
193 char buf[100];
194
plars16bfb442002-08-05 22:07:16 +0000195 tst_sig(FORK, DEF_HANDLER, cleanup);
plars865695b2001-08-27 22:15:12 +0000196
plars865695b2001-08-27 22:15:12 +0000197 TEST_PAUSE;
198
199 /* make a temporary directory and cd to it */
200 tst_tmpdir();
201 sprintf(in_file, "in.%d", getpid());
202 if ((fd = creat(in_file, 00700)) < 0) {
203 tst_brkm(TBROK, cleanup, "creat failed in setup, errno: %d",
204 errno);
Garrett Cooper53740502010-12-16 00:04:01 -0800205 }
plars865695b2001-08-27 22:15:12 +0000206 sprintf(buf, "abcdefghijklmnopqrstuvwxyz");
207 if (write(fd, buf, strlen(buf)) < 0) {
208 tst_brkm(TBROK, cleanup, "write failed, errno: %d", errno);
Garrett Cooper53740502010-12-16 00:04:01 -0800209 }
plars865695b2001-08-27 22:15:12 +0000210 close(fd);
211 sprintf(out_file, "out.%d", getpid());
212}
213
214/*
215 * cleanup() - performs all ONE TIME cleanup for this test at
216 * completion or premature exit.
217 */
subrata_modak56207ce2009-03-23 13:35:39 +0000218void cleanup()
plars865695b2001-08-27 22:15:12 +0000219{
220 /*
221 * print timing stats if that option was specified.
222 * print errno log if that option was specified.
223 */
224 TEST_CLEANUP;
225
plars16bfb442002-08-05 22:07:16 +0000226 close(out_fd);
plars865695b2001-08-27 22:15:12 +0000227 /* delete the test directory created in setup() */
228 tst_rmdir();
229
plars865695b2001-08-27 22:15:12 +0000230}
231
subrata_modak56207ce2009-03-23 13:35:39 +0000232int create_server(void)
233{
234 static int count = 0;
plars16bfb442002-08-05 22:07:16 +0000235
236 sockfd = socket(PF_INET, SOCK_DGRAM, 0);
subrata_modak56207ce2009-03-23 13:35:39 +0000237 if (sockfd < 0) {
plars16bfb442002-08-05 22:07:16 +0000238 tst_brkm(TBROK, cleanup, "call to socket() failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000239 strerror(errno));
plars16bfb442002-08-05 22:07:16 +0000240 return -1;
241 }
robbiew31f6f672003-01-28 14:50:49 +0000242 sin1.sin_family = AF_INET;
subrata_modak6b0adc92008-02-25 11:33:27 +0000243 sin1.sin_port = htons(((getpid() * TST_TOTAL) % 32768) + 11000 + count);
robbiew31f6f672003-01-28 14:50:49 +0000244 sin1.sin_addr.s_addr = INADDR_ANY;
robbiewe93a3242005-08-31 20:27:12 +0000245 count++;
subrata_modak56207ce2009-03-23 13:35:39 +0000246 if (bind(sockfd, (struct sockaddr *)&sin1, sizeof(sin1)) < 0) {
plars16bfb442002-08-05 22:07:16 +0000247 tst_brkm(TBROK, cleanup, "call to bind() failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000248 strerror(errno));
plars16bfb442002-08-05 22:07:16 +0000249 return -1;
250 }
robbiewd34d5812005-07-11 22:28:09 +0000251 child_pid = FORK_OR_VFORK();
subrata_modak56207ce2009-03-23 13:35:39 +0000252 if (child_pid < 0) {
plars16bfb442002-08-05 22:07:16 +0000253 tst_brkm(TBROK, cleanup, "client/server fork failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000254 strerror(errno));
plars16bfb442002-08-05 22:07:16 +0000255 return -1;
256 }
subrata_modak56207ce2009-03-23 13:35:39 +0000257 if (!child_pid) { /* child */
robbiewd34d5812005-07-11 22:28:09 +0000258#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000259 if (self_exec(argv0, "") < 0) {
robbiewd34d5812005-07-11 22:28:09 +0000260 tst_brkm(TBROK, cleanup, "self_exec failed");
261 return -1;
subrata_modak56207ce2009-03-23 13:35:39 +0000262
plars16bfb442002-08-05 22:07:16 +0000263 }
robbiewd34d5812005-07-11 22:28:09 +0000264#else
265 do_child();
266#endif
plars16bfb442002-08-05 22:07:16 +0000267 }
268
269 s = socket(PF_INET, SOCK_DGRAM, 0);
270 inet_aton("127.0.0.1", &sin1.sin_addr);
subrata_modak56207ce2009-03-23 13:35:39 +0000271 if (s < 0) {
plars16bfb442002-08-05 22:07:16 +0000272 tst_brkm(TBROK, cleanup, "call to socket() failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000273 strerror(errno));
plars16bfb442002-08-05 22:07:16 +0000274 return -1;
275 }
subrata_modak56207ce2009-03-23 13:35:39 +0000276 if (connect(s, (struct sockaddr *)&sin1, sizeof(sin1)) < 0) {
plars16bfb442002-08-05 22:07:16 +0000277 tst_brkm(TBROK, cleanup, "call to connect() failed: %s",
subrata_modak56207ce2009-03-23 13:35:39 +0000278 strerror(errno));
plars16bfb442002-08-05 22:07:16 +0000279 }
280 return s;
281
282}
robbiewaa01abd2003-03-27 18:39:24 +0000283
284int main(int ac, char **av)
285{
286 int i;
subrata_modak56207ce2009-03-23 13:35:39 +0000287 int lc; /* loop counter */
288 char *msg; /* parse_opts() return message */
robbiewaa01abd2003-03-27 18:39:24 +0000289
Garrett Cooper45e285d2010-11-22 12:19:25 -0800290 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
Garrett Cooper53740502010-12-16 00:04:01 -0800291<<<<<<< HEAD
Garrett Cooper60fa8012010-11-22 13:50:58 -0800292 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper53740502010-12-16 00:04:01 -0800293=======
294 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
295>>>>>>> master
296 }
robbiewd34d5812005-07-11 22:28:09 +0000297#ifdef UCLINUX
298 argv0 = av[0];
299 maybe_run_child(&do_child, "");
300#endif
301
robbiewaa01abd2003-03-27 18:39:24 +0000302 setup();
303
304 /*
305 * The following loop checks looping state if -c option given
306 */
307 for (lc = 0; TEST_LOOPING(lc); lc++) {
308 Tst_count = 0;
309
310 for (i = 0; i < TST_TOTAL; ++i) {
311 do_sendfile(testcases[i].offset, i);
312 }
313 }
314 cleanup();
315
Garrett Cooper53740502010-12-16 00:04:01 -0800316 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800317}