blob: 95ba7a6486d2ba6a2687b0cd9835becd9f5b7e65 [file] [log] [blame]
/*
*
* 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;
const char *msg;
struct stat buf;
int fail;
int cnt;
char wbuf[17 * PIPE_SIZE_TEST];
struct sigaction sigptr; /* set up signal handler */
if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL) {
tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
}
/* 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();
}