]> Savannah Git Hosting - gnulib.git/commitdiff
opendir, closedir, dirfd, fdopendir: port to OS/2 kLIBC
authorKO Myung-Hun <komh78@gmail.com>
Thu, 14 Jan 2016 02:23:49 +0000 (11:23 +0900)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 15 Jan 2016 00:45:38 +0000 (16:45 -0800)
* 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.

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

index c0298bc5d45ee754dc3ec47456d41c6c1d16192b..30d12903517946e2020cc3d4a2e09f0b24389481 100644 (file)
@@ -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 @@ closedir (DIR *dirp)
 
   retval = closedir (dirp);
 
+# ifdef __KLIBC__
+  if (!retval)
+    _gl_unregister_dirp_fd (fd);
+# endif
 #else
 
   if (dirp->current != INVALID_HANDLE_VALUE)
index 4c62737bdc6bfa4107ce71b22e37f5a3934ea1d8..65482d7b7ac085edd46d2aed0c588e40140cd296 100644 (file)
@@ -158,6 +158,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.
index 1ea2a6373db8965183a99bd61944017018741ed0..a32584856a22be571f3501b4431f03dca9eef4b8 100644 (file)
 #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;
 }
index f30ab2431b59e7b5b1e75911a8de10ca4a92c432..c1f4dcbaca0668ca4cf0b0b7ab1eb5010df63b4e 100644 (file)
@@ -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
index 1b0e8f7d73b6f46f09b51c5af894b3835fc097f8..a135fd834a87688c1aac61a1822139f84021a58b 100644 (file)
 # 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];
index dab66730dd87620a4eb4ae6b4bd329baa15d0b3a..15a5cc8a493f6913c224382fb1457a50ddd99703 100644 (file)
@@ -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 @@ AC_DEFUN([gl_FUNC_CLOSEDIR],
       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
 ])
index e9532e60a999961ccc897bdd4cf265eef01b3ba6..758fed0c6eb2ce89e8db55cfe6fda235d97b9d11 100644 (file)
@@ -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 @@ 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
+      AC_DEFINE([REPLACE_DIRFD], [1],
+        [Define to 1 if gnulib's dirfd() replacement is used.])
     fi
   fi
 ])
index 1181dde172486dc55f1dd633443aafe1a07b90bf..2124f9890dedc93a8cb7bb7db7ea925cd8410508 100644 (file)
@@ -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 @@ 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
 ])
index 8fb964593b8897dab8ec9cb8305637345c388be9..0763878a3c471428ec5df05ea85bbaba724ab4e7 100644 (file)
@@ -8,6 +8,7 @@ m4/closedir.m4
 
 Depends-on:
 dirent
+dirfd           [test $HAVE_CLOSEDIR = 0 || test $REPLACE_CLOSEDIR = 1]
 
 configure.ac:
 gl_FUNC_CLOSEDIR
index 1c6d26fa338945d35df844b1fa414556e3f38e0a..0ad0bf42c251a69eebd0f797e4bd1dc1ea686740 100644 (file)
@@ -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
index cfb9e1a268b782c12437528729b6b8737f4c1510..819285344782ce357628afc848a85ebec87fe9c7 100644 (file)
@@ -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