105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Hook for making making file descriptor functions close(), ioctl() extensible. 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 2009-2012 Free Software Foundation, Inc. 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang Written by Bruno Haible <bruno@clisp.org>, 2009. 405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 505436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software: you can redistribute it and/or modify it 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang under the terms of the GNU General Public License as published 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang by the Free Software Foundation; either version 3 of the License, or 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang (at your option) any later version. 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, 1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang but WITHOUT ANY WARRANTY; without even the implied warranty of 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang General Public License for more details. 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang You should have received a copy of the GNU General Public License 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h> 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification. */ 2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "fd-hook.h" 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdlib.h> 2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Currently, this entire code is only needed for the handling of sockets 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang on native Windows platforms. */ 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if WINDOWS_SOCKETS 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* The first and last link in the doubly linked list. 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang Initially the list is empty. */ 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic struct fd_hook anchor = { &anchor, &anchor, NULL, NULL }; 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wangexecute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary, 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int fd) 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (remaining_list == &anchor) 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* End of list reached. */ 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return primary (fd); 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return remaining_list->private_close_fn (remaining_list->private_next, 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang primary, fd); 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wangexecute_all_close_hooks (gl_close_fn primary, int fd) 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return execute_close_hooks (anchor.private_next, primary, fd); 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wangexecute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary, 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang int fd, int request, void *arg) 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (remaining_list == &anchor) 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* End of list reached. */ 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return primary (fd, request, arg); 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return remaining_list->private_ioctl_fn (remaining_list->private_next, 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang primary, fd, request, arg); 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wangexecute_all_ioctl_hooks (gl_ioctl_fn primary, 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int fd, int request, void *arg) 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg); 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wangregister_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link) 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (close_hook == NULL) 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang close_hook = execute_close_hooks; 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (ioctl_hook == NULL) 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang ioctl_hook = execute_ioctl_hooks; 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (link->private_next == NULL && link->private_prev == NULL) 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Add the link to the doubly linked list. */ 8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang link->private_next = anchor.private_next; 8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang link->private_prev = &anchor; 8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang link->private_close_fn = close_hook; 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang link->private_ioctl_fn = ioctl_hook; 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang anchor.private_next->private_prev = link; 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang anchor.private_next = link; 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The link is already in use. */ 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (link->private_close_fn != close_hook 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang || link->private_ioctl_fn != ioctl_hook) 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang abort (); 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wangunregister_fd_hook (struct fd_hook *link) 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang struct fd_hook *next = link->private_next; 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang struct fd_hook *prev = link->private_prev; 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (next != NULL && prev != NULL) 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The link is in use. Remove it from the doubly linked list. */ 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang prev->private_next = next; 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang next->private_prev = prev; 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Clear the link, to mark it unused. */ 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang link->private_next = NULL; 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang link->private_prev = NULL; 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang link->private_close_fn = NULL; 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang link->private_ioctl_fn = NULL; 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 117