| /* |
| * |
| * Copyright (c) International Business Machines Corp., 2001 |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| * the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* |
| * Test Description: |
| * Verify that, |
| * 1) pwrite() fails when attempted to write to an unnamed pipe, |
| * returns ESPIPE. |
| * 2) pwrite() fails if the specified offset position was invalid, |
| * returns EINVAL. |
| * 3) pwrite() fails if fd is not a valid file descriptor, |
| * returns EBADF. |
| * 4) pwrite() fails if fd is not open for writing, return EBADF. |
| * 5) pwrite() fails when attempted to write with buf outside |
| * accessible address space, returns EFAULT. |
| */ |
| |
| #define _XOPEN_SOURCE 500 |
| |
| #include <errno.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| |
| #include "test.h" |
| #include "safe_macros.h" |
| |
| #define TEMPFILE "pwrite_file" |
| #define K1 1024 |
| |
| TCID_DEFINE(pwrite02); |
| |
| static char write_buf[K1]; |
| |
| static void setup(void); |
| static void cleanup(void); |
| |
| static void test_espipe(void); |
| static void test_einval(void); |
| static void test_ebadf1(void); |
| static void test_ebadf2(void); |
| |
| #if !defined(UCLINUX) |
| static void test_efault(void); |
| #endif |
| |
| static void (*testfunc[])(void) = { |
| test_espipe, test_einval, test_ebadf1, test_ebadf2, |
| #if !defined(UCLINUX) |
| test_efault |
| #endif |
| }; |
| |
| int TST_TOTAL = ARRAY_SIZE(testfunc); |
| |
| int main(int ac, char **av) |
| { |
| int i, lc; |
| const char *msg; |
| |
| if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) |
| tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
| |
| setup(); |
| |
| for (lc = 0; TEST_LOOPING(lc); lc++) { |
| tst_count = 0; |
| |
| for (i = 0; i < TST_TOTAL; i++) |
| (*testfunc[i])(); |
| } |
| |
| cleanup(); |
| tst_exit(); |
| } |
| |
| /* |
| * sighandler - handle SIGXFSZ |
| * |
| * This is here to start looking at a failure in test case #2. This |
| * test case passes on a machine running RedHat 6.2 but it will fail |
| * on a machine running RedHat 7.1. |
| */ |
| static void sighandler(int sig) |
| { |
| int ret; |
| |
| if (sig != SIGXFSZ) { |
| ret = write(STDOUT_FILENO, "get wrong signal\n", |
| sizeof("get wrong signal\n")); |
| } else { |
| ret = write(STDOUT_FILENO, "caught SIGXFSZ\n", |
| sizeof("caught SIGXFSZ\n")); |
| } |
| |
| (void)ret; |
| } |
| |
| static void setup(void) |
| { |
| tst_sig(NOFORK, DEF_HANDLER, cleanup); |
| |
| /* see the comment in the sighandler() function */ |
| /* call signal() to trap the signal generated */ |
| if (signal(SIGXFSZ, sighandler) == SIG_ERR) |
| tst_brkm(TBROK, cleanup, "signal() failed"); |
| |
| TEST_PAUSE; |
| |
| tst_tmpdir(); |
| |
| memset(write_buf, 'a', K1); |
| } |
| |
| static void print_test_result(int err, int exp_errno) |
| { |
| if (err == 0) { |
| tst_resm(TFAIL, "call succeeded unexpectedly"); |
| return; |
| } |
| |
| if (err == exp_errno) { |
| tst_resm(TPASS, "pwrite failed as expected: %d - %s", |
| err, strerror(err)); |
| } else { |
| tst_resm(TFAIL, "pwrite failed unexpectedly; expected: %d - %s" |
| "return: %d - %s", exp_errno, strerror(exp_errno), |
| err, strerror(err)); |
| } |
| } |
| |
| static void test_espipe(void) |
| { |
| int pipe_fds[2]; |
| |
| SAFE_PIPE(cleanup, pipe_fds); |
| |
| TEST(pwrite(pipe_fds[1], write_buf, K1, 0)); |
| |
| print_test_result(errno, ESPIPE); |
| |
| SAFE_CLOSE(cleanup, pipe_fds[0]); |
| SAFE_CLOSE(cleanup, pipe_fds[1]); |
| } |
| |
| static void test_einval(void) |
| { |
| int fd; |
| |
| fd = SAFE_OPEN(cleanup, TEMPFILE, O_RDWR | O_CREAT, 0666); |
| |
| /* the specified offset was invalid */ |
| TEST(pwrite(fd, write_buf, K1, -1)); |
| |
| print_test_result(errno, EINVAL); |
| |
| SAFE_CLOSE(cleanup, fd); |
| } |
| |
| static void test_ebadf1(void) |
| { |
| int fd = -1; |
| |
| TEST(pwrite(fd, write_buf, K1, 0)); |
| |
| print_test_result(errno, EBADF); |
| } |
| |
| static void test_ebadf2(void) |
| { |
| int fd; |
| |
| fd = SAFE_OPEN(cleanup, TEMPFILE, O_RDONLY | O_CREAT, 0666); |
| |
| TEST(pwrite(fd, write_buf, K1, 0)); |
| |
| print_test_result(errno, EBADF); |
| |
| SAFE_CLOSE(cleanup, fd); |
| } |
| |
| #if !defined(UCLINUX) |
| static void test_efault(void) |
| { |
| int fd; |
| char *buf = sbrk(0); |
| |
| fd = SAFE_OPEN(cleanup, TEMPFILE, O_RDWR | O_CREAT, 0666); |
| |
| TEST(pwrite(fd, buf, K1, 0)); |
| |
| print_test_result(errno, EFAULT); |
| |
| SAFE_CLOSE(cleanup, fd); |
| } |
| #endif |
| |
| static void cleanup(void) |
| { |
| tst_rmdir(); |
| } |