* lib/fd-hook.h: Renamed from lib/close-hook.h.
(gl_close_fn, gl_ioctl_fn): New types.
(struct fd_hook): Renamed from struct close_hook. Change type of
private_close_fn field. Add private_ioctl_fn field.
(close_hook_fn): Add parameter for primary close method.
(execute_close_hooks, execute_all_close_hooks): Likewise.
(ioctl_hook_fn): New type.
(execute_ioctl_hooks, execute_all_ioctl_hooks): New declarations.
(register_fd_hook): Renamed from register_close_hook. Add ioctl_hook
argument.
(unregister_fd_hook): Renamed from unregister_close_hook.
* lib/fd-hook.c: Renamed from lib/close-hook.c.
Don't include <unistd.h>.
(close): Remove undef.
(anchor): Update.
(execute_close_hooks): Add argument for primary close method.
(execute_all_close_hooks): Likewise.
(execute_ioctl_hooks, execute_all_ioctl_hooks): New functions.
(register_fd_hook): Renamed from register_close_hook. Add ioctl_hook
argument. Allow each argument to be NULL.
(unregister_fd_hook): Renamed from unregister_close_hook.
* lib/close.c (rpl_close): Pass 'close' function pointer to
execute_all_close_hooks.
* lib/ioctl.c: Include <errno.h>, fd-hook.h.
(primary_ioctl): New function.
(ioctl): Don't call ioctlsocket here. Instead, call
execute_all_ioctl_hooks.
* lib/sockets.c (close_fd_maybe_socket): Add argument for primary
close method.
(ioctl_fd_maybe_socket): New function, with code from lib/ioctl.c.
(fd_sockets_hook): Renamed from close_sockets_hook.
(gl_sockets_startup, gl_sockets_cleanup): Update.
* modules/fd-hook: Renamed from modules/close-hook. Update.
* modules/close (Depends-on): Add fd-hook, remove close-hook.
* modules/sockets (Depends-on): Likewise.
* modules/ioctl (Depends-on): Add fd-hook.
* tests/test-nonblocking.c (main): Use GNULIB_TEST_SOCKET, not
GNULIB_SOCKET.
+2011-04-19 Bruno Haible <bruno@clisp.org>
+
+ ioctl: Remove link dependency on native Windows.
+ * lib/fd-hook.h: Renamed from lib/close-hook.h.
+ (gl_close_fn, gl_ioctl_fn): New types.
+ (struct fd_hook): Renamed from struct close_hook. Change type of
+ private_close_fn field. Add private_ioctl_fn field.
+ (close_hook_fn): Add parameter for primary close method.
+ (execute_close_hooks, execute_all_close_hooks): Likewise.
+ (ioctl_hook_fn): New type.
+ (execute_ioctl_hooks, execute_all_ioctl_hooks): New declarations.
+ (register_fd_hook): Renamed from register_close_hook. Add ioctl_hook
+ argument.
+ (unregister_fd_hook): Renamed from unregister_close_hook.
+ * lib/fd-hook.c: Renamed from lib/close-hook.c.
+ Don't include <unistd.h>.
+ (close): Remove undef.
+ (anchor): Update.
+ (execute_close_hooks): Add argument for primary close method.
+ (execute_all_close_hooks): Likewise.
+ (execute_ioctl_hooks, execute_all_ioctl_hooks): New functions.
+ (register_fd_hook): Renamed from register_close_hook. Add ioctl_hook
+ argument. Allow each argument to be NULL.
+ (unregister_fd_hook): Renamed from unregister_close_hook.
+ * lib/close.c (rpl_close): Pass 'close' function pointer to
+ execute_all_close_hooks.
+ * lib/ioctl.c: Include <errno.h>, fd-hook.h.
+ (primary_ioctl): New function.
+ (ioctl): Don't call ioctlsocket here. Instead, call
+ execute_all_ioctl_hooks.
+ * lib/sockets.c (close_fd_maybe_socket): Add argument for primary
+ close method.
+ (ioctl_fd_maybe_socket): New function, with code from lib/ioctl.c.
+ (fd_sockets_hook): Renamed from close_sockets_hook.
+ (gl_sockets_startup, gl_sockets_cleanup): Update.
+ * modules/fd-hook: Renamed from modules/close-hook. Update.
+ * modules/close (Depends-on): Add fd-hook, remove close-hook.
+ * modules/sockets (Depends-on): Likewise.
+ * modules/ioctl (Depends-on): Add fd-hook.
+ * tests/test-nonblocking.c (main): Use GNULIB_TEST_SOCKET, not
+ GNULIB_SOCKET.
+
2011-04-19 Bruno Haible <bruno@clisp.org>
Move the support of O_NONBLOCK in open() to the 'open' module.
Date Modules Changes
+2011-04-19 close-hook This module has been renamed to 'fd-hook' and
+ generalized.
+
2011-03-08 regex-quote The last argument is no longer an 'int cflags'
but instead a pointer to a previously constructed
'struct regex_quote_spec'.
+++ /dev/null
-/* Hook for making the close() function extensible.
- Copyright (C) 2009-2011 Free Software Foundation, Inc.
- Written by Bruno Haible <bruno@clisp.org>, 2009.
-
- This program is free software: you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include <config.h>
-
-/* Specification. */
-#include "close-hook.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#undef close
-
-
-/* Currently, this entire code is only needed for the handling of sockets
- on native Windows platforms. */
-#if WINDOWS_SOCKETS
-
-/* The first and last link in the doubly linked list.
- Initially the list is empty. */
-static struct close_hook anchor = { &anchor, &anchor, NULL };
-
-int
-execute_close_hooks (int fd, const struct close_hook *remaining_list)
-{
- if (remaining_list == &anchor)
- /* End of list reached. */
- return close (fd);
- else
- return remaining_list->private_fn (fd, remaining_list->private_next);
-}
-
-int
-execute_all_close_hooks (int fd)
-{
- return execute_close_hooks (fd, anchor.private_next);
-}
-
-void
-register_close_hook (close_hook_fn hook, struct close_hook *link)
-{
- if (link->private_next == NULL && link->private_prev == NULL)
- {
- /* Add the link to the doubly linked list. */
- link->private_next = anchor.private_next;
- link->private_prev = &anchor;
- link->private_fn = hook;
- anchor.private_next->private_prev = link;
- anchor.private_next = link;
- }
- else
- {
- /* The link is already in use. */
- if (link->private_fn != hook)
- abort ();
- }
-}
-
-void
-unregister_close_hook (struct close_hook *link)
-{
- struct close_hook *next = link->private_next;
- struct close_hook *prev = link->private_prev;
-
- if (next != NULL && prev != NULL)
- {
- /* The link is in use. Remove it from the doubly linked list. */
- prev->private_next = next;
- next->private_prev = prev;
- /* Clear the link, to mark it unused. */
- link->private_next = NULL;
- link->private_prev = NULL;
- link->private_fn = NULL;
- }
-}
-
-#endif
+++ /dev/null
-/* Hook for making the close() function extensible.
- Copyright (C) 2009-2011 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-
-#ifndef CLOSE_HOOK_H
-#define CLOSE_HOOK_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Currently, this entire code is only needed for the handling of sockets
- on native Windows platforms. */
-#if WINDOWS_SOCKETS
-
-
-/* An element of the list of close hooks.
- The fields of this structure are considered private. */
-struct close_hook
-{
- /* Doubly linked list. */
- struct close_hook *private_next;
- struct close_hook *private_prev;
- /* Function that treats the types of FD that it knows about and calls
- execute_close_hooks (FD, REMAINING_LIST) as a fallback. */
- int (*private_fn) (int fd, const struct close_hook *remaining_list);
-};
-
-/* This type of function closes FD, applying special knowledge for the FD
- types it knows about, and calls execute_close_hooks (FD, REMAINING_LIST)
- for the other FD types. */
-typedef int (*close_hook_fn) (int fd, const struct close_hook *remaining_list);
-
-/* Execute the close hooks in REMAINING_LIST.
- Return 0 or -1, like close() would do. */
-extern int execute_close_hooks (int fd, const struct close_hook *remaining_list);
-
-/* Execute all close hooks.
- Return 0 or -1, like close() would do. */
-extern int execute_all_close_hooks (int fd);
-
-/* Add a function to the list of close hooks.
- The LINK variable points to a piece of memory which is guaranteed to be
- accessible until the corresponding call to unregister_close_hook. */
-extern void register_close_hook (close_hook_fn hook, struct close_hook *link);
-
-/* Removes a function from the list of close hooks. */
-extern void unregister_close_hook (struct close_hook *link);
-
-
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CLOSE_HOOK_H */
/* Specification. */
#include <unistd.h>
-#include "close-hook.h"
+#include "fd-hook.h"
/* Override close() to call into other gnulib modules. */
#undef close
{
#if WINDOWS_SOCKETS
- int retval = execute_all_close_hooks (fd);
+ int retval = execute_all_close_hooks (close, fd);
#else
int retval = close (fd);
#endif
--- /dev/null
+/* Hook for making making file descriptor functions close(), ioctl() extensible.
+ Copyright (C) 2009-2011 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2009.
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "fd-hook.h"
+
+#include <stdlib.h>
+
+/* Currently, this entire code is only needed for the handling of sockets
+ on native Windows platforms. */
+#if WINDOWS_SOCKETS
+
+/* The first and last link in the doubly linked list.
+ Initially the list is empty. */
+static struct fd_hook anchor = { &anchor, &anchor, NULL, NULL };
+
+int
+execute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary,
+ int fd)
+{
+ if (remaining_list == &anchor)
+ /* End of list reached. */
+ return primary (fd);
+ else
+ return remaining_list->private_close_fn (remaining_list->private_next,
+ primary, fd);
+}
+
+int
+execute_all_close_hooks (gl_close_fn primary, int fd)
+{
+ return execute_close_hooks (anchor.private_next, primary, fd);
+}
+
+int
+execute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary,
+ int fd, int request, void *arg)
+{
+ if (remaining_list == &anchor)
+ /* End of list reached. */
+ return primary (fd, request, arg);
+ else
+ return remaining_list->private_ioctl_fn (remaining_list->private_next,
+ primary, fd, request, arg);
+}
+
+int
+execute_all_ioctl_hooks (gl_ioctl_fn primary,
+ int fd, int request, void *arg)
+{
+ return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg);
+}
+
+void
+register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link)
+{
+ if (close_hook == NULL)
+ close_hook = execute_close_hooks;
+ if (ioctl_hook == NULL)
+ ioctl_hook = execute_ioctl_hooks;
+
+ if (link->private_next == NULL && link->private_prev == NULL)
+ {
+ /* Add the link to the doubly linked list. */
+ link->private_next = anchor.private_next;
+ link->private_prev = &anchor;
+ link->private_close_fn = close_hook;
+ link->private_ioctl_fn = ioctl_hook;
+ anchor.private_next->private_prev = link;
+ anchor.private_next = link;
+ }
+ else
+ {
+ /* The link is already in use. */
+ if (link->private_close_fn != close_hook
+ || link->private_ioctl_fn != ioctl_hook)
+ abort ();
+ }
+}
+
+void
+unregister_fd_hook (struct fd_hook *link)
+{
+ struct fd_hook *next = link->private_next;
+ struct fd_hook *prev = link->private_prev;
+
+ if (next != NULL && prev != NULL)
+ {
+ /* The link is in use. Remove it from the doubly linked list. */
+ prev->private_next = next;
+ next->private_prev = prev;
+ /* Clear the link, to mark it unused. */
+ link->private_next = NULL;
+ link->private_prev = NULL;
+ link->private_close_fn = NULL;
+ link->private_ioctl_fn = NULL;
+ }
+}
+
+#endif
--- /dev/null
+/* Hook for making making file descriptor functions close(), ioctl() extensible.
+ Copyright (C) 2009-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+
+#ifndef FD_HOOK_H
+#define FD_HOOK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Currently, this entire code is only needed for the handling of sockets
+ on native Windows platforms. */
+#if WINDOWS_SOCKETS
+
+
+/* Type of function that closes FD. */
+typedef int (*gl_close_fn) (int fd);
+
+/* Type of function that applies a control request to FD. */
+typedef int (*gl_ioctl_fn) (int fd, int request, void *arg);
+
+/* An element of the list of file descriptor hooks.
+ In CLOS (Common Lisp Object System) speak, it consists of an "around"
+ method for the close() function and an "around" method for the ioctl()
+ function.
+ The fields of this structure are considered private. */
+struct fd_hook
+{
+ /* Doubly linked list. */
+ struct fd_hook *private_next;
+ struct fd_hook *private_prev;
+ /* Function that treats the types of FD that it knows about and calls
+ execute_close_hooks (REMAINING_LIST, PRIMARY, FD) as a fallback. */
+ int (*private_close_fn) (const struct fd_hook *remaining_list,
+ gl_close_fn primary,
+ int fd);
+ /* Function that treats the types of FD that it knows about and calls
+ execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) as a
+ fallback. */
+ int (*private_ioctl_fn) (const struct fd_hook *remaining_list,
+ gl_ioctl_fn primary,
+ int fd, int request, void *arg);
+};
+
+/* This type of function closes FD, applying special knowledge for the FD
+ types it knows about, and calls
+ execute_close_hooks (REMAINING_LIST, PRIMARY, FD)
+ for the other FD types.
+ In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
+ and PRIMARY is the "primary" method for close(). */
+typedef int (*close_hook_fn) (const struct fd_hook *remaining_list,
+ gl_close_fn primary,
+ int fd);
+
+/* Execute the close hooks in REMAINING_LIST, with PRIMARY as "primary" method.
+ Return 0 or -1, like close() would do. */
+extern int execute_close_hooks (const struct fd_hook *remaining_list,
+ gl_close_fn primary,
+ int fd);
+
+/* Execute all close hooks, with PRIMARY as "primary" method.
+ Return 0 or -1, like close() would do. */
+extern int execute_all_close_hooks (gl_close_fn primary, int fd);
+
+/* This type of function applies a control request to FD, applying special
+ knowledge for the FD types it knows about, and calls
+ execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG)
+ for the other FD types.
+ In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
+ and PRIMARY is the "primary" method for ioctl(). */
+typedef int (*ioctl_hook_fn) (const struct fd_hook *remaining_list,
+ gl_ioctl_fn primary,
+ int fd, int request, void *arg);
+
+/* Execute the ioctl hooks in REMAINING_LIST, with PRIMARY as "primary" method.
+ Return 0 or -1, like ioctl() would do. */
+extern int execute_ioctl_hooks (const struct fd_hook *remaining_list,
+ gl_ioctl_fn primary,
+ int fd, int request, void *arg);
+
+/* Execute all ioctl hooks, with PRIMARY as "primary" method.
+ Return 0 or -1, like ioctl() would do. */
+extern int execute_all_ioctl_hooks (gl_ioctl_fn primary,
+ int fd, int request, void *arg);
+
+/* Add a function pair to the list of file descriptor hooks.
+ CLOSE_HOOK and IOCTL_HOOK may be NULL, indicating no change.
+ The LINK variable points to a piece of memory which is guaranteed to be
+ accessible until the corresponding call to unregister_fd_hook. */
+extern void register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook,
+ struct fd_hook *link);
+
+/* Removes a hook from the list of file descriptor hooks. */
+extern void unregister_fd_hook (struct fd_hook *link);
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FD_HOOK_H */
#else /* mingw */
-# define WIN32_LEAN_AND_MEAN
-/* Get winsock2.h. */
-# include <sys/socket.h>
+# include <errno.h>
-/* Get set_winsock_errno, FD_TO_SOCKET etc. */
-# include "w32sock.h"
+# include "fd-hook.h"
-int
-ioctl (int fd, int req, ...)
+static int
+primary_ioctl (int fd, int request, void *arg)
{
-# if GNULIB_SOCKET
- void *buf;
- va_list args;
- SOCKET sock;
- int r;
-
- va_start (args, req);
- buf = va_arg (args, void *);
- va_end (args);
-
/* We don't support FIONBIO on pipes here. If you want to make pipe
fds non-blocking, use the gnulib 'nonblocking' module, until
gnulib implements fcntl F_GETFL / F_SETFL with O_NONBLOCK. */
- sock = FD_TO_SOCKET (fd);
- r = ioctlsocket (sock, req, buf);
- if (r < 0)
- set_winsock_errno ();
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+ioctl (int fd, int request, ... /* {void *,char *} arg */)
+{
+ void *arg;
+ va_list args;
- return r;
+ va_start (args, request);
+ arg = va_arg (args, void *);
+ va_end (args);
+# if WINDOWS_SOCKETS
+ return execute_all_ioctl_hooks (primary_ioctl, fd, request, arg);
# else
- errno = ENOSYS;
- return -1;
+ return primary_ioctl (fd, request, arg);
# endif
}
/* This includes winsock2.h on MinGW. */
# include <sys/socket.h>
-# include "close-hook.h"
+# include "fd-hook.h"
/* Get set_winsock_errno, FD_TO_SOCKET etc. */
# include "w32sock.h"
static int
-close_fd_maybe_socket (int fd, const struct close_hook *remaining_list)
+close_fd_maybe_socket (const struct fd_hook *remaining_list,
+ gl_close_fn primary,
+ int fd)
{
SOCKET sock;
WSANETWORKEVENTS ev;
}
else
/* Some other type of file descriptor. */
- return execute_close_hooks (fd, remaining_list);
+ return execute_close_hooks (remaining_list, primary, fd);
}
-static struct close_hook close_sockets_hook;
+static int
+ioctl_fd_maybe_socket (const struct fd_hook *remaining_list,
+ gl_ioctl_fn primary,
+ int fd, int request, void *arg)
+{
+ SOCKET sock;
+ WSANETWORKEVENTS ev;
+
+ /* Test whether fd refers to a socket. */
+ sock = FD_TO_SOCKET (fd);
+ ev.lNetworkEvents = 0xDEADBEEF;
+ WSAEnumNetworkEvents (sock, NULL, &ev);
+ if (ev.lNetworkEvents != 0xDEADBEEF)
+ {
+ /* fd refers to a socket. */
+ if (ioctlsocket (sock, request, arg) < 0)
+ {
+ set_winsock_errno ();
+ return -1;
+ }
+ else
+ return 0;
+ }
+ else
+ /* Some other type of file descriptor. */
+ return execute_ioctl_hooks (remaining_list, primary, fd, request, arg);
+}
+
+static struct fd_hook fd_sockets_hook;
static int initialized_sockets_version /* = 0 */;
return 2;
if (initialized_sockets_version == 0)
- register_close_hook (close_fd_maybe_socket, &close_sockets_hook);
+ register_fd_hook (close_fd_maybe_socket, ioctl_fd_maybe_socket,
+ &fd_sockets_hook);
initialized_sockets_version = version;
}
initialized_sockets_version = 0;
- unregister_close_hook (&close_sockets_hook);
+ unregister_fd_hook (&fd_sockets_hook);
err = WSACleanup ();
if (err != 0)
Depends-on:
unistd
-close-hook
+fd-hook
fclose
configure.ac:
+++ /dev/null
-Description:
-Hook for making close() extensible.
-
-Files:
-lib/close-hook.h
-lib/close-hook.c
-
-Depends-on:
-unistd
-
-configure.ac:
-
-Makefile.am:
-lib_SOURCES += close-hook.c
-
-Include:
-"close-hook.h"
-
-License:
-LGPLv2+
-
-Maintainer:
-Bruno Haible
--- /dev/null
+Description:
+Hook for making file descriptor functions (close(), ioctl()) extensible.
+
+Files:
+lib/fd-hook.h
+lib/fd-hook.c
+
+Depends-on:
+unistd
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += fd-hook.c
+
+Include:
+"fd-hook.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible
sys_ioctl
sys_socket
errno
+fd-hook
configure.ac:
gl_FUNC_IOCTL
Depends-on:
socketlib
sys_socket
-close-hook
+fd-hook
configure.ac:
gl_SOCKETS
ASSERT (close (fd_pipe[1]) == 0);
#endif /* GNULIB_TEST_PIPE2 */
-#if GNULIB_SOCKET
+#if GNULIB_TEST_SOCKET
{
/* Test sockets. */
bool sock_works = true;
ASSERT (close (fd_sock) == 0);
# endif /* SOCK_NONBLOCK */
}
-#endif /* GNULIB_SOCKET */
+#endif /* GNULIB_TEST_SOCKET */
/* Test error handling. */
{