From b80176069521ff306b2b81ef0a9abfa8d741ada7 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 21 Jul 2009 06:48:56 -0600 Subject: [PATCH] dup2-tests: test previous patch * modules/dup2-tests: New file. * tests/test-dup2.c: Likewise. * tests/test-open.c (main): Avoid unspecified behavior. * tests/test-pipe.c (child_main): Use dup2 semantics to simplify test. Signed-off-by: Eric Blake --- ChangeLog | 7 ++++ modules/dup2-tests | 12 ++++++ tests/test-dup2.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/test-open.c | 4 +- tests/test-pipe.c | 47 +++++---------------- 5 files changed, 147 insertions(+), 40 deletions(-) create mode 100644 modules/dup2-tests create mode 100644 tests/test-dup2.c diff --git a/ChangeLog b/ChangeLog index d87cc8e6d..6a89b40aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-07-21 Eric Blake + dup2-tests: test previous patch + * modules/dup2-tests: New file. + * tests/test-dup2.c: Likewise. + * tests/test-open.c (main): Avoid unspecified behavior. + * tests/test-pipe.c (child_main): Use dup2 semantics to simplify + test. + dup2: work around mingw and cygwin 1.5 bug * m4/dup2.m4 (gl_FUNC_DUP2): Detect mingw bug. * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Add witness. diff --git a/modules/dup2-tests b/modules/dup2-tests new file mode 100644 index 000000000..9b1e7db40 --- /dev/null +++ b/modules/dup2-tests @@ -0,0 +1,12 @@ +Files: +tests/test-dup2.c + +Depends-on: +close +open + +configure.ac: + +Makefile.am: +TESTS += test-dup2 +check_PROGRAMS += test-dup2 diff --git a/tests/test-dup2.c b/tests/test-dup2.c new file mode 100644 index 000000000..67f49eff0 --- /dev/null +++ b/tests/test-dup2.c @@ -0,0 +1,117 @@ +/* Test duplicating file descriptors. + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 3 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, see . */ + +/* Written by Eric Blake , 2009. */ + +#include + +#include + +#include +#include +#include +#include + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the Win32 API functions. */ +# define WIN32_LEAN_AND_MEAN +# include +#endif + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + +/* Return non-zero if FD is open. */ +static int +is_open (int fd) +{ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* On Win32, the initial state of unassigned standard file + descriptors is that they are open but point to an + INVALID_HANDLE_VALUE, and there is no fcntl. */ + return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; +#else +# ifndef F_GETFL +# error Please port fcntl to your platform +# endif + return 0 <= fcntl (fd, F_GETFL); +#endif +} + +int +main () +{ + const char *file = "test-dup2.tmp"; + char buffer[1]; + int fd = open (file, O_CREAT | O_RDWR, 0600); + + ASSERT (0 <= fd); + ASSERT (is_open (fd)); + ASSERT (!is_open (fd + 1)); + ASSERT (!is_open (fd + 2)); + + /* Assigning to self must be a no-op. */ + ASSERT (dup2 (fd, fd) == fd); + ASSERT (is_open (fd)); + + /* If the source is not open, then the destination is unaffected. */ + errno = 0; + ASSERT (dup2 (fd + 1, fd + 1) == -1); + ASSERT (errno == EBADF); + ASSERT (!is_open (fd + 1)); + errno = 0; + ASSERT (dup2 (fd + 1, fd) == -1); + ASSERT (errno == EBADF); + ASSERT (is_open (fd)); + + /* The destination must be valid. */ + errno = 0; + ASSERT (dup2 (fd, -2) == -1); + ASSERT (errno == EBADF); + + /* Using dup2 can skip fds. */ + ASSERT (dup2 (fd, fd + 2) == fd + 2); + ASSERT (is_open (fd)); + ASSERT (!is_open (fd + 1)); + ASSERT (is_open (fd + 2)); + + /* Prove that dup2 closes the previous occupant of a fd. */ + ASSERT (open ("/dev/null", O_WRONLY, 0600) == fd + 1); + ASSERT (dup2 (fd + 1, fd) == fd); + ASSERT (close (fd + 1) == 0); + ASSERT (write (fd, "1", 1) == 1); + ASSERT (dup2 (fd + 2, fd) == fd); + ASSERT (write (fd + 2, "2", 1) == 1); + ASSERT (lseek (fd, SEEK_SET, 0) == 0); + ASSERT (read (fd, buffer, 1) == 1); + ASSERT (*buffer == '2'); + + /* Clean up. */ + ASSERT (close (fd + 2) == 0); + ASSERT (close (fd) == 0); + ASSERT (unlink (file) == 0); + + return 0; +} diff --git a/tests/test-open.c b/tests/test-open.c index 0eb8a3309..f7bb54360 100644 --- a/tests/test-open.c +++ b/tests/test-open.c @@ -1,5 +1,5 @@ /* Test of opening a file descriptor. - Copyright (C) 2007-2008 Free Software Foundation, Inc. + Copyright (C) 2007-2009 Free Software Foundation, Inc. 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 @@ -38,7 +38,7 @@ int main () { - ASSERT (open ("nonexist.ent/", O_CREAT, 0600) < 0); + ASSERT (open ("nonexist.ent/", O_CREAT | O_RDONLY, 0600) < 0); ASSERT (open ("/dev/null/", O_RDONLY) < 0); ASSERT (open ("/dev/null", O_RDONLY) >= 0); diff --git a/tests/test-pipe.c b/tests/test-pipe.c index 16c72f603..404534da2 100644 --- a/tests/test-pipe.c +++ b/tests/test-pipe.c @@ -20,18 +20,12 @@ #include "pipe.h" #include "wait-process.h" -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Get declarations of the Win32 API functions. */ -# define WIN32_LEAN_AND_MEAN -# include -#endif - #include -#include #include #include #include #include +#include /* Depending on arguments, this test intentionally closes stderr or starts life with stderr closed. So, we arrange to have fd 10 @@ -59,6 +53,7 @@ child_main (int argc, char *argv[]) { char buffer[2] = { 's', 't' }; int fd; + int ret; ASSERT (argc == 3); @@ -71,46 +66,22 @@ child_main (int argc, char *argv[]) buffer[0]++; ASSERT (write (STDOUT_FILENO, buffer, 1) == 1); -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - /* On Win32, the initial state of unassigned standard file descriptors is - that they are open but point to an INVALID_HANDLE_VALUE. Thus - close (STDERR_FILENO) would always succeed. */ + errno = 0; + ret = dup2 (STDERR_FILENO, STDERR_FILENO); switch (atoi (argv[2])) { case 0: - /* Expect fd 2 is open to a valid handle. */ - ASSERT ((HANDLE) _get_osfhandle (STDERR_FILENO) != INVALID_HANDLE_VALUE); + /* Expect fd 2 is open. */ + ASSERT (ret == STDERR_FILENO); break; case 1: - /* Expect fd 2 is pointing to INVALID_HANDLE_VALUE. */ - ASSERT ((HANDLE) _get_osfhandle (STDERR_FILENO) == INVALID_HANDLE_VALUE); + /* Expect fd 2 is closed. */ + ASSERT (ret == -1); + ASSERT (errno == EBADF); break; default: ASSERT (false); } -#elif defined F_GETFL - /* On Unix, the initial state of unassigned standard file descriptors is - that they are closed. */ - { - int ret; - errno = 0; - ret = fcntl (STDERR_FILENO, F_GETFL); - switch (atoi (argv[2])) - { - case 0: - /* Expect fd 2 is open. */ - ASSERT (ret >= 0); - break; - case 1: - /* Expect fd 2 is closed. */ - ASSERT (ret < 0); - ASSERT (errno == EBADF); - break; - default: - ASSERT (false); - } - } -#endif for (fd = 3; fd < 7; fd++) { -- 2.11.0