From 262a473f232c1565ff8c84dae94a9b8ef958a941 Mon Sep 17 00:00:00 2001 From: KO Myung-Hun Date: Fri, 28 Nov 2014 16:47:12 +0900 Subject: [PATCH] opendir, closedir, dirfd, fdopendir: port to OS/2 kLIBC * lib/closedir.c (closedir): Unregister fd if closedir() succeeds. * lib/dirent.h.in (_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): Check OS/2 as well. * 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 | 2 +- m4/dirfd.m4 | 3 ++- m4/opendir.m4 | 2 +- modules/closedir | 1 + modules/dirfd | 5 ++-- modules/fdopendir | 1 + modules/opendir | 1 + 12 files changed, 147 insertions(+), 6 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 #include +#ifdef __KLIBC__ +# include +# include + +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 + +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 #endif +#ifdef __KLIBC__ +# include +# include +#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..0ed82f7 100644 --- a/m4/closedir.m4 +++ b/m4/closedir.m4 @@ -16,7 +16,7 @@ AC_DEFUN([gl_FUNC_CLOSEDIR], dnl to keep fchdir's bookkeeping up-to-date. m4_ifdef([gl_FUNC_FCHDIR], [ gl_TEST_FCHDIR - if test $HAVE_FCHDIR = 0; then + if test $HAVE_FCHDIR = 0 || test -z "${host_os##os2*}"; then if test $HAVE_CLOSEDIR = 1; then REPLACE_CLOSEDIR=1 fi diff --git a/m4/dirfd.m4 b/m4/dirfd.m4 index b422769..34e9496 100644 --- a/m4/dirfd.m4 +++ b/m4/dirfd.m4 @@ -36,7 +36,8 @@ AC_DEFUN([gl_FUNC_DIRFD], 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 + 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..896f34f 100644 --- a/m4/opendir.m4 +++ b/m4/opendir.m4 @@ -16,7 +16,7 @@ AC_DEFUN([gl_FUNC_OPENDIR], dnl to keep fchdir's bookkeeping up-to-date. m4_ifdef([gl_FUNC_FCHDIR], [ gl_TEST_FCHDIR - if test $HAVE_FCHDIR = 0; then + if test $HAVE_FCHDIR = 0 || test -z "${host_os##os2*}" ; then if test $HAVE_OPENDIR = 1; then REPLACE_OPENDIR=1 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