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