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 * NAME
22 *	sendfile03.c
23 *
24 * DESCRIPTION
25 *	Testcase to test that sendfile(2) system call returns appropriete
26 *	errnos on error.
27 *
28 * ALGORITHM
29 *	1. Call sendfile(2) with out_fd = -1, and expect EBADF to be returned.
30 *	2. Call sendfile(2) with in_fd = -1, and expect EBADF to be returned.
31 *	3. Call sendfile(2) with in_fd = out_fd = -1, and expect EBADF.
32 *
33 * USAGE:  <for command-line>
34 *  sendfile03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
35 *     where,  -c n : Run n copies concurrently.
36 *             -e   : Turn on errno logging.
37 *             -i n : Execute test n times.
38 *             -I x : Execute test for x seconds.
39 *             -P x : Pause for x seconds between iterations.
40 *             -t   : Turn on syscall timing.
41 *
42 * HISTORY
43 *	07/2001 Ported by Wayne Boyer
44 *
45 * RESTRICTIONS
46 *	NONE
47 */
48
49#include <stdio.h>
50#include <errno.h>
51#include <fcntl.h>
52#include <sys/sendfile.h>
53#include "test.h"
54
55#define FAILED 1
56
57#ifndef OFF_T
58#define OFF_T off_t
59#endif /* Not def: OFF_T */
60
61TCID_DEFINE(sendfile03);
62int TST_TOTAL = 3;
63
64int in_fd, out_fd;
65char in_file[100], out_file[100];
66
67void cleanup(void);
68void setup(void);
69void setup_func1(void);
70
71struct test_case_t {
72	char *desc;
73	void (*setupfunc) ();
74	int out_fd;
75	int in_fd;
76	OFF_T *offset;
77	int count;
78	int exp_errno;
79} testcases[] = {
80	{
81	"Test for EBADF, in_fd = -1", NULL, 8, -1, NULL, 0, EBADF}, {
82	"Test for EBADF, out_fd = -1", NULL, -1, 7, NULL, 0, EBADF}, {
83	"Test for EBADF, in_fd = out_fd = -1", NULL, -1, -1, NULL,
84		    0, EBADF}
85};
86
87int main(int ac, char **av)
88{
89	int i;
90	int lc;
91
92	tst_parse_opts(ac, av, NULL, NULL);
93
94	setup();
95
96	/*
97	 * The following loop checks looping state if -c option given
98	 */
99	for (lc = 0; TEST_LOOPING(lc); lc++) {
100		tst_count = 0;
101
102		for (i = 0; i < TST_TOTAL; ++i) {
103			if (testcases[i].setupfunc != NULL) {
104				testcases[i].setupfunc();
105			}
106
107			TEST(sendfile(testcases[i].out_fd, testcases[i].in_fd,
108				      testcases[i].offset, testcases[i].count));
109
110			if (TEST_RETURN != -1) {
111				tst_resm(TFAIL, "call succeeded unexpectedly");
112				continue;
113			}
114
115			if (TEST_ERRNO != testcases[i].exp_errno) {
116				tst_resm(TFAIL, "sendfile returned unexpected "
117					 "errno, expected: %d, got: %d",
118					 testcases[i].exp_errno, TEST_ERRNO);
119			} else {
120				tst_resm(TPASS, "sendfile() returned %d : %s",
121					 TEST_ERRNO, strerror(TEST_ERRNO));
122			}
123		}
124	}
125	cleanup();
126
127	tst_exit();
128}
129
130/*
131 * setup() - performs all ONE TIME setup for this test.
132 */
133void setup(void)
134{
135	char buf[100];
136
137	tst_sig(NOFORK, DEF_HANDLER, cleanup);
138
139	TEST_PAUSE;
140
141	/* make a temporary directory and cd to it */
142	tst_tmpdir();
143
144	sprintf(in_file, "in.%d", getpid());
145	if ((in_fd = creat(in_file, 00700)) < 0) {
146		tst_brkm(TBROK, cleanup, "creat failed in setup, errno: %d",
147			 errno);
148	}
149	sprintf(buf, "abcdefghijklmnopqrstuvwxyz");
150	if (write(in_fd, buf, strlen(buf)) < 0) {
151		tst_brkm(TBROK, cleanup, "write failed, errno: %d", errno);
152	}
153	close(in_fd);
154	if ((in_fd = open(in_file, O_RDONLY)) < 0) {
155		tst_brkm(TBROK, cleanup, "open failed, errno: %d", errno);
156	}
157	sprintf(out_file, "out.%d", getpid());
158	if ((out_fd = open(out_file, O_TRUNC | O_CREAT | O_RDWR, 0777)) < 0) {
159		tst_brkm(TBROK, cleanup, "open failed, errno: %d", errno);
160	}
161}
162
163/*
164 * cleanup() - performs all ONE TIME cleanup for this test at
165 *	       completion or premature exit.
166 */
167void cleanup(void)
168{
169	/*
170	 * print timing stats if that option was specified.
171	 * print errno log if that option was specified.
172	 */
173	close(out_fd);
174	close(in_fd);
175
176	/* delete the test directory created in setup() */
177	tst_rmdir();
178
179}
180