1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 07/2001 Ported by John George 5 * 04/2002 wjhuie sigset cleanups 6 * 08/2007 Ricardo Salveti de Araujo <rsalveti (at) linux.vnet.ibm.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 16 * the GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23 /* 24 * DESCRIPTION 25 * Check the return value, and errnos of write(2) 26 * - when the file descriptor is invalid - EBADF 27 * - when the buf parameter is invalid - EFAULT 28 * - on an attempt to write to a pipe that is not open for reading - EPIPE 29 */ 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <fcntl.h> 33 #include <errno.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <sys/wait.h> 37 #include <sys/mman.h> 38 #include "tst_test.h" 39 40 static int fd; 41 static int inv_fd = -1; 42 static char b[32]; 43 static char *buf = b; 44 static char *bad_addr; 45 static int pipefd[2]; 46 47 static struct tcase { 48 int *fd; 49 char **buf; 50 size_t size; 51 int exp_errno; 52 } tcases[] = { 53 {&inv_fd, &buf, sizeof(buf), EBADF}, 54 {&fd, &bad_addr, sizeof(buf), EFAULT}, 55 {&pipefd[1], &buf, sizeof(buf), EPIPE}, 56 }; 57 58 static int sigpipe_cnt; 59 60 static void sighandler(int sig) 61 { 62 if (sig == SIGPIPE) 63 sigpipe_cnt++; 64 } 65 66 static void verify_write(unsigned int i) 67 { 68 struct tcase *tc = &tcases[i]; 69 70 sigpipe_cnt = 0; 71 72 TEST(write(*tc->fd, *tc->buf, tc->size)); 73 74 if (TST_RET != -1) { 75 tst_res(TFAIL, "write() succeeded unexpectedly"); 76 return; 77 } 78 79 if (TST_ERR != tc->exp_errno) { 80 tst_res(TFAIL | TTERRNO, 81 "write() failed unexpectedly, expected %s", 82 tst_strerrno(tc->exp_errno)); 83 return; 84 } 85 86 if (tc->exp_errno == EPIPE && sigpipe_cnt != 1) { 87 tst_res(TFAIL, "sigpipe_cnt = %i", sigpipe_cnt); 88 return; 89 } 90 91 tst_res(TPASS | TTERRNO, "write() failed expectedly"); 92 } 93 94 static void setup(void) 95 { 96 fd = SAFE_OPEN("write_test", O_RDWR | O_CREAT, 0644); 97 98 bad_addr = SAFE_MMAP(0, 1, PROT_NONE, 99 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 100 101 SAFE_PIPE(pipefd); 102 SAFE_CLOSE(pipefd[0]); 103 104 SAFE_SIGNAL(SIGPIPE, sighandler); 105 } 106 107 static void cleanup(void) 108 { 109 if (fd > 0) 110 SAFE_CLOSE(fd); 111 112 SAFE_MUNMAP(bad_addr, 1); 113 } 114 115 static struct tst_test test = { 116 .needs_tmpdir = 1, 117 .setup = setup, 118 .cleanup = cleanup, 119 .test = verify_write, 120 .tcnt = ARRAY_SIZE(tcases), 121 }; 122