Mercurial > gnulib
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