1 /* Hook for making file descriptor functions close(), ioctl() extensible.
2 Copyright (C) 2009-2023 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2009.
5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
10 This file is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
25 /* Currently, this entire code is only needed for the handling of sockets
26 on native Windows platforms. */
29 /* The first and last link in the doubly linked list.
30 Initially the list is empty. */
31 static struct fd_hook anchor
= { &anchor
, &anchor
, NULL
, NULL
};
34 execute_close_hooks (const struct fd_hook
*remaining_list
, gl_close_fn primary
,
37 if (remaining_list
== &anchor
)
38 /* End of list reached. */
41 return remaining_list
->private_close_fn (remaining_list
->private_next
,
46 execute_all_close_hooks (gl_close_fn primary
, int fd
)
48 return execute_close_hooks (anchor
.private_next
, primary
, fd
);
52 execute_ioctl_hooks (const struct fd_hook
*remaining_list
, gl_ioctl_fn primary
,
53 int fd
, int request
, void *arg
)
55 if (remaining_list
== &anchor
)
56 /* End of list reached. */
57 return primary (fd
, request
, arg
);
59 return remaining_list
->private_ioctl_fn (remaining_list
->private_next
,
60 primary
, fd
, request
, arg
);
64 execute_all_ioctl_hooks (gl_ioctl_fn primary
,
65 int fd
, int request
, void *arg
)
67 return execute_ioctl_hooks (anchor
.private_next
, primary
, fd
, request
, arg
);
71 register_fd_hook (close_hook_fn close_hook
, ioctl_hook_fn ioctl_hook
, struct fd_hook
*link
)
73 if (close_hook
== NULL
)
74 close_hook
= execute_close_hooks
;
75 if (ioctl_hook
== NULL
)
76 ioctl_hook
= execute_ioctl_hooks
;
78 if (link
->private_next
== NULL
&& link
->private_prev
== NULL
)
80 /* Add the link to the doubly linked list. */
81 link
->private_next
= anchor
.private_next
;
82 link
->private_prev
= &anchor
;
83 link
->private_close_fn
= close_hook
;
84 link
->private_ioctl_fn
= ioctl_hook
;
85 anchor
.private_next
->private_prev
= link
;
86 anchor
.private_next
= link
;
90 /* The link is already in use. */
91 if (link
->private_close_fn
!= close_hook
92 || link
->private_ioctl_fn
!= ioctl_hook
)
98 unregister_fd_hook (struct fd_hook
*link
)
100 struct fd_hook
*next
= link
->private_next
;
101 struct fd_hook
*prev
= link
->private_prev
;
103 if (next
!= NULL
&& prev
!= NULL
)
105 /* The link is in use. Remove it from the doubly linked list. */
106 prev
->private_next
= next
;
107 next
->private_prev
= prev
;
108 /* Clear the link, to mark it unused. */
109 link
->private_next
= NULL
;
110 link
->private_prev
= NULL
;
111 link
->private_close_fn
= NULL
;
112 link
->private_ioctl_fn
= NULL
;