summaryrefslogtreecommitdiff
path: root/lib/dup2.c
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2009-08-31 14:20:03 -0600
committerEric Blake <ebb9@byu.net>2009-09-02 19:14:43 -0600
commit4475e25b6a19e31e5783781f2132cdbd05bcf7c4 (patch)
tree8e8a8793c084d0e534a75896602a77b0218fa079 /lib/dup2.c
parent5578788cdb078c97988eb445c2bd848081679e4c (diff)
downloadgnulib-4475e25b6a19e31e5783781f2132cdbd05bcf7c4.tar.gz
fchdir: simplify error handling, and support dup3
* modules/fchdir (Depends-on): Use strdup-posix, not strdup. Add stdbool, malloc-posix, realloc-posix. * lib/fchdir.c (struct dir_info_t): Delete saved_errno. (ensure_dirs_slot): Return false on allocation failure. (rpl_dup2): Delete. (_gl_register_dup): New function. (_gl_unregister_fd, rpl_opendir, rpl_dup): Update callers. (_gl_register_fd): Close fd on allocation failure. * lib/fcntl.in.h (_gl_register_fd): Update signature. * lib/unistd.in.h (_gl_register_dup) [FCHDIR_REPLACEMENT]: New prototype. (rpl_dup2_fchdir): Delete prototype. * lib/open.c (open): Update caller. * lib/dup2.c (dup2): Track fchdir metadata. * lib/dup3.c (dup3): Likewise. * m4/dup2.m4 (gl_REPLACE_DUP2): New macro. * m4/fchdir.m4 (gl_FUNC_FCHDIR): Use it. Signed-off-by: Eric Blake <ebb9@byu.net>
Diffstat (limited to 'lib/dup2.c')
-rw-r--r--lib/dup2.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/lib/dup2.c b/lib/dup2.c
index fb3ffb0df0..a513e5bfea 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -70,6 +70,10 @@ rpl_dup2 (int fd, int desired_fd)
/* Correct a cygwin 1.5.x errno value. */
else if (result == -1 && errno == EMFILE)
errno = EBADF;
+#ifdef FCHDIR_REPLACEMENT
+ if (fd != desired_fd && result == desired_fd)
+ result = _gl_register_dup (fd, desired_fd);
+#endif
return result;
}
@@ -98,13 +102,19 @@ dupfd (int fd, int desired_fd)
int
dup2 (int fd, int desired_fd)
{
+ int result;
if (fd == desired_fd)
- return fd;
+ return fcntl (fd, F_GETFL) < 0 ? -1 : fd;
close (desired_fd);
# ifdef F_DUPFD
- return fcntl (fd, F_DUPFD, desired_fd);
+ result = fcntl (fd, F_DUPFD, desired_fd);
# else
- return dupfd (fd, desired_fd);
+ result = dupfd (fd, desired_fd);
# endif
+#ifdef FCHDIR_REPLACEMENT
+ if (0 <= result)
+ result = _gl_register_dup (fd, desired_fd);
+#endif
+ return result;
}
#endif /* !REPLACE_DUP2 */