Home | History | Annotate | Download | only in pwrite
      1 /*
      2  *
      3  *   Copyright (c) International Business Machines  Corp., 2001
      4  *
      5  *   This program is free software;  you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation; either version 2 of the License, or
      8  *   (at your option) any later version.
      9  *
     10  *   This program is distributed in the hope that it will be useful,
     11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     13  *   the GNU General Public License for more details.
     14  *
     15  *   You should have received a copy of the GNU General Public License
     16  *   along with this program;  if not, write to the Free Software
     17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     18  */
     19 
     20 /*
     21  * Test Description:
     22  *  Verify that,
     23  *   1) pwrite() fails when attempted to write to an unnamed pipe,
     24  *      returns ESPIPE.
     25  *   2) pwrite() fails if the specified offset position was invalid,
     26  *	returns EINVAL.
     27  *   3) pwrite() fails if fd is not a valid file descriptor,
     28  *	returns EBADF.
     29  *   4) pwrite() fails if fd is not open for writing, return EBADF.
     30  *   5) pwrite() fails when attempted to write with buf outside
     31  *      accessible address space, returns EFAULT.
     32  */
     33 
     34 #define _XOPEN_SOURCE 500
     35 
     36 #include <errno.h>
     37 #include <unistd.h>
     38 #include <fcntl.h>
     39 
     40 #include "test.h"
     41 #include "safe_macros.h"
     42 
     43 #define TEMPFILE	"pwrite_file"
     44 #define K1		1024
     45 
     46 TCID_DEFINE(pwrite02);
     47 
     48 static char write_buf[K1];
     49 
     50 static void setup(void);
     51 static void cleanup(void);
     52 
     53 static void test_espipe(void);
     54 static void test_einval(void);
     55 static void test_ebadf1(void);
     56 static void test_ebadf2(void);
     57 
     58 #if !defined(UCLINUX)
     59 static void test_efault(void);
     60 #endif
     61 
     62 static void (*testfunc[])(void) = {
     63 	test_espipe, test_einval, test_ebadf1, test_ebadf2,
     64 #if !defined(UCLINUX)
     65 	test_efault
     66 #endif
     67 };
     68 
     69 int TST_TOTAL = ARRAY_SIZE(testfunc);
     70 
     71 int main(int ac, char **av)
     72 {
     73 	int i, lc;
     74 
     75 	tst_parse_opts(ac, av, NULL, NULL);
     76 
     77 	setup();
     78 
     79 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     80 		tst_count = 0;
     81 
     82 		for (i = 0; i < TST_TOTAL; i++)
     83 			(*testfunc[i])();
     84 	}
     85 
     86 	cleanup();
     87 	tst_exit();
     88 }
     89 
     90 /*
     91  * sighandler - handle SIGXFSZ
     92  *
     93  * This is here to start looking at a failure in test case #2.  This
     94  * test case passes on a machine running RedHat 6.2 but it will fail
     95  * on a machine running RedHat 7.1.
     96  */
     97 static void sighandler(int sig)
     98 {
     99 	int ret;
    100 
    101 	if (sig != SIGXFSZ) {
    102 		ret = write(STDOUT_FILENO, "get wrong signal\n",
    103 		            sizeof("get wrong signal\n"));
    104 	} else {
    105 		ret = write(STDOUT_FILENO, "caught SIGXFSZ\n",
    106 		            sizeof("caught SIGXFSZ\n"));
    107 	}
    108 
    109 	(void)ret;
    110 }
    111 
    112 static void setup(void)
    113 {
    114 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
    115 
    116 	/* see the comment in the sighandler() function */
    117 	/* call signal() to trap the signal generated */
    118 	if (signal(SIGXFSZ, sighandler) == SIG_ERR)
    119 		tst_brkm(TBROK, cleanup, "signal() failed");
    120 
    121 	TEST_PAUSE;
    122 
    123 	tst_tmpdir();
    124 
    125 	memset(write_buf, 'a', K1);
    126 }
    127 
    128 static void print_test_result(int err, int exp_errno)
    129 {
    130 	if (err == 0) {
    131 		tst_resm(TFAIL, "call succeeded unexpectedly");
    132 		return;
    133 	}
    134 
    135 	if (err == exp_errno) {
    136 		tst_resm(TPASS, "pwrite failed as expected: %d - %s",
    137 			 err, strerror(err));
    138 	} else {
    139 		tst_resm(TFAIL, "pwrite failed unexpectedly; expected: %d - %s"
    140 			 "return: %d - %s", exp_errno, strerror(exp_errno),
    141 			 err, strerror(err));
    142 	}
    143 }
    144 
    145 static void test_espipe(void)
    146 {
    147 	int pipe_fds[2];
    148 
    149 	SAFE_PIPE(cleanup, pipe_fds);
    150 
    151 	TEST(pwrite(pipe_fds[1], write_buf, K1, 0));
    152 
    153 	print_test_result(errno, ESPIPE);
    154 
    155 	SAFE_CLOSE(cleanup, pipe_fds[0]);
    156 	SAFE_CLOSE(cleanup, pipe_fds[1]);
    157 }
    158 
    159 static void test_einval(void)
    160 {
    161 	int fd;
    162 
    163 	fd = SAFE_OPEN(cleanup, TEMPFILE, O_RDWR | O_CREAT, 0666);
    164 
    165 	/* the specified offset was invalid */
    166 	TEST(pwrite(fd, write_buf, K1, -1));
    167 
    168 	print_test_result(errno, EINVAL);
    169 
    170 	SAFE_CLOSE(cleanup, fd);
    171 }
    172 
    173 static void test_ebadf1(void)
    174 {
    175 	int fd = -1;
    176 
    177 	TEST(pwrite(fd, write_buf, K1, 0));
    178 
    179 	print_test_result(errno, EBADF);
    180 }
    181 
    182 static void test_ebadf2(void)
    183 {
    184 	int fd;
    185 
    186 	fd = SAFE_OPEN(cleanup, TEMPFILE, O_RDONLY | O_CREAT, 0666);
    187 
    188 	TEST(pwrite(fd, write_buf, K1, 0));
    189 
    190 	print_test_result(errno, EBADF);
    191 
    192 	SAFE_CLOSE(cleanup, fd);
    193 }
    194 
    195 #if !defined(UCLINUX)
    196 static void test_efault(void)
    197 {
    198 	int fd;
    199 	char *buf = sbrk(0);
    200 
    201 	fd = SAFE_OPEN(cleanup, TEMPFILE, O_RDWR | O_CREAT, 0666);
    202 
    203 	TEST(pwrite(fd, buf, K1, 0));
    204 
    205 	print_test_result(errno, EFAULT);
    206 
    207 	SAFE_CLOSE(cleanup, fd);
    208 }
    209 #endif
    210 
    211 static void cleanup(void)
    212 {
    213 	tst_rmdir();
    214 }
    215