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) tee() returns -1 and sets errno to EINVAL if fd_in does 21 * not refer to a pipe. 22 * 2) tee() returns -1 and sets errno to EINVAL if fd_out does 23 * not refer to a pipe. 24 * 3) tee() returns -1 and sets errno to EINVAL if fd_in and 25 * fd_out refer to the same pipe. 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 35 #include "test.h" 36 #include "safe_macros.h" 37 #include "lapi/tee.h" 38 39 #define TEST_FILE "testfile" 40 41 #define STR "abcdefghigklmnopqrstuvwxyz" 42 #define TEE_TEST_LEN 10 43 44 static int fd; 45 static int pipes[2]; 46 47 static struct test_case_t { 48 int *fdin; 49 int *fdout; 50 int exp_errno; 51 } test_cases[] = { 52 { &fd, &pipes[1], EINVAL }, 53 { &pipes[0], &fd, EINVAL }, 54 { &pipes[0], &pipes[1], EINVAL }, 55 }; 56 57 static void setup(void); 58 static void cleanup(void); 59 static void tee_verify(const struct test_case_t *); 60 61 char *TCID = "tee02"; 62 int TST_TOTAL = ARRAY_SIZE(test_cases); 63 64 int main(int ac, char **av) 65 { 66 int i, lc; 67 68 tst_parse_opts(ac, av, NULL, NULL); 69 70 setup(); 71 72 for (lc = 0; TEST_LOOPING(lc); lc++) { 73 tst_count = 0; 74 75 for (i = 0; i < TST_TOTAL; i++) 76 tee_verify(&test_cases[i]); 77 } 78 79 cleanup(); 80 tst_exit(); 81 } 82 83 static void setup(void) 84 { 85 if ((tst_kvercmp(2, 6, 17)) < 0) { 86 tst_brkm(TCONF, cleanup, "This test can only run on kernels " 87 "that are 2.6.17 or higher"); 88 } 89 90 TEST_PAUSE; 91 92 tst_sig(FORK, DEF_HANDLER, cleanup); 93 94 tst_tmpdir(); 95 96 fd = SAFE_OPEN(cleanup, TEST_FILE, O_RDWR | O_CREAT); 97 98 SAFE_PIPE(cleanup, pipes); 99 SAFE_WRITE(cleanup, 1, pipes[1], STR, sizeof(STR) - 1); 100 } 101 102 static void tee_verify(const struct test_case_t *tc) 103 { 104 TEST(tee(*(tc->fdin), *(tc->fdout), TEE_TEST_LEN, 0)); 105 106 if (TEST_RETURN != -1) { 107 tst_resm(TFAIL, "tee() returned %ld, " 108 "expected -1, errno:%d", TEST_RETURN, 109 tc->exp_errno); 110 return; 111 } 112 113 if (TEST_ERRNO == tc->exp_errno) { 114 tst_resm(TPASS | TTERRNO, "tee() failed as expected"); 115 } else { 116 tst_resm(TFAIL | TTERRNO, 117 "tee() failed unexpectedly; expected: %d - %s", 118 tc->exp_errno, strerror(tc->exp_errno)); 119 } 120 } 121 122 static void cleanup(void) 123 { 124 if (fd && close(fd) < 0) 125 tst_resm(TWARN | TERRNO, "close fd failed"); 126 127 if (pipes[0] && close(pipes[0]) < 0) 128 tst_resm(TWARN | TERRNO, "close pipes[0] failed"); 129 130 if (pipes[1] && close(pipes[1]) < 0) 131 tst_resm(TWARN | TERRNO, "close pipes[1] failed"); 132 133 tst_rmdir(); 134 } 135