summaryrefslogtreecommitdiff
path: root/lib/dirfd.c
diff options
context:
space:
mode:
authorKO Myung-Hun <komh78@gmail.com>2016-01-14 11:23:49 +0900
committerPaul Eggert <eggert@cs.ucla.edu>2016-01-14 16:45:38 -0800
commit7524d6101f21f751ea536f237d55cb7ada03824a (patch)
tree3c3ea1d90feaedb193c9a1d791859968f426b022 /lib/dirfd.c
parentc7e1cc415cd60f989fc75b99596e3bd656d3004e (diff)
downloadgnulib-7524d6101f21f751ea536f237d55cb7ada03824a.tar.gz
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.
Diffstat (limited to 'lib/dirfd.c')
-rw-r--r--lib/dirfd.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/lib/dirfd.c b/lib/dirfd.c
index 1ea2a6373d..a32584856a 100644
--- a/lib/dirfd.c
+++ b/lib/dirfd.c
@@ -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;
}