Home | History | Annotate | Download | only in sendfile
      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 
     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  */
    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  */
    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