Mercurial > hg > octave-lojdl > gnulib-hg
changeset 14595:32d72ffe29dd
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.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Mon, 18 Apr 2011 02:34:47 +0200 |
parents | e270695eecd5 |
children | 4eeab6ee310c |
files | ChangeLog NEWS lib/close-hook.c lib/close-hook.h lib/close.c lib/fd-hook.c lib/fd-hook.h lib/ioctl.c lib/sockets.c modules/close modules/close-hook modules/fd-hook modules/ioctl modules/sockets tests/test-nonblocking.c |
diffstat | 15 files changed, 367 insertions(+), 223 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,45 @@ +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.
--- a/NEWS +++ b/NEWS @@ -12,6 +12,9 @@ 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'.
deleted file mode 100644 --- a/lib/close-hook.c +++ /dev/null @@ -1,91 +0,0 @@ -/* 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
deleted file mode 100644 --- a/lib/close-hook.h +++ /dev/null @@ -1,72 +0,0 @@ -/* 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 */
--- a/lib/close.c +++ b/lib/close.c @@ -19,7 +19,7 @@ /* Specification. */ #include <unistd.h> -#include "close-hook.h" +#include "fd-hook.h" /* Override close() to call into other gnulib modules. */ @@ -28,7 +28,7 @@ #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
new file mode 100644 --- /dev/null +++ b/lib/fd-hook.c @@ -0,0 +1,116 @@ +/* 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
new file mode 100644 --- /dev/null +++ b/lib/fd-hook.h @@ -0,0 +1,119 @@ +/* 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 */
--- a/lib/ioctl.c +++ b/lib/ioctl.c @@ -44,40 +44,35 @@ #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 (); - - return r; - -# else errno = ENOSYS; return -1; +} + +int +ioctl (int fd, int request, ... /* {void *,char *} arg */) +{ + void *arg; + va_list args; + + 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 + return primary_ioctl (fd, request, arg); # endif }
--- a/lib/sockets.c +++ b/lib/sockets.c @@ -27,13 +27,15 @@ /* 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; @@ -64,10 +66,38 @@ } 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 */; @@ -90,7 +120,8 @@ 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; } @@ -107,7 +138,7 @@ initialized_sockets_version = 0; - unregister_close_hook (&close_sockets_hook); + unregister_fd_hook (&fd_sockets_hook); err = WSACleanup (); if (err != 0)
--- a/modules/close +++ b/modules/close @@ -7,7 +7,7 @@ Depends-on: unistd -close-hook +fd-hook fclose configure.ac:
deleted file mode 100644 --- a/modules/close-hook +++ /dev/null @@ -1,23 +0,0 @@ -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
new file mode 100644 --- /dev/null +++ b/modules/fd-hook @@ -0,0 +1,23 @@ +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
--- a/modules/ioctl +++ b/modules/ioctl @@ -10,6 +10,7 @@ sys_ioctl sys_socket errno +fd-hook configure.ac: gl_FUNC_IOCTL
--- a/modules/sockets +++ b/modules/sockets @@ -10,7 +10,7 @@ Depends-on: socketlib sys_socket -close-hook +fd-hook configure.ac: gl_SOCKETS
--- a/tests/test-nonblocking.c +++ b/tests/test-nonblocking.c @@ -79,7 +79,7 @@ ASSERT (close (fd_pipe[1]) == 0); #endif /* GNULIB_TEST_PIPE2 */ -#if GNULIB_SOCKET +#if GNULIB_TEST_SOCKET { /* Test sockets. */ bool sock_works = true; @@ -104,7 +104,7 @@ ASSERT (close (fd_sock) == 0); # endif /* SOCK_NONBLOCK */ } -#endif /* GNULIB_SOCKET */ +#endif /* GNULIB_TEST_SOCKET */ /* Test error handling. */ {