bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 14/14] opendir, closedir, dirfd, fdopendir: port to OS/2 kLIBC


From: KO Myung-Hun
Subject: [PATCH 14/14] opendir, closedir, dirfd, fdopendir: port to OS/2 kLIBC
Date: Tue, 9 Dec 2014 10:40:59 +0900

* lib/closedir.c (closedir): Unregister fd if closedir() succeeds.
* lib/dirent.in.h (_gl_register_dirp_fd, _gl_unregister_dirp_fd):
Declare on kLIBC.
* lib/dirfd.c (struct dirp_fd_list): New. Structures to keep track of
fd associated with dirp.
(_gl_register_dirp_fd): New. Register fd associated with dirp to
dirp_fd_list.
(_gl_unregister_dirp_fd): New. Unregister fd with closing it.
(dirfd): Implemented for kLIBC.
* lib/fdopendir.c (fdopendir): Implemented for kLIBC.
* lib/opendir.c (opendir): New. Register fd and dirp pair if open()
succeeds.
* m4/closedir.m4 (gl_FUNC_CLOSEDIR): Replace if OS/2.
* m4/dirfd.m4 (gl_FUNC_DIRFD): Likewise.
* m4/opendir.m4 (gl_FUNC_OPENDIR): Likewise.
* modules/closedir (Depends-on): Add dirfd.
* modules/dirfd (Depends-on): Add 'test $REPLACE_DIRFD = 1' to errno
condition.
(configure.ac): Add dirfd to LIBOBJS if $REPLACE_DIRFD = 1 as well.
* modules/fdopendir (Depends-on): Add dirfd.
* modules/opendir (Depends-on): Add dirfd.
---
 lib/closedir.c    |  6 ++++-
 lib/dirent.in.h   |  7 ++++++
 lib/dirfd.c       | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/fdopendir.c   | 36 +++++++++++++++++++++++++++++
 lib/opendir.c     | 21 +++++++++++++++++
 m4/closedir.m4    |  9 +++++++-
 m4/dirfd.m4       |  8 ++++---
 m4/opendir.m4     |  9 +++++++-
 modules/closedir  |  1 +
 modules/dirfd     |  5 ++--
 modules/fdopendir |  1 +
 modules/opendir   |  1 +
 12 files changed, 164 insertions(+), 8 deletions(-)

diff --git a/lib/closedir.c b/lib/closedir.c
index 940c6f9..b40181c 100644
--- a/lib/closedir.c
+++ b/lib/closedir.c
@@ -39,7 +39,7 @@
 int
 closedir (DIR *dirp)
 {
-# if REPLACE_FCHDIR
+# if REPLACE_FCHDIR || defined __KLIBC__
   int fd = dirfd (dirp);
 # endif
   int retval;
@@ -49,6 +49,10 @@ closedir (DIR *dirp)
 
   retval = closedir (dirp);
 
+# ifdef __KLIBC__
+  if (!retval)
+    _gl_unregister_dirp_fd (fd);
+# endif
 #else
 
   if (dirp->current != INVALID_HANDLE_VALUE)
diff --git a/lib/dirent.in.h b/lib/dirent.in.h
index 4822d6b..cce86d9 100644
--- a/lib/dirent.in.h
+++ b/lib/dirent.in.h
@@ -156,6 +156,13 @@ _GL_WARN_ON_USE (closedir, "closedir is not portable - "
 #  endif
 _GL_FUNCDECL_RPL (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1)));
 _GL_CXXALIAS_RPL (dirfd, int, (DIR *));
+
+#  ifdef __KLIBC__
+/* Gnulib internal hooks needed to maintain the dirfd metadata.  */
+_GL_EXTERN_C int _gl_register_dirp_fd (int fd, DIR *dirp)
+     _GL_ARG_NONNULL ((2));
+_GL_EXTERN_C void _gl_unregister_dirp_fd (int fd);
+#  endif
 # else
 #  if defined __cplusplus && defined GNULIB_NAMESPACE && defined dirfd
     /* dirfd is defined as a macro and not as a function.
diff --git a/lib/dirfd.c b/lib/dirfd.c
index 4d37928..aa6514f 100644
--- a/lib/dirfd.c
+++ b/lib/dirfd.c
@@ -22,11 +22,79 @@
 #include <dirent.h>
 #include <errno.h>
 
+#ifdef __KLIBC__
+# include <stdlib.h>
+# include <io.h>
+
+static struct dirp_fd_list
+{
+  DIR *dirp;
+  int fd;
+  struct dirp_fd_list *next;
+} *dirp_fd_start = NULL;
+
+/* Register fd associated with dirp to dirp_fd_list. */
+int
+_gl_register_dirp_fd (int fd, DIR *dirp)
+{
+  struct dirp_fd_list *new_dirp_fd;
+
+  new_dirp_fd = malloc (sizeof (*new_dirp_fd));
+  if (!new_dirp_fd)
+    return -1;
+
+  new_dirp_fd->dirp = dirp;
+  new_dirp_fd->fd = fd;
+  new_dirp_fd->next = dirp_fd_start;
+
+  dirp_fd_start = new_dirp_fd;
+
+  return 0;
+}
+
+/* Unregister fd from dirp_fd_list with closing it */
+void
+_gl_unregister_dirp_fd (int fd)
+{
+  struct dirp_fd_list *dirp_fd;
+  struct dirp_fd_list *dirp_fd_prev;
+
+  for (dirp_fd_prev = NULL, dirp_fd = dirp_fd_start; dirp_fd;
+       dirp_fd_prev = dirp_fd, dirp_fd = dirp_fd->next)
+    {
+      if (dirp_fd->fd == fd)
+        {
+          if (dirp_fd_prev)
+            dirp_fd_prev->next = dirp_fd->next;
+          else  /* dirp_fd == dirp_fd_start */
+            dirp_fd_start = dirp_fd_start->next;
+
+          close (fd);
+          free (dirp_fd);
+          break;
+        }
+    }
+}
+#endif
+
 int
 dirfd (DIR *dir_p)
 {
   int fd = DIR_TO_FD (dir_p);
   if (fd == -1)
+#ifndef __KLIBC__
     errno = ENOTSUP;
+#else
+    {
+      struct dirp_fd_list *dirp_fd;
+
+      for (dirp_fd = dirp_fd_start; dirp_fd; dirp_fd = dirp_fd->next)
+        if (dirp_fd->dirp == dir_p)
+          return dirp_fd->fd;
+
+      errno = EINVAL;
+    }
+#endif
+
   return fd;
 }
diff --git a/lib/fdopendir.c b/lib/fdopendir.c
index b6c94a0..80ec4cf 100644
--- a/lib/fdopendir.c
+++ b/lib/fdopendir.c
@@ -62,6 +62,41 @@ static DIR *fd_clone_opendir (int, struct saved_cwd const *);
    If this function returns successfully, FD is under control of the
    dirent.h system, and the caller should not close or modify the state of
    FD other than by the dirent.h functions.  */
+# ifdef __KLIBC__
+#  include <InnoTekLIBC/backend.h>
+
+DIR *
+fdopendir (int fd)
+{
+  char path[_MAX_PATH];
+  DIR *dirp;
+
+  /* Get a path from fd */
+  if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
+    return NULL;
+
+  dirp = opendir (path);
+  if (!dirp)
+    return NULL;
+
+  /* Unregister fd registered by opendir() */
+  _gl_unregister_dirp_fd (dirfd (dirp));
+
+  /* Register our fd */
+  if (_gl_register_dirp_fd (fd, dirp))
+    {
+      int saved_errno = errno;
+
+      closedir (dirp);
+
+      errno = saved_errno;
+
+      dirp = NULL;
+    }
+
+  return dirp;
+}
+# else
 DIR *
 fdopendir (int fd)
 {
@@ -84,6 +119,7 @@ fdopendir (int fd)
 
   return dir;
 }
+# endif
 
 /* Like fdopendir, except that if OLDER_DUPFD is not -1, it is known
    to be a dup of FD which is less than FD - 1 and which will be
diff --git a/lib/opendir.c b/lib/opendir.c
index c67f2e5..064e699 100644
--- a/lib/opendir.c
+++ b/lib/opendir.c
@@ -40,6 +40,11 @@
 # include <unistd.h>
 #endif
 
+#ifdef __KLIBC__
+# include <io.h>
+# include <fcntl.h>
+#endif
+
 DIR *
 opendir (const char *dir_name)
 {
@@ -51,6 +56,22 @@ opendir (const char *dir_name)
   if (dirp == NULL)
     return NULL;
 
+# ifdef __KLIBC__
+  {
+    int fd = open (dir_name, O_RDONLY);
+    if (fd == -1 || _gl_register_dirp_fd (fd, dirp))
+      {
+        int saved_errno = errno;
+
+        close (fd);
+        closedir (dirp);
+
+        errno = saved_errno;
+
+        return NULL;
+      }
+  }
+# endif
 #else
 
   char dir_name_mask[MAX_PATH + 1 + 1 + 1];
diff --git a/m4/closedir.m4 b/m4/closedir.m4
index d234a52..206f5f8 100644
--- a/m4/closedir.m4
+++ b/m4/closedir.m4
@@ -1,4 +1,4 @@
-# closedir.m4 serial 2
+# closedir.m4 serial 3
 dnl Copyright (C) 2011-2014 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -22,4 +22,11 @@ AC_DEFUN([gl_FUNC_CLOSEDIR],
       fi
     fi
   ])
+  dnl Replace closedir() on OS/2 kLIBC for support dirfd() function replaced
+  dnl by gnulib.
+  if test -z "${host_os##os2*}"; then
+    if test $HAVE_OPENDIR = 1; then
+      REPLACE_OPENDIR=1
+    fi
+  fi
 ])
diff --git a/m4/dirfd.m4 b/m4/dirfd.m4
index b422769..1de121a 100644
--- a/m4/dirfd.m4
+++ b/m4/dirfd.m4
@@ -1,4 +1,4 @@
-# serial 22   -*- Autoconf -*-
+# serial 23   -*- Autoconf -*-
 
 dnl Find out how to get the file descriptor associated with an open DIR*.
 
@@ -35,8 +35,10 @@ AC_DEFUN([gl_FUNC_DIRFD],
        gl_cv_func_dirfd_macro=yes,
        gl_cv_func_dirfd_macro=no)])
 
-  # Use the replacement only if we have no function or macro with that name.
-  if test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no; then
+  # Use the replacement if we have no function or macro with that name,
+  # or if OS/2 kLIBC whose dirfd() does not work.
+  if test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no \
+     || test  -z "${host_os##os2*}" ; then
     if test $ac_cv_have_decl_dirfd = yes; then
       # If the system declares dirfd already, let's declare rpl_dirfd instead.
       REPLACE_DIRFD=1
diff --git a/m4/opendir.m4 b/m4/opendir.m4
index fa29c64..4dcba85 100644
--- a/m4/opendir.m4
+++ b/m4/opendir.m4
@@ -1,4 +1,4 @@
-# opendir.m4 serial 2
+# opendir.m4 serial 3
 dnl Copyright (C) 2011-2014 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -22,4 +22,11 @@ AC_DEFUN([gl_FUNC_OPENDIR],
       fi
     fi
   ])
+  dnl Replace opendir() on OS/2 kLIBC to support dirfd() function replaced
+  dnl by gnulib.
+  if test -z "${host_os##os2*}"; then
+    if test $HAVE_OPENDIR = 1; then
+      REPLACE_OPENDIR=1
+    fi
+  fi
 ])
diff --git a/modules/closedir b/modules/closedir
index 8fb9645..0763878 100644
--- a/modules/closedir
+++ b/modules/closedir
@@ -8,6 +8,7 @@ m4/closedir.m4
 
 Depends-on:
 dirent
+dirfd           [test $HAVE_CLOSEDIR = 0 || test $REPLACE_CLOSEDIR = 1]
 
 configure.ac:
 gl_FUNC_CLOSEDIR
diff --git a/modules/dirfd b/modules/dirfd
index 1c6d26f..0ad0bf4 100644
--- a/modules/dirfd
+++ b/modules/dirfd
@@ -8,11 +8,12 @@ m4/dirfd.m4
 Depends-on:
 dirent
 extensions
-errno           [test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = 
no]
+errno           [test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = 
no || test $REPLACE_DIRFD = 1]
 
 configure.ac:
 gl_FUNC_DIRFD
-if test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no; then
+if test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no \
+   || test $REPLACE_DIRFD = 1; then
   AC_LIBOBJ([dirfd])
   gl_PREREQ_DIRFD
 fi
diff --git a/modules/fdopendir b/modules/fdopendir
index ee9a875..0606e5d 100644
--- a/modules/fdopendir
+++ b/modules/fdopendir
@@ -16,6 +16,7 @@ fstat           [test $HAVE_FDOPENDIR = 0]
 openat-die      [test $HAVE_FDOPENDIR = 0]
 opendir         [test $HAVE_FDOPENDIR = 0]
 save-cwd        [test $HAVE_FDOPENDIR = 0]
+dirfd           [test $HAVE_FDOPENDIR = 0]
 
 configure.ac:
 gl_FUNC_FDOPENDIR
diff --git a/modules/opendir b/modules/opendir
index cfb9e1a..8192853 100644
--- a/modules/opendir
+++ b/modules/opendir
@@ -12,6 +12,7 @@ largefile
 filename        [test $HAVE_OPENDIR = 0 || test $REPLACE_OPENDIR = 1]
 unistd          [test $HAVE_OPENDIR = 0 || test $REPLACE_OPENDIR = 1]
 closedir        [test $HAVE_OPENDIR = 0 || test $REPLACE_OPENDIR = 1]
+dirfd           [test $HAVE_OPENDIR = 0 || test $REPLACE_OPENDIR = 1]
 
 configure.ac:
 gl_FUNC_OPENDIR
-- 
1.8.5.2




reply via email to

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