2009-12-07 Eric Blake <ebb9@byu.net>
+ cloexec: preserve text vs. binary across dup_cloexec
+ * lib/cloexec.c (dup_cloexec) [W32]: Query and use translation
+ mode.
+ * modules/dup2-tests (Depends-on): Add binary-io.
+ * modules/cloexec-tests (Depends-on): Likewise.
+ * tests/test-dup2.c (setmode, is_mode): New helpers.
+ (main): Add tests that translation mode is preserved.
+ * tests/test-cloexec.c (setmode, is_mode, main): Likewise.
+ Reported by Bruno Haible.
+
mgetgroups: reduce duplicate listings
* lib/mgetgroups.c (mgetgroups): Reduce duplicates from the
resulting array.
#else
+ /* Use dup2 to reject invalid file descriptors; the cloexec flag
+ will be unaffected. */
if (desc < 0)
{
errno = EBADF;
HANDLE curr_process = GetCurrentProcess ();
HANDLE old_handle = (HANDLE) _get_osfhandle (fd);
HANDLE new_handle;
+ int mode;
- if (old_handle == INVALID_HANDLE_VALUE)
+ if (old_handle == INVALID_HANDLE_VALUE
+ || (mode = setmode (fd, O_BINARY)) == -1)
{
/* fd is closed, or is open to no handle at all.
We cannot duplicate fd in this case, because _open_osfhandle
errno = EBADF;
return -1;
}
+ setmode (fd, mode);
if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
old_handle, /* SourceHandle */
return -1;
}
- nfd = _open_osfhandle ((long) new_handle, O_BINARY | O_NOINHERIT);
+ nfd = _open_osfhandle ((long) new_handle, mode | O_NOINHERIT);
if (nfd < 0)
{
CloseHandle (new_handle);
tests/test-cloexec.c
Depends-on:
+binary-io
configure.ac:
tests/test-dup2.c
Depends-on:
+binary-io
cloexec
open
# include <windows.h>
#endif
+#include "binary-io.h"
+
#define ASSERT(expr) \
do \
{ \
#endif
}
+#if !O_BINARY
+# define setmode(f,m) 0
+#endif
+
+/* Return non-zero if FD is open in the given MODE, which is either
+ O_TEXT or O_BINARY. */
+static int
+is_mode (int fd, int mode)
+{
+ int value = setmode (fd, O_BINARY);
+ setmode (fd, value);
+ return mode == value;
+}
+
int
main (void)
{
ASSERT (!is_inheritable (fd));
ASSERT (close (fd2) == 0);
+ /* On systems that distinguish between text and binary mode,
+ dup_cloexec reuses the mode of the source. */
+ setmode (fd, O_BINARY);
+ ASSERT (is_mode (fd, O_BINARY));
+ fd2 = dup_cloexec (fd);
+ ASSERT (fd < fd2);
+ ASSERT (is_mode (fd2, O_BINARY));
+ ASSERT (close (fd2) == 0);
+ setmode (fd, O_TEXT);
+ ASSERT (is_mode (fd, O_TEXT));
+ fd2 = dup_cloexec (fd);
+ ASSERT (fd < fd2);
+ ASSERT (is_mode (fd2, O_TEXT));
+ ASSERT (close (fd2) == 0);
+
/* Test error handling. */
errno = 0;
ASSERT (set_cloexec_flag (-1, false) == -1);
#include <stdio.h>
#include <stdlib.h>
+#include "binary-io.h"
#include "cloexec.h"
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
#endif
}
+#if !O_BINARY
+# define setmode(f,m) 0
+#endif
+
+/* Return non-zero if FD is open in the given MODE, which is either
+ O_TEXT or O_BINARY. */
+static int
+is_mode (int fd, int mode)
+{
+ int value = setmode (fd, O_BINARY);
+ setmode (fd, value);
+ return mode == value;
+}
+
int
main (void)
{
ASSERT (dup2 (fd + 1, fd + 2) == fd + 2);
ASSERT (is_inheritable (fd + 2));
+ /* On systems that distinguish between text and binary mode, dup2
+ reuses the mode of the source. */
+ setmode (fd, O_BINARY);
+ ASSERT (is_mode (fd, O_BINARY));
+ ASSERT (dup2 (fd, fd + 1) == fd + 1);
+ ASSERT (is_mode (fd + 1, O_BINARY));
+ setmode (fd, O_TEXT);
+ ASSERT (is_mode (fd, O_TEXT));
+ ASSERT (dup2 (fd, fd + 1) == fd + 1);
+ ASSERT (is_mode (fd + 1, O_TEXT));
+
/* Clean up. */
ASSERT (close (fd + 2) == 0);
ASSERT (close (fd + 1) == 0);