LCOV - code coverage report
Current view: top level - gltests - test-dup2.c (source / functions) Hit Total Coverage
Test: GNU Libidn Lines: 78 78 100.0 %
Date: 2015-07-08 23:12:53 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Test duplicating file descriptors.
       2             :    Copyright (C) 2009-2015 Free Software Foundation, Inc.
       3             : 
       4             :    This program is free software: you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation; either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    This program is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public License
      15             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      16             : 
      17             : /* Written by Eric Blake <ebb9@byu.net>, 2009.  */
      18             : 
      19             : #include <config.h>
      20             : 
      21             : #include <unistd.h>
      22             : 
      23             : #include "signature.h"
      24             : SIGNATURE_CHECK (dup2, int, (int, int));
      25             : 
      26             : #include <errno.h>
      27             : #include <fcntl.h>
      28             : 
      29             : #if HAVE_SYS_RESOURCE_H
      30             : # include <sys/resource.h>
      31             : #endif
      32             : 
      33             : #include "binary-io.h"
      34             : 
      35             : #if GNULIB_TEST_CLOEXEC
      36             : # include "cloexec.h"
      37             : #endif
      38             : 
      39             : #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
      40             : /* Get declarations of the native Windows API functions.  */
      41             : # define WIN32_LEAN_AND_MEAN
      42             : # include <windows.h>
      43             : /* Get _get_osfhandle.  */
      44             : # include "msvc-nothrow.h"
      45             : #endif
      46             : 
      47             : #include "macros.h"
      48             : 
      49             : /* Return non-zero if FD is open.  */
      50             : static int
      51          10 : is_open (int fd)
      52             : {
      53             : #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
      54             :   /* On native Windows, the initial state of unassigned standard file
      55             :      descriptors is that they are open but point to an
      56             :      INVALID_HANDLE_VALUE, and there is no fcntl.  */
      57             :   return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
      58             : #else
      59             : # ifndef F_GETFL
      60             : #  error Please port fcntl to your platform
      61             : # endif
      62          10 :   return 0 <= fcntl (fd, F_GETFL);
      63             : #endif
      64             : }
      65             : 
      66             : #if GNULIB_TEST_CLOEXEC
      67             : /* Return non-zero if FD is open and inheritable across exec/spawn.  */
      68             : static int
      69             : is_inheritable (int fd)
      70             : {
      71             : # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
      72             :   /* On native Windows, the initial state of unassigned standard file
      73             :      descriptors is that they are open but point to an
      74             :      INVALID_HANDLE_VALUE, and there is no fcntl.  */
      75             :   HANDLE h = (HANDLE) _get_osfhandle (fd);
      76             :   DWORD flags;
      77             :   if (h == INVALID_HANDLE_VALUE || GetHandleInformation (h, &flags) == 0)
      78             :     return 0;
      79             :   return (flags & HANDLE_FLAG_INHERIT) != 0;
      80             : # else
      81             : #  ifndef F_GETFD
      82             : #   error Please port fcntl to your platform
      83             : #  endif
      84             :   int i = fcntl (fd, F_GETFD);
      85             :   return 0 <= i && (i & FD_CLOEXEC) == 0;
      86             : # endif
      87             : }
      88             : #endif /* GNULIB_TEST_CLOEXEC */
      89             : 
      90             : #if !O_BINARY
      91             : # define setmode(f,m) zero ()
      92          10 : static int zero (void) { return 0; }
      93             : #endif
      94             : 
      95             : /* Return non-zero if FD is open in the given MODE, which is either
      96             :    O_TEXT or O_BINARY.  */
      97             : static int
      98           4 : is_mode (int fd, int mode)
      99             : {
     100           4 :   int value = setmode (fd, O_BINARY);
     101           4 :   setmode (fd, value);
     102           4 :   return mode == value;
     103             : }
     104             : 
     105             : int
     106           1 : main (void)
     107             : {
     108           1 :   const char *file = "test-dup2.tmp";
     109             :   char buffer[1];
     110           1 :   int bad_fd = getdtablesize ();
     111           1 :   int fd = open (file, O_CREAT | O_TRUNC | O_RDWR, 0600);
     112             : 
     113             :   /* Assume std descriptors were provided by invoker.  */
     114           1 :   ASSERT (STDERR_FILENO < fd);
     115           1 :   ASSERT (is_open (fd));
     116             :   /* Ignore any other fd's leaked into this process.  */
     117           1 :   close (fd + 1);
     118           1 :   close (fd + 2);
     119           1 :   ASSERT (!is_open (fd + 1));
     120           1 :   ASSERT (!is_open (fd + 2));
     121             : 
     122             :   /* Assigning to self must be a no-op.  */
     123           1 :   ASSERT (dup2 (fd, fd) == fd);
     124           1 :   ASSERT (is_open (fd));
     125             : 
     126             :   /* The source must be valid.  */
     127           1 :   errno = 0;
     128           1 :   ASSERT (dup2 (-1, fd) == -1);
     129           1 :   ASSERT (errno == EBADF);
     130           1 :   close (99);
     131           1 :   errno = 0;
     132           1 :   ASSERT (dup2 (99, fd) == -1);
     133           1 :   ASSERT (errno == EBADF);
     134           1 :   errno = 0;
     135           1 :   ASSERT (dup2 (AT_FDCWD, fd) == -1);
     136           1 :   ASSERT (errno == EBADF);
     137           1 :   ASSERT (is_open (fd));
     138             : 
     139             :   /* If the source is not open, then the destination is unaffected.  */
     140           1 :   errno = 0;
     141           1 :   ASSERT (dup2 (fd + 1, fd + 1) == -1);
     142           1 :   ASSERT (errno == EBADF);
     143           1 :   ASSERT (!is_open (fd + 1));
     144           1 :   errno = 0;
     145           1 :   ASSERT (dup2 (fd + 1, fd) == -1);
     146           1 :   ASSERT (errno == EBADF);
     147           1 :   ASSERT (is_open (fd));
     148             : 
     149             :   /* The destination must be valid.  */
     150           1 :   errno = 0;
     151           1 :   ASSERT (dup2 (fd, -2) == -1);
     152           1 :   ASSERT (errno == EBADF);
     153           1 :   if (bad_fd > 256)
     154             :     {
     155           1 :       ASSERT (dup2 (fd, 255) == 255);
     156           1 :       ASSERT (dup2 (fd, 256) == 256);
     157           1 :       ASSERT (close (255) == 0);
     158           1 :       ASSERT (close (256) == 0);
     159             :     }
     160           1 :   ASSERT (dup2 (fd, bad_fd - 1) == bad_fd - 1);
     161           1 :   ASSERT (close (bad_fd - 1) == 0);
     162           1 :   errno = 0;
     163           1 :   ASSERT (dup2 (fd, bad_fd) == -1);
     164           1 :   ASSERT (errno == EBADF);
     165             : 
     166             :   /* Using dup2 can skip fds.  */
     167           1 :   ASSERT (dup2 (fd, fd + 2) == fd + 2);
     168           1 :   ASSERT (is_open (fd));
     169           1 :   ASSERT (!is_open (fd + 1));
     170           1 :   ASSERT (is_open (fd + 2));
     171             : 
     172             :   /* Verify that dup2 closes the previous occupant of a fd.  */
     173           1 :   ASSERT (open ("/dev/null", O_WRONLY, 0600) == fd + 1);
     174           1 :   ASSERT (dup2 (fd + 1, fd) == fd);
     175           1 :   ASSERT (close (fd + 1) == 0);
     176           1 :   ASSERT (write (fd, "1", 1) == 1);
     177           1 :   ASSERT (dup2 (fd + 2, fd) == fd);
     178           1 :   ASSERT (lseek (fd, 0, SEEK_END) == 0);
     179           1 :   ASSERT (write (fd + 2, "2", 1) == 1);
     180           1 :   ASSERT (lseek (fd, 0, SEEK_SET) == 0);
     181           1 :   ASSERT (read (fd, buffer, 1) == 1);
     182           1 :   ASSERT (*buffer == '2');
     183             : 
     184             : #if GNULIB_TEST_CLOEXEC
     185             :   /* Any new fd created by dup2 must not be cloexec.  */
     186             :   ASSERT (close (fd + 2) == 0);
     187             :   ASSERT (dup_cloexec (fd) == fd + 1);
     188             :   ASSERT (!is_inheritable (fd + 1));
     189             :   ASSERT (dup2 (fd + 1, fd + 1) == fd + 1);
     190             :   ASSERT (!is_inheritable (fd + 1));
     191             :   ASSERT (dup2 (fd + 1, fd + 2) == fd + 2);
     192             :   ASSERT (!is_inheritable (fd + 1));
     193             :   ASSERT (is_inheritable (fd + 2));
     194             :   errno = 0;
     195             :   ASSERT (dup2 (fd + 1, -1) == -1);
     196             :   ASSERT (errno == EBADF);
     197             :   ASSERT (!is_inheritable (fd + 1));
     198             : #endif
     199             : 
     200             :   /* On systems that distinguish between text and binary mode, dup2
     201             :      reuses the mode of the source.  */
     202           1 :   setmode (fd, O_BINARY);
     203           1 :   ASSERT (is_mode (fd, O_BINARY));
     204           1 :   ASSERT (dup2 (fd, fd + 1) == fd + 1);
     205           1 :   ASSERT (is_mode (fd + 1, O_BINARY));
     206           1 :   setmode (fd, O_TEXT);
     207           1 :   ASSERT (is_mode (fd, O_TEXT));
     208           1 :   ASSERT (dup2 (fd, fd + 1) == fd + 1);
     209           1 :   ASSERT (is_mode (fd + 1, O_TEXT));
     210             : 
     211             :   /* Clean up.  */
     212           1 :   ASSERT (close (fd + 2) == 0);
     213           1 :   ASSERT (close (fd + 1) == 0);
     214           1 :   ASSERT (close (fd) == 0);
     215           1 :   ASSERT (unlink (file) == 0);
     216             : 
     217           1 :   return 0;
     218             : }

Generated by: LCOV version 1.11