changeset 18208:4de72064cdfe

opendir, closedir, dirfd, fdopendir: port to OS/2 kLIBC * 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. (REPLACE_DIRFD): Define to 1 if replaced. * 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/opendir (Depends-on): Add dirfd.
author KO Myung-Hun <komh78@gmail.com>
date Thu, 14 Jan 2016 11:23:49 +0900
parents a2fadbadc563
children ac0e7e95a996
files lib/closedir.c lib/dirent.in.h lib/dirfd.c lib/fdopendir.c lib/opendir.c m4/closedir.m4 m4/dirfd.m4 m4/opendir.m4 modules/closedir modules/dirfd modules/opendir
diffstat 11 files changed, 162 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/lib/closedir.c	Thu Jan 14 11:23:47 2016 +0900
+++ b/lib/closedir.c	Thu Jan 14 11:23:49 2016 +0900
@@ -39,7 +39,7 @@
 int
 closedir (DIR *dirp)
 {
-# if REPLACE_FCHDIR
+# if REPLACE_FCHDIR || REPLACE_DIRFD
   int fd = dirfd (dirp);
 # endif
   int retval;
@@ -49,6 +49,10 @@
 
   retval = closedir (dirp);
 
+# ifdef __KLIBC__
+  if (!retval)
+    _gl_unregister_dirp_fd (fd);
+# endif
 #else
 
   if (dirp->current != INVALID_HANDLE_VALUE)
--- a/lib/dirent.in.h	Thu Jan 14 11:23:47 2016 +0900
+++ b/lib/dirent.in.h	Thu Jan 14 11:23:49 2016 +0900
@@ -158,6 +158,13 @@
 #  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.
--- a/lib/dirfd.c	Thu Jan 14 11:23:47 2016 +0900
+++ b/lib/dirfd.c	Thu Jan 14 11:23:49 2016 +0900
@@ -22,11 +22,77 @@
 #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 = 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;
 }
--- a/lib/fdopendir.c	Thu Jan 14 11:23:47 2016 +0900
+++ b/lib/fdopendir.c	Thu Jan 14 11:23:49 2016 +0900
@@ -62,6 +62,41 @@
    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 @@
 
   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
--- a/lib/opendir.c	Thu Jan 14 11:23:47 2016 +0900
+++ b/lib/opendir.c	Thu Jan 14 11:23:49 2016 +0900
@@ -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 @@
   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];
--- a/m4/closedir.m4	Thu Jan 14 11:23:47 2016 +0900
+++ b/m4/closedir.m4	Thu Jan 14 11:23:49 2016 +0900
@@ -1,4 +1,4 @@
-# closedir.m4 serial 2
+# closedir.m4 serial 3
 dnl Copyright (C) 2011-2016 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,10 @@
       fi
     fi
   ])
+  dnl Replace closedir() for supporting the gnulib-defined dirfd() function.
+  if test -z "${host_os##os2*}"; then
+    if test $HAVE_OPENDIR = 1; then
+      REPLACE_OPENDIR=1
+    fi
+  fi
 ])
--- a/m4/dirfd.m4	Thu Jan 14 11:23:47 2016 +0900
+++ b/m4/dirfd.m4	Thu Jan 14 11:23:49 2016 +0900
@@ -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,11 +35,15 @@
        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
+      AC_DEFINE([REPLACE_DIRFD], [1],
+        [Define to 1 if gnulib's dirfd() replacement is used.])
     fi
   fi
 ])
--- a/m4/opendir.m4	Thu Jan 14 11:23:47 2016 +0900
+++ b/m4/opendir.m4	Thu Jan 14 11:23:49 2016 +0900
@@ -1,4 +1,4 @@
-# opendir.m4 serial 2
+# opendir.m4 serial 3
 dnl Copyright (C) 2011-2016 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 @@
       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
 ])
--- a/modules/closedir	Thu Jan 14 11:23:47 2016 +0900
+++ b/modules/closedir	Thu Jan 14 11:23:49 2016 +0900
@@ -8,6 +8,7 @@
 
 Depends-on:
 dirent
+dirfd           [test $HAVE_CLOSEDIR = 0 || test $REPLACE_CLOSEDIR = 1]
 
 configure.ac:
 gl_FUNC_CLOSEDIR
--- a/modules/dirfd	Thu Jan 14 11:23:47 2016 +0900
+++ b/modules/dirfd	Thu Jan 14 11:23:49 2016 +0900
@@ -8,11 +8,12 @@
 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
--- a/modules/opendir	Thu Jan 14 11:23:47 2016 +0900
+++ b/modules/opendir	Thu Jan 14 11:23:49 2016 +0900
@@ -12,6 +12,7 @@
 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