* hurd/hurdioctl.c (_hurd_dummy_ioctl_handler): New function. * hurd/hurd/ioctl.h (_hurd_dummy_ioctl_handler): Likewise. * hurd/fd-ioctl-call.c: New file. * hurd/hurd/fd.h: Update copyright years. (_hurd_fd_call_ioctl_handler): New function declaration. * hurd/Makefile: Update copyright years. (user-interfaces): Add `ioctl_handler'. (dtable): Add `fd-ioctl-call'. * sysdeps/mach/hurd/ioctl.c: Update copyright years. (__ioctl): Call fd ioctl handler. --- hurd/Makefile | 7 ++- hurd/fd-ioctl-call.c | 90 +++++++++++++++++++++++++++++++++++++++++++++ hurd/hurd/fd.h | 6 ++- hurd/hurd/ioctl.h | 5 ++ hurd/hurdioctl.c | 9 ++++- sysdeps/mach/hurd/ioctl.c | 12 +++++- 6 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 hurd/fd-ioctl-call.c
diff --git a/hurd/Makefile b/hurd/Makefile index ff6b7cb..4ad5128 100644 --- a/hurd/Makefile +++ b/hurd/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991,92,93,94,95,96,97,98,99,2001,2002,2004,2006 +# Copyright (C) 1991,92,93,94,95,96,97,98,99,2001,2002,2004,2006,2009 # Free Software Foundation, Inc. # This file is part of the GNU C Library. @@ -40,7 +40,7 @@ user-interfaces := $(addprefix hurd/,\ msg msg_reply msg_request \ exec exec_startup crash interrupt \ fs fsys io term tioctl socket ifsock \ - login password pfinet \ + login password pfinet ioctl_handler \ ) server-interfaces := hurd/msg faultexc @@ -67,7 +67,8 @@ sig = hurdsig hurdfault siginfo hurd-raise preempt-sig \ thread-self thread-cancel intr-msg catch-signal dtable = dtable port2fd new-fd alloc-fd intern-fd \ getdport openport \ - fd-close fd-read fd-write hurdioctl ctty-input ctty-output + fd-close fd-read fd-write hurdioctl ctty-input ctty-output \ + fd-ioctl-call inlines = $(inline-headers:%.h=%-inlines) distribute = hurdstartup.h hurdfault.h hurdhost.h sysvshm.h \ faultexc.defs intr-rpc.defs intr-rpc.h intr-msg.h Notes diff --git a/hurd/fd-ioctl-call.c b/hurd/fd-ioctl-call.c new file mode 100644 index 0000000..c5a41e8 --- /dev/null +++ b/hurd/fd-ioctl-call.c @@ -0,0 +1,90 @@ +/* Call descriptors ioctl handler. + Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library 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 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/ioctl.h> +#include <hurd/ioctl_handler.h> +#include <dlfcn.h> +#include <stdio.h> +#include <unistd.h> + + +/* Get PORT's ioctl handler module and load it, returning the linker map + in MAP as returned by `dlopen'. */ + +static error_t +load_ioctl_handler (io_t port, void **map) +{ + io_t handler; + error_t err; + + err = __ioctl_handler_get (port, &handler); + if (!err) + { + int fd = _hurd_intern_fd (handler, 0, 1); /* Consumes HANDLER. */ + if (fd == -1) + err = errno; + else + { + char *name; + err = __asprintf (&name, "/dev/fd/%d", fd); + if (err == -1) + err = errno; + else + { + *map = __libc_dlopen (name); + free (name); + err = 0; + } + __close (fd); + } + } + + return err; +} + + +/* Call D's ioctl handler, loading it from the underlying port if + necessary. Arguments are the same as ioctl handlers. */ + +int +_hurd_fd_call_ioctl_handler (int fd, int request, void *arg) +{ + ioctl_handler_t ioctl_handler; + void *ioctl_handler_map; + int result; + error_t err; + + /* Avoid spurious "may be used uninitialized" warning. */ + ioctl_handler_map = NULL; + + err = HURD_DPORT_USE (fd, load_ioctl_handler (port, &ioctl_handler_map)); + if (!err && ioctl_handler_map) + ioctl_handler = __libc_dlsym (ioctl_handler_map, "hurd_ioctl_handler"); + if (err || !ioctl_handler_map || !ioctl_handler) + ioctl_handler = _hurd_dummy_ioctl_handler; + + result = (*ioctl_handler) (fd, request, arg); + + if (ioctl_handler_map) + __libc_dlclose (ioctl_handler_map); + + return result; +} diff --git a/hurd/hurd/fd.h b/hurd/hurd/fd.h index 2a981f4..6ea9ad6 100644 --- a/hurd/hurd/fd.h +++ b/hurd/hurd/fd.h @@ -1,6 +1,6 @@ /* File descriptors. Copyright (C) 1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2006,2007 - Free Software Foundation, Inc. + 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -291,5 +291,9 @@ extern file_t __directory_name_split_at (int fd, const char *directory_name, char **name); +/* Call D's ioctl handler, loading it from the underlying port if + necessary. Arguments are the same as ioctl handlers. */ +extern int _hurd_fd_call_ioctl_handler (int fd, int request, void *arg); + #endif /* hurd/fd.h */ diff --git a/hurd/hurd/ioctl.h b/hurd/hurd/ioctl.h index e5ab3dc..f932fa1 100644 --- a/hurd/hurd/ioctl.h +++ b/hurd/hurd/ioctl.h @@ -74,4 +74,9 @@ extern int hurd_register_ioctl_handler (int first_request, int last_request, ioctl_handler_t _hurd_lookup_ioctl_handler (int request); +/* A dummy handler that always fails. */ + +int _hurd_dummy_ioctl_handler (int fd, int request, void *arg); + + #endif /* hurd/ioctl.h */ diff --git a/hurd/hurdioctl.c b/hurd/hurdioctl.c index 13a1a78..0b91ee1 100644 --- a/hurd/hurdioctl.c +++ b/hurd/hurdioctl.c @@ -1,5 +1,5 @@ /* ioctl commands which must be done in the C library. - Copyright (C) 1994,95,96,97,99,2001,02 Free Software Foundation, Inc. + Copyright (C) 1994,95,96,97,99,2001,02,09 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -50,6 +50,13 @@ _hurd_lookup_ioctl_handler (int request) return NULL; } +/* A dummy handler that always fails. */ +int +_hurd_dummy_ioctl_handler (int fd, int request, void *arg) +{ + return __hurd_fail (ENOTTY); +} + #include <fcntl.h> /* Find out how many bytes may be read from FD without blocking. */ diff --git a/sysdeps/mach/hurd/ioctl.c b/sysdeps/mach/hurd/ioctl.c index 769eb68..736ad8e 100644 --- a/sysdeps/mach/hurd/ioctl.c +++ b/sysdeps/mach/hurd/ioctl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992,93,94,95,96,97,99,2000,2002,2005 +/* Copyright (C) 1992,93,94,95,96,97,99,2000,2002,2005,2009 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -220,6 +220,16 @@ __ioctl (int fd, unsigned long int request, ...) } { + int save = errno; + int result = _hurd_fd_call_ioctl_handler (fd, request, arg); + if (result != -1 || errno != ENOTTY) + return result; + + /* The handler doesn't grok this one. Try linked handlers. */ + errno = save; + } + + { /* Check for a registered handler for REQUEST. */ ioctl_handler_t handler = _hurd_lookup_ioctl_handler (request); if (handler) -- 1.6.3.3