bug-gnulib
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]