/* * * 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 */ /* * NAME * write04.c * * DESCRIPTION * Testcase to check that write() sets errno to EAGAIN * * ALGORITHM * Create a named pipe (fifo), open it in O_NONBLOCK mode, and * attempt to write to it when it is full, write(2) should fail * with EAGAIN. * * USAGE: <for command-line> * write04 [-c n] [-e] [-i n] [-I x] [-P x] [-t] * where, -c n : Run n copies concurrently. * -e : Turn on errno logging. * -i n : Execute test n times. * -I x : Execute test for x seconds. * -P x : Pause for x seconds between iterations. * -t : Turn on syscall timing. * * HISTORY * ??/???? someone made this testcase but didn't add HISTORY * * RESTRICTIONS * NONE */ #include <sys/stat.h> #include <fcntl.h> #include <signal.h> #include <setjmp.h> #include <errno.h> #include <string.h> #include "test.h" #define PIPE_SIZE_TEST getpagesize() void alarm_handler(); void setup(); void cleanup(); char *TCID = "write04"; int TST_TOTAL = 1; char fifo[100] = "fifo"; static sigjmp_buf jmp; int rfd, wfd; int main(int argc, char **argv) { int lc; struct stat buf; int fail; int cnt; char wbuf[17 * PIPE_SIZE_TEST]; struct sigaction sigptr; /* set up signal handler */ tst_parse_opts(argc, argv, NULL, NULL); /* global setup */ setup(); /* * The following loop checks looping state if -i option given */ for (lc = 0; TEST_LOOPING(lc); lc++) { /* reset tst_count in case we are looping */ tst_count = 0; if (mknod(fifo, S_IFIFO | 0777, 0) < 0) { tst_resm(TBROK, "mknod() failed, errno: %d", errno); cleanup(); } if (stat(fifo, &buf) != 0) { tst_resm(TBROK, "stat() failed, errno: %d", errno); cleanup(); } if ((buf.st_mode & S_IFIFO) == 0) { tst_resm(TBROK, "Mode does not indicate fifo file"); cleanup(); } #if 0 sigset(SIGALRM, alarm_handler); #endif sigptr.sa_handler = (void (*)(int signal))alarm_handler; sigfillset(&sigptr.sa_mask); sigptr.sa_flags = 0; sigaddset(&sigptr.sa_mask, SIGALRM); if (sigaction(SIGALRM, &sigptr, NULL) == -1) { tst_resm(TBROK, "sigaction(): Failed"); cleanup(); } //block1: tst_resm(TINFO, "Enter block 1: test for EAGAIN in write()"); fail = 0; (void)memset((void *)wbuf, 'A', 17 * PIPE_SIZE_TEST); /* * open the read end of the pipe */ if (sigsetjmp(jmp, 1)) { tst_resm(TBROK, "Error reading fifo, read blocked"); fail = 1; } (void)alarm(10); /* set alarm for 10 seconds */ rfd = open(fifo, O_RDONLY | O_NONBLOCK); (void)alarm(0); if (rfd < 0) { tst_resm(TBROK, "open() for reading the pipe failed"); fail = 1; } /* * open the write end of the pipe */ if (sigsetjmp(jmp, 1)) { tst_resm(TBROK, "setjmp() failed"); cleanup(); } (void)alarm(10); /* set alarm for 10 seconds */ wfd = open(fifo, O_WRONLY | O_NONBLOCK); (void)alarm(0); if (wfd < 0) { tst_resm(TBROK, "open() for writing the pipe failed"); fail = 1; } /* * attempt to fill the pipe with some data */ if (sigsetjmp(jmp, 1)) { tst_resm(TBROK, "sigsetjmp() failed"); fail = 1; } (void)alarm(10); cnt = write(wfd, wbuf, 17 * PIPE_SIZE_TEST); (void)alarm(0); if (cnt == 17 * PIPE_SIZE_TEST) { tst_resm(TBROK, "Error reading fifo, nozero read"); fail = 1; } /* * Now that the fifo is full try and send some more */ if (sigsetjmp(jmp, 1)) { tst_resm(TBROK, "sigsetjmp() failed"); fail = 1; } (void)alarm(10); cnt = write(wfd, wbuf, 8 * PIPE_SIZE_TEST); (void)alarm(0); if (cnt != -1) { tst_resm(TBROK, "write() failed to fail when pipe " "is full"); fail = 1; } else { if (errno != EAGAIN) { tst_resm(TBROK, "write set bad errno, expected " "EAGAIN, got %d", errno); fail = 1; } tst_resm(TINFO, "read() succeded in setting errno to " "EAGAIN"); } if (fail) { tst_resm(TFAIL, "Block 1 FAILED"); } else { tst_resm(TPASS, "Block 1 PASSED"); } tst_resm(TINFO, "Exit block 1"); /* unlink fifo in case we are looping. */ unlink(fifo); } cleanup(); tst_exit(); } void alarm_handler(void) { siglongjmp(jmp, 1); } /* * setup() * performs all ONE TIME setup for this test */ void setup(void) { tst_sig(FORK, DEF_HANDLER, cleanup); /* Pause if that option was specified * TEST_PAUSE contains the code to fork the test with the -i option. * You want to make sure you do this before you create your temporary * directory. */ TEST_PAUSE; /* Create a unique temporary directory and chdir() to it. */ tst_tmpdir(); /* create a temporary filename */ sprintf(fifo, "%s.%d", fifo, getpid()); } void cleanup(void) { close(rfd); close(wfd); unlink(fifo); tst_rmdir(); }