1 /* 2 * Copyright (c) 2014 Fujitsu Ltd. 3 * Author: Xing Gu <gux.fnst (at) cn.fujitsu.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 */ 17 /* 18 * Description: 19 * Verify that, 20 * 1) vmsplice() returns -1 and sets errno to EBADF if fd 21 * is not valid. 22 * 2) vmsplice() returns -1 and sets errno to EBADF if fd 23 * doesn't refer to a pipe. 24 * 3) vmsplice() returns -1 and sets errno to EINVAL if 25 * nr_segs is greater than IOV_MAX. 26 */ 27 28 #define _GNU_SOURCE 29 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <fcntl.h> 33 #include <unistd.h> 34 #include <fcntl.h> 35 #include <sys/uio.h> 36 37 #include "test.h" 38 #include "safe_macros.h" 39 #include "linux_syscall_numbers.h" 40 #include "lapi/fcntl.h" 41 #include "lapi/vmsplice.h" 42 43 #include "limits_ltp.h" 44 45 #define TESTFILE "testfile" 46 47 #define TEST_BLOCK_SIZE 128 48 49 static char buffer[TEST_BLOCK_SIZE]; 50 static int notvalidfd = -1; 51 static int filefd; 52 static int pipes[2]; 53 static struct iovec ivc; 54 55 static struct test_case_t { 56 int *fd; 57 const struct iovec *iov; 58 unsigned long nr_segs; 59 int exp_errno; 60 } test_cases[] = { 61 { ¬validfd, &ivc, 1, EBADF }, 62 { &filefd, &ivc, 1, EBADF }, 63 { &pipes[1], &ivc, IOV_MAX + 1, EINVAL }, 64 }; 65 66 static void setup(void); 67 static void cleanup(void); 68 static void vmsplice_verify(const struct test_case_t *); 69 70 char *TCID = "vmsplice02"; 71 int TST_TOTAL = ARRAY_SIZE(test_cases); 72 73 int main(int ac, char **av) 74 { 75 int i, lc; 76 77 tst_parse_opts(ac, av, NULL, NULL); 78 79 setup(); 80 81 for (lc = 0; TEST_LOOPING(lc); lc++) { 82 tst_count = 0; 83 84 for (i = 0; i < TST_TOTAL; i++) 85 vmsplice_verify(&test_cases[i]); 86 } 87 88 cleanup(); 89 tst_exit(); 90 } 91 92 static void setup(void) 93 { 94 if ((tst_kvercmp(2, 6, 17)) < 0) { 95 tst_brkm(TCONF, cleanup, "This test can only run on " 96 "kernels that are 2.6.17 or higher"); 97 } 98 99 tst_sig(NOFORK, DEF_HANDLER, cleanup); 100 101 TEST_PAUSE; 102 103 tst_tmpdir(); 104 105 if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC) { 106 tst_brkm(TCONF, cleanup, "Cannot do splice() " 107 "on a file located on an NFS filesystem"); 108 } 109 110 filefd = SAFE_OPEN(cleanup, TESTFILE, 111 O_WRONLY | O_CREAT, 0644); 112 113 SAFE_PIPE(cleanup, pipes); 114 115 ivc.iov_base = buffer; 116 ivc.iov_len = TEST_BLOCK_SIZE; 117 } 118 119 static void vmsplice_verify(const struct test_case_t *tc) 120 { 121 TEST(vmsplice(*(tc->fd), tc->iov, tc->nr_segs, 0)); 122 123 if (TEST_RETURN != -1) { 124 tst_resm(TFAIL, "vmsplice() returned %ld, " 125 "expected -1, errno:%d", TEST_RETURN, 126 tc->exp_errno); 127 return; 128 } 129 130 if (TEST_ERRNO == tc->exp_errno) { 131 tst_resm(TPASS | TTERRNO, "vmsplice() failed as expected"); 132 } else { 133 tst_resm(TFAIL | TTERRNO, 134 "vmsplice() failed unexpectedly; expected: %d - %s", 135 tc->exp_errno, strerror(tc->exp_errno)); 136 } 137 } 138 139 static void cleanup(void) 140 { 141 if (filefd && close(filefd) < 0) 142 tst_resm(TWARN | TERRNO, "close filefd failed"); 143 144 if (pipes[0] && close(pipes[0]) < 0) 145 tst_resm(TWARN | TERRNO, "close pipes[0] failed"); 146 147 if (pipes[1] && close(pipes[1]) < 0) 148 tst_resm(TWARN | TERRNO, "close pipes[1] failed"); 149 150 tst_rmdir(); 151 } 152