LCOV - GNU Libidn - gltests/test-dup2.c

LCOV - code coverage report
Current view: top level - gltests - test-dup2.c (source / functions) Hit Total Coverage
Test: GNU Libidn Lines: 93 93 100.0 %
Date: 2020年07月22日 17:53:13 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

 Line data Source code
 1  : /* Test duplicating file descriptors.
 2  : Copyright (C) 2009-2020 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 <https://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 __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  : # if GNULIB_MSVC_NOTHROW
 45  : # include "msvc-nothrow.h"
 46  : # else
 47  : # include <io.h>
 48  : # endif
 49  : #endif
 50  : 
 51  : #include "macros.h"
 52  : 
 53  : /* Return non-zero if FD is open. */
 54  : static int
 55  10 : is_open (int fd)
 56  : {
 57  : #if defined _WIN32 && ! defined __CYGWIN__
 58  : /* On native Windows, the initial state of unassigned standard file
 59  : descriptors is that they are open but point to an
 60  : INVALID_HANDLE_VALUE, and there is no fcntl. */
 61  : return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
 62  : #else
 63  : # ifndef F_GETFL
 64  : # error Please port fcntl to your platform
 65  : # endif
 66  10 : return 0 <= fcntl (fd, F_GETFL);
 67  : #endif
 68  : }
 69  : 
 70  : #if GNULIB_TEST_CLOEXEC
 71  : /* Return non-zero if FD is open and inheritable across exec/spawn. */
 72  : static int
 73  5 : is_inheritable (int fd)
 74  : {
 75  : # if defined _WIN32 && ! defined __CYGWIN__
 76  : /* On native Windows, the initial state of unassigned standard file
 77  : descriptors is that they are open but point to an
 78  : INVALID_HANDLE_VALUE, and there is no fcntl. */
 79  : HANDLE h = (HANDLE) _get_osfhandle (fd);
 80  : DWORD flags;
 81  : if (h == INVALID_HANDLE_VALUE || GetHandleInformation (h, &flags) == 0)
 82  : return 0;
 83  : return (flags & HANDLE_FLAG_INHERIT) != 0;
 84  : # else
 85  : # ifndef F_GETFD
 86  : # error Please port fcntl to your platform
 87  : # endif
 88  5 : int i = fcntl (fd, F_GETFD);
 89  5 : return 0 <= i && (i & FD_CLOEXEC) == 0;
 90  : # endif
 91  : }
 92  : #endif /* GNULIB_TEST_CLOEXEC */
 93  : 
 94  : #if !O_BINARY
 95  : # define setmode(f,m) zero ()
 96  10 : static int zero (void) { return 0; }
 97  : #endif
 98  : 
 99  : /* Return non-zero if FD is open in the given MODE, which is either
 100  : O_TEXT or O_BINARY. */
 101  : static int
 102  4 : is_mode (int fd, int mode)
 103  : {
 104  4 : int value = setmode (fd, O_BINARY);
 105  4 : setmode (fd, value);
 106  4 : return mode == value;
 107  : }
 108  : 
 109  : int
 110  1 : main (void)
 111  : {
 112  1 : const char *file = "test-dup2.tmp";
 113  : char buffer[1];
 114  1 : int bad_fd = getdtablesize ();
 115  1 : int fd = open (file, O_CREAT | O_TRUNC | O_RDWR, 0600);
 116  : 
 117  : /* Assume std descriptors were provided by invoker. */
 118  1 : ASSERT (STDERR_FILENO < fd);
 119  1 : ASSERT (is_open (fd));
 120  : /* Ignore any other fd's leaked into this process. */
 121  1 : close (fd + 1);
 122  1 : close (fd + 2);
 123  1 : ASSERT (!is_open (fd + 1));
 124  1 : ASSERT (!is_open (fd + 2));
 125  : 
 126  : /* Assigning to self must be a no-op. */
 127  1 : ASSERT (dup2 (fd, fd) == fd);
 128  1 : ASSERT (is_open (fd));
 129  : 
 130  : /* The source must be valid. */
 131  1 : errno = 0;
 132  1 : ASSERT (dup2 (-1, fd) == -1);
 133  1 : ASSERT (errno == EBADF);
 134  1 : close (99);
 135  1 : errno = 0;
 136  1 : ASSERT (dup2 (99, fd) == -1);
 137  1 : ASSERT (errno == EBADF);
 138  1 : errno = 0;
 139  1 : ASSERT (dup2 (AT_FDCWD, fd) == -1);
 140  1 : ASSERT (errno == EBADF);
 141  1 : ASSERT (is_open (fd));
 142  : 
 143  : /* If the source is not open, then the destination is unaffected. */
 144  1 : errno = 0;
 145  1 : ASSERT (dup2 (fd + 1, fd + 1) == -1);
 146  1 : ASSERT (errno == EBADF);
 147  1 : ASSERT (!is_open (fd + 1));
 148  1 : errno = 0;
 149  1 : ASSERT (dup2 (fd + 1, fd) == -1);
 150  1 : ASSERT (errno == EBADF);
 151  1 : ASSERT (is_open (fd));
 152  : 
 153  : /* The destination must be valid. */
 154  1 : errno = 0;
 155  1 : ASSERT (dup2 (fd, -2) == -1);
 156  1 : ASSERT (errno == EBADF);
 157  1 : if (bad_fd > 256)
 158  : {
 159  1 : ASSERT (dup2 (fd, 255) == 255);
 160  1 : ASSERT (dup2 (fd, 256) == 256);
 161  1 : ASSERT (close (255) == 0);
 162  1 : ASSERT (close (256) == 0);
 163  : }
 164  1 : ASSERT (dup2 (fd, bad_fd - 1) == bad_fd - 1);
 165  1 : ASSERT (close (bad_fd - 1) == 0);
 166  1 : errno = 0;
 167  1 : ASSERT (dup2 (fd, bad_fd) == -1);
 168  1 : ASSERT (errno == EBADF);
 169  : 
 170  : /* Using dup2 can skip fds. */
 171  1 : ASSERT (dup2 (fd, fd + 2) == fd + 2);
 172  1 : ASSERT (is_open (fd));
 173  1 : ASSERT (!is_open (fd + 1));
 174  1 : ASSERT (is_open (fd + 2));
 175  : 
 176  : /* Verify that dup2 closes the previous occupant of a fd. */
 177  1 : ASSERT (open ("/dev/null", O_WRONLY, 0600) == fd + 1);
 178  1 : ASSERT (dup2 (fd + 1, fd) == fd);
 179  1 : ASSERT (close (fd + 1) == 0);
 180  1 : ASSERT (write (fd, "1", 1) == 1);
 181  1 : ASSERT (dup2 (fd + 2, fd) == fd);
 182  1 : ASSERT (lseek (fd, 0, SEEK_END) == 0);
 183  1 : ASSERT (write (fd + 2, "2", 1) == 1);
 184  1 : ASSERT (lseek (fd, 0, SEEK_SET) == 0);
 185  1 : ASSERT (read (fd, buffer, 1) == 1);
 186  1 : ASSERT (*buffer == '2');
 187  : 
 188  : #if GNULIB_TEST_CLOEXEC
 189  : /* Any new fd created by dup2 must not be cloexec. */
 190  1 : ASSERT (close (fd + 2) == 0);
 191  1 : ASSERT (dup_cloexec (fd) == fd + 1);
 192  1 : ASSERT (!is_inheritable (fd + 1));
 193  1 : ASSERT (dup2 (fd + 1, fd + 1) == fd + 1);
 194  1 : ASSERT (!is_inheritable (fd + 1));
 195  1 : ASSERT (dup2 (fd + 1, fd + 2) == fd + 2);
 196  1 : ASSERT (!is_inheritable (fd + 1));
 197  1 : ASSERT (is_inheritable (fd + 2));
 198  1 : errno = 0;
 199  1 : ASSERT (dup2 (fd + 1, -1) == -1);
 200  1 : ASSERT (errno == EBADF);
 201  1 : ASSERT (!is_inheritable (fd + 1));
 202  : #endif
 203  : 
 204  : /* On systems that distinguish between text and binary mode, dup2
 205  : reuses the mode of the source. */
 206  1 : setmode (fd, O_BINARY);
 207  1 : ASSERT (is_mode (fd, O_BINARY));
 208  1 : ASSERT (dup2 (fd, fd + 1) == fd + 1);
 209  1 : ASSERT (is_mode (fd + 1, O_BINARY));
 210  1 : setmode (fd, O_TEXT);
 211  1 : ASSERT (is_mode (fd, O_TEXT));
 212  1 : ASSERT (dup2 (fd, fd + 1) == fd + 1);
 213  1 : ASSERT (is_mode (fd + 1, O_TEXT));
 214  : 
 215  : /* Clean up. */
 216  1 : ASSERT (close (fd + 2) == 0);
 217  1 : ASSERT (close (fd + 1) == 0);
 218  1 : ASSERT (close (fd) == 0);
 219  1 : ASSERT (unlink (file) == 0);
 220  : 
 221  1 : return 0;
 222  : }

Generated by: LCOV version 1.13

AltStyle によって変換されたページ (->オリジナル) /