[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3 09/13] dup, dup2, fcntl: support a directory fd on OS/2 kLIBC
From: |
KO Myung-Hun |
Subject: |
[PATCH v3 09/13] dup, dup2, fcntl: support a directory fd on OS/2 kLIBC |
Date: |
Mon, 19 Jan 2015 13:47:15 +0900 |
On OS/2 kLIBC, dup(), dup2() and fcntl() do not work on a directory
fd.
* lib/dup.c (dup_nothrow): New.
* lib/dup2.c (klibc_dup2dirfd): New. dup2() for a directory fd.
(klibc_dup2): New.
* lib/fcntl.c (klibc_fcntl): New.
* m4/dup.m4 (gl_FUNC_DUP): Check if dup() works on a directory fd.
* m4/dup2.m4 (gl_FUNC_DUP2): Check if dup2() works on a directory fd.
* m4/fcntl.m4 (gl_FUNC_FCNTL): Check if F_DUPFD works on a directory
fd.
---
lib/dup.c | 25 ++++++++++++++++++
lib/dup2.c | 51 ++++++++++++++++++++++++++++++++++++
lib/fcntl.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
m4/dup.m4 | 30 ++++++++++++++++++++-
m4/dup2.m4 | 15 ++++++++++-
m4/fcntl.m4 | 14 +++++++++-
6 files changed, 219 insertions(+), 3 deletions(-)
diff --git a/lib/dup.c b/lib/dup.c
index 20f0453..734ed13 100644
--- a/lib/dup.c
+++ b/lib/dup.c
@@ -45,6 +45,31 @@ dup_nothrow (int fd)
return result;
}
+#elif defined __KLIBC__
+# include <fcntl.h>
+# include <sys/stat.h>
+
+# include <InnoTekLIBC/backend.h>
+
+static int
+dup_nothrow (int fd)
+{
+ int dupfd;
+ struct stat sbuf;
+
+ dupfd = dup (fd);
+ if (dupfd == -1 && errno == ENOTSUP \
+ && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
+ {
+ char path[_MAX_PATH];
+
+ /* Get a path from fd */
+ if (!__libc_Back_ioFHToPath (fd, path, sizeof (path)))
+ dupfd = open (path, O_RDONLY);
+ }
+
+ return dupfd;
+}
#else
# define dup_nothrow dup
#endif
diff --git a/lib/dup2.c b/lib/dup2.c
index 0e13214..1add8c0 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -85,6 +85,57 @@ ms_windows_dup2 (int fd, int desired_fd)
# define dup2 ms_windows_dup2
+# elif defined __KLIBC__
+
+# include <InnoTekLIBC/backend.h>
+
+static int
+klibc_dup2dirfd (int fd, int desired_fd)
+{
+ int tempfd;
+ int dupfd;
+
+ tempfd = open ("NUL", O_RDONLY);
+ if (tempfd == -1)
+ return -1;
+
+ if (tempfd == desired_fd)
+ {
+ close (tempfd);
+
+ char path[_MAX_PATH];
+ if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
+ return -1;
+
+ return open(path, O_RDONLY);
+ }
+
+ dupfd = klibc_dup2dirfd (fd, desired_fd);
+
+ close (tempfd);
+
+ return dupfd;
+}
+
+static int
+klibc_dup2 (int fd, int desired_fd)
+{
+ int dupfd;
+ struct stat sbuf;
+
+ dupfd = dup2 (fd, desired_fd);
+ if (dupfd == -1 && errno == ENOTSUP \
+ && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
+ {
+ close (desired_fd);
+
+ return klibc_dup2dirfd (fd, desired_fd);
+ }
+
+ return dupfd;
+}
+
+# define dup2 klibc_dup2
# endif
int
diff --git a/lib/fcntl.c b/lib/fcntl.c
index 23b73e9..47bdd91 100644
--- a/lib/fcntl.c
+++ b/lib/fcntl.c
@@ -162,6 +162,93 @@ dupfd (int oldfd, int newfd, int flags)
}
#endif /* W32 */
+#ifdef __KLIBC__
+
+# define INCL_DOS
+# include <os2.h>
+
+static int
+klibc_fcntl (int fd, int action, /* arg */...)
+{
+ va_list arg_ptr;
+ int arg;
+ struct stat sbuf;
+ int result = -1;
+
+ va_start (arg_ptr, action);
+ arg = va_arg (arg_ptr, int);
+ result = fcntl (fd, action, arg);
+ /* EPERM for F_DUPFD, ENOTSUP for others */
+ if (result == -1 && (errno == EPERM || errno == ENOTSUP) \
+ && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
+ {
+ ULONG ulMode;
+
+ switch (action)
+ {
+ case F_DUPFD:
+ /* Find available fd */
+ while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
+ arg++;
+
+ result = dup2 (fd, arg);
+ break;
+
+ /* Using underlying APIs is right ? */
+ case F_GETFD:
+ if (DosQueryFHState (fd, &ulMode))
+ break;
+
+ result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
+ break;
+
+ case F_SETFD:
+ if (arg & ~FD_CLOEXEC)
+ break;
+
+ if (DosQueryFHState (fd, &ulMode))
+ break;
+
+ if (arg & FD_CLOEXEC)
+ ulMode |= OPEN_FLAGS_NOINHERIT;
+ else
+ ulMode &= ~OPEN_FLAGS_NOINHERIT;
+
+ /* Filter supported flags. */
+ ulMode &= OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR \
+ | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT;
+
+ if (DosSetFHState (fd, ulMode))
+ break;
+
+ result = 0;
+ break;
+
+ case F_GETFL:
+ result = 0;
+ break;
+
+ case F_SETFL:
+ if (arg != 0)
+ break;
+
+ result = 0;
+ break;
+
+ default :
+ errno = EINVAL;
+ break;
+ }
+ }
+
+ va_end (arg_ptr);
+
+ return result;
+}
+
+# define fcntl klibc_fcntl
+#endif
+
/* Perform the specified ACTION on the file descriptor FD, possibly
using the argument ARG further described below. This replacement
handles the following actions, and forwards all others on to the
diff --git a/m4/dup.m4 b/m4/dup.m4
index b67e5b7..1206c9c 100644
--- a/m4/dup.m4
+++ b/m4/dup.m4
@@ -1,4 +1,4 @@
-# dup.m4 serial 3
+# dup.m4 serial 4
dnl Copyright (C) 2011-2015 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -19,6 +19,34 @@ AC_DEFUN([gl_FUNC_DUP],
REPLACE_DUP=1
fi
])
+ AC_CACHE_CHECK([whether dup works], [gl_cv_func_dup_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM([[#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>]],
+ [int result = 0;
+ int fd;
+
+ /* On OS/2 kLIBC, dup() does not work on a directory fd. */
+ fd = open (".", O_RDONLY);
+ if (fd == -1)
+ result |= 1;
+ else if (dup (fd) == -1 )
+ result |= 2;
+
+ close (fd);
+
+ return result;
+ ])
+ ],
+ [gl_cv_func_dup_works=yes], [gl_cv_func_dup_works=no])
+ ])
+ case "$gl_cv_func_dup_works" in
+ *yes) ;;
+ *)
+ REPLACE_DUP=1
+ ;;
+ esac
])
# Prerequisites of lib/dup.c.
diff --git a/m4/dup2.m4 b/m4/dup2.m4
index 0354c6a..d743c84 100644
--- a/m4/dup2.m4
+++ b/m4/dup2.m4
@@ -1,4 +1,4 @@
-#serial 20
+#serial 21
dnl Copyright (C) 2002, 2005, 2007, 2009-2015 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -50,6 +50,17 @@ AC_DEFUN([gl_FUNC_DUP2],
result |= 32;
dup2 (2, 255);
dup2 (2, 256);
+ /* On OS/2 kLIBC, dup2() does not work on a directory fd. */
+ {
+ int fd = open (".", O_RDONLY);
+ if (fd == -1)
+ result |= 64;
+ else if (dup2 (fd, fd + 1) == -1 )
+ result |= 128;
+
+ close (fd);
+ }
+
return result;
])
],
@@ -68,6 +79,8 @@ AC_DEFUN([gl_FUNC_DUP2],
gl_cv_func_dup2_works="guessing no" ;;
haiku*) # on Haiku alpha 2, dup2(1, 1) resets FD_CLOEXEC.
gl_cv_func_dup2_works="guessing no" ;;
+ os2*) # on OS/2 kLIBC, dup2() does not work on a directory fd.
+ gl_cv_func_dup2_works="guessing no" ;;
*) gl_cv_func_dup2_works="guessing yes" ;;
esac])
])
diff --git a/m4/fcntl.m4 b/m4/fcntl.m4
index 733cd2d..6042682 100644
--- a/m4/fcntl.m4
+++ b/m4/fcntl.m4
@@ -1,4 +1,4 @@
-# fcntl.m4 serial 5
+# fcntl.m4 serial 6
dnl Copyright (C) 2009-2015 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -43,6 +43,18 @@ AC_DEFUN([gl_FUNC_FCNTL],
if (errno != EINVAL) result |= 2;
if (fcntl (0, F_DUPFD, bad_fd) != -1) result |= 4;
if (errno != EINVAL) result |= 8;
+ /* On OS/2 kLIBC, F_DUPFD does not work on a directory fd */
+ {
+ int fd;
+ fd = open (".", O_RDONLY);
+ if (fd == -1)
+ result |= 16;
+ else if (fcntl (fd, F_DUPFD, STDERR_FILENO + 1) == -1)
+ result |= 32;
+
+ close (fd);
+ }
+
return result;
]])],
[gl_cv_func_fcntl_f_dupfd_works=yes],
--
1.8.5.2
- [PATCH v3] OS/2 patches, KO Myung-Hun, 2015/01/18
- [PATCH v3 05/13] getdtablesize: do not use getrlimit() on OS/2 kLIBC, KO Myung-Hun, 2015/01/18
- [PATCH v3 06/13] wcwidth: fix 'conflicting types' error for `__wcwidth' on OS/2 kLIBC, KO Myung-Hun, 2015/01/18
- [PATCH v3 02/13] binary-io: don't put fd in binary mode if it is a console on EMX, KO Myung-Hun, 2015/01/18
- [PATCH v3 01/13] stdint: check _INTPTR_T_DECLARED before defining intptr_t and uintptr_t, KO Myung-Hun, 2015/01/18
- [PATCH v3 03/13] pipe-filter-aux: undefine HAVE_SELECT on KLIBC, KO Myung-Hun, 2015/01/18
- [PATCH v3 04/13] w32spawn: clear SHELL_SPECIAL_CHARS and SHELL_SPACE_CHAR on OS/2 kLIBC, KO Myung-Hun, 2015/01/18
- [PATCH v3 08/13] pipe_filter_ii_execute: port to OS/2 kLIBC, KO Myung-Hun, 2015/01/18
- [PATCH v3 07/13] gnulib-tool: fall back into copy if symbolic link is not supported, KO Myung-Hun, 2015/01/18
- [PATCH v3 09/13] dup, dup2, fcntl: support a directory fd on OS/2 kLIBC,
KO Myung-Hun <=
- [PATCH v3 11/13] configmake: prepend /@unixroot on OS/2 kLIBC, KO Myung-Hun, 2015/01/18
- [PATCH v3 13/13] openat_proc_name: port to OS/2 kLIBC, KO Myung-Hun, 2015/01/18
- [PATCH v3 12/13] utimes: detect utimes() correctly on OS/2 kLIBC, KO Myung-Hun, 2015/01/18
- [PATCH v3 10/13] opendir, closedir, dirfd, fdopendir: port to OS/2 kLIBC, KO Myung-Hun, 2015/01/18