Home | History | Annotate | Download | only in tee
      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