Mercurial > gnulib
annotate tests/test-dup-safer.c @ 40196:e63f5d3edab5
relocatable-prog: Update documentation.
* doc/relocatable-maint.texi (Supporting Relocation): Update to match
the recent changes.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sun, 24 Feb 2019 01:49:15 +0100 |
parents | b06060465f09 |
children |
rev | line source |
---|---|
12399 | 1 /* Test that dup_safer leaves standard fds alone. |
40057
b06060465f09
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
19595
diff
changeset
|
2 Copyright (C) 2009-2019 Free Software Foundation, Inc. |
12399 | 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 | |
19190 | 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
12399 | 16 |
17 /* Written by Eric Blake <ebb9@byu.net>, 2009. */ | |
18 | |
19 #include <config.h> | |
20 | |
21 #include "unistd--.h" | |
22 | |
23 #include <fcntl.h> | |
24 #include <errno.h> | |
25 #include <stdbool.h> | |
26 #include <stdio.h> | |
17373
160b88fd4691
tests: don't assume getdtablesize () <= 10000000
Paul Eggert <eggert@cs.ucla.edu>
parents:
17249
diff
changeset
|
27 #include <unistd.h> |
12399 | 28 |
29 #include "binary-io.h" | |
30 #include "cloexec.h" | |
31 | |
19595
beb2ad957aca
Simplify code. Drop support for Borland C++ on Windows.
Bruno Haible <bruno@clisp.org>
parents:
19484
diff
changeset
|
32 #if defined _WIN32 && ! defined __CYGWIN__ |
16214
ec738d6aeef5
Talk about "native Windows API", not "Win32".
Bruno Haible <bruno@clisp.org>
parents:
16201
diff
changeset
|
33 /* Get declarations of the native Windows API functions. */ |
12399 | 34 # define WIN32_LEAN_AND_MEAN |
35 # include <windows.h> | |
15752
b86e9061a6d0
New module 'msvc-nothrow'. Makes _get_osfhandle safe on MSVC 9.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
36 /* Get _get_osfhandle. */ |
18883
19886582ca8d
Implement a way to opt out from MSVC support.
Bruno Haible <bruno@clisp.org>
parents:
18626
diff
changeset
|
37 # if GNULIB_MSVC_NOTHROW |
19886582ca8d
Implement a way to opt out from MSVC support.
Bruno Haible <bruno@clisp.org>
parents:
18626
diff
changeset
|
38 # include "msvc-nothrow.h" |
19886582ca8d
Implement a way to opt out from MSVC support.
Bruno Haible <bruno@clisp.org>
parents:
18626
diff
changeset
|
39 # else |
19886582ca8d
Implement a way to opt out from MSVC support.
Bruno Haible <bruno@clisp.org>
parents:
18626
diff
changeset
|
40 # include <io.h> |
19886582ca8d
Implement a way to opt out from MSVC support.
Bruno Haible <bruno@clisp.org>
parents:
18626
diff
changeset
|
41 # endif |
12399 | 42 #endif |
43 | |
44 #if !O_BINARY | |
45 # define setmode(f,m) zero () | |
46 static int zero (void) { return 0; } | |
47 #endif | |
48 | |
49 /* This test intentionally closes stderr. So, we arrange to have fd 10 | |
50 (outside the range of interesting fd's during the test) set up to | |
51 duplicate the original stderr. */ | |
52 | |
53 #define BACKUP_STDERR_FILENO 10 | |
12510
618282a72d9b
tests: use macros.h in more places
Eric Blake <ebb9@byu.net>
parents:
12399
diff
changeset
|
54 #define ASSERT_STREAM myerr |
618282a72d9b
tests: use macros.h in more places
Eric Blake <ebb9@byu.net>
parents:
12399
diff
changeset
|
55 #include "macros.h" |
12399 | 56 |
12510
618282a72d9b
tests: use macros.h in more places
Eric Blake <ebb9@byu.net>
parents:
12399
diff
changeset
|
57 static FILE *myerr; |
12399 | 58 |
59 /* Return true if FD is open. */ | |
60 static bool | |
61 is_open (int fd) | |
62 { | |
19595
beb2ad957aca
Simplify code. Drop support for Borland C++ on Windows.
Bruno Haible <bruno@clisp.org>
parents:
19484
diff
changeset
|
63 #if defined _WIN32 && ! defined __CYGWIN__ |
16214
ec738d6aeef5
Talk about "native Windows API", not "Win32".
Bruno Haible <bruno@clisp.org>
parents:
16201
diff
changeset
|
64 /* On native Windows, the initial state of unassigned standard file |
12399 | 65 descriptors is that they are open but point to an |
66 INVALID_HANDLE_VALUE, and there is no fcntl. */ | |
67 return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; | |
68 #else | |
69 # ifndef F_GETFL | |
70 # error Please port fcntl to your platform | |
71 # endif | |
72 return 0 <= fcntl (fd, F_GETFL); | |
73 #endif | |
74 } | |
75 | |
76 /* Return true if FD is open and inheritable across exec/spawn. */ | |
77 static bool | |
78 is_inheritable (int fd) | |
79 { | |
19595
beb2ad957aca
Simplify code. Drop support for Borland C++ on Windows.
Bruno Haible <bruno@clisp.org>
parents:
19484
diff
changeset
|
80 #if defined _WIN32 && ! defined __CYGWIN__ |
16214
ec738d6aeef5
Talk about "native Windows API", not "Win32".
Bruno Haible <bruno@clisp.org>
parents:
16201
diff
changeset
|
81 /* On native Windows, the initial state of unassigned standard file |
12399 | 82 descriptors is that they are open but point to an |
83 INVALID_HANDLE_VALUE, and there is no fcntl. */ | |
84 HANDLE h = (HANDLE) _get_osfhandle (fd); | |
85 DWORD flags; | |
86 if (h == INVALID_HANDLE_VALUE || GetHandleInformation (h, &flags) == 0) | |
87 return 0; | |
88 return (flags & HANDLE_FLAG_INHERIT) != 0; | |
89 #else | |
90 # ifndef F_GETFD | |
91 # error Please port fcntl to your platform | |
92 # endif | |
93 int i = fcntl (fd, F_GETFD); | |
94 return 0 <= i && (i & FD_CLOEXEC) == 0; | |
95 #endif | |
96 } | |
97 | |
98 /* Return true if FD is open in the given MODE, which is either | |
99 O_TEXT or O_BINARY. */ | |
100 static bool | |
101 is_mode (int fd, int mode) | |
102 { | |
103 int value = setmode (fd, O_BINARY); | |
104 setmode (fd, value); | |
105 return mode == value; | |
106 } | |
107 | |
108 #define witness "test-dup-safer.txt" | |
109 | |
110 int | |
111 main (void) | |
112 { | |
113 int i; | |
114 int fd; | |
17373
160b88fd4691
tests: don't assume getdtablesize () <= 10000000
Paul Eggert <eggert@cs.ucla.edu>
parents:
17249
diff
changeset
|
115 int bad_fd = getdtablesize (); |
12399 | 116 |
117 /* We close fd 2 later, so save it in fd 10. */ | |
118 if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO | |
119 || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL) | |
120 return 2; | |
121 | |
122 /* Create file for later checks. */ | |
123 fd = creat (witness, 0600); | |
124 ASSERT (STDERR_FILENO < fd); | |
125 | |
126 /* Four iterations, with progressively more standard descriptors | |
127 closed. */ | |
128 for (i = -1; i <= STDERR_FILENO; i++) | |
129 { | |
130 if (0 <= i) | |
131 ASSERT (close (i) == 0); | |
132 | |
133 /* Detect errors. */ | |
134 errno = 0; | |
135 ASSERT (dup (-1) == -1); | |
136 ASSERT (errno == EBADF); | |
137 errno = 0; | |
17373
160b88fd4691
tests: don't assume getdtablesize () <= 10000000
Paul Eggert <eggert@cs.ucla.edu>
parents:
17249
diff
changeset
|
138 ASSERT (dup (bad_fd) == -1); |
12399 | 139 ASSERT (errno == EBADF); |
140 close (fd + 1); | |
141 errno = 0; | |
142 ASSERT (dup (fd + 1) == -1); | |
143 ASSERT (errno == EBADF); | |
144 | |
145 /* Preserve text vs. binary. */ | |
146 setmode (fd, O_BINARY); | |
147 ASSERT (dup (fd) == fd + 1); | |
148 ASSERT (is_open (fd + 1)); | |
149 ASSERT (is_inheritable (fd + 1)); | |
150 ASSERT (is_mode (fd + 1, O_BINARY)); | |
151 | |
152 ASSERT (close (fd + 1) == 0); | |
153 setmode (fd, O_TEXT); | |
154 ASSERT (dup (fd) == fd + 1); | |
155 ASSERT (is_open (fd + 1)); | |
156 ASSERT (is_inheritable (fd + 1)); | |
157 ASSERT (is_mode (fd + 1, O_TEXT)); | |
158 | |
159 /* Create cloexec copy. */ | |
160 ASSERT (close (fd + 1) == 0); | |
161 ASSERT (fd_safer_flag (dup_cloexec (fd), O_CLOEXEC) == fd + 1); | |
162 ASSERT (set_cloexec_flag (fd + 1, true) == 0); | |
163 ASSERT (is_open (fd + 1)); | |
164 ASSERT (!is_inheritable (fd + 1)); | |
165 ASSERT (close (fd) == 0); | |
166 | |
167 /* dup always creates inheritable copies. Also, check that | |
168 earliest slot past std fds is used. */ | |
169 ASSERT (dup (fd + 1) == fd); | |
170 ASSERT (is_open (fd)); | |
171 ASSERT (is_inheritable (fd)); | |
172 ASSERT (close (fd + 1) == 0); | |
173 } | |
174 | |
175 /* Cleanup. */ | |
176 ASSERT (close (fd) == 0); | |
177 ASSERT (unlink (witness) == 0); | |
178 | |
179 return 0; | |
180 } |