1/* -*- buffer-read-only: t -*- vi: set ro: */
2/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3#line 1
4/* Hook for making the close() function extensible.
5   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
6   Written by Bruno Haible <bruno@clisp.org>, 2009.
7
8   This program is free software: you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published
10   by the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include <config.h>
22
23/* Specification.  */
24#include "close-hook.h"
25
26#include <stdlib.h>
27#include <unistd.h>
28
29#undef close
30
31
32/* Currently, this entire code is only needed for the handling of sockets
33   on native Windows platforms.  */
34#if WINDOWS_SOCKETS
35
36/* The first and last link in the doubly linked list.
37   Initially the list is empty.  */
38static struct close_hook anchor = { &anchor, &anchor, NULL };
39
40int
41execute_close_hooks (int fd, const struct close_hook *remaining_list)
42{
43  if (remaining_list == &anchor)
44    /* End of list reached.  */
45    return close (fd);
46  else
47    return remaining_list->private_fn (fd, remaining_list->private_next);
48}
49
50int
51execute_all_close_hooks (int fd)
52{
53  return execute_close_hooks (fd, anchor.private_next);
54}
55
56void
57register_close_hook (close_hook_fn hook, struct close_hook *link)
58{
59  if (link->private_next == NULL && link->private_prev == NULL)
60    {
61      /* Add the link to the doubly linked list.  */
62      link->private_next = anchor.private_next;
63      link->private_prev = &anchor;
64      link->private_fn = hook;
65      anchor.private_next->private_prev = link;
66      anchor.private_next = link;
67    }
68  else
69    {
70      /* The link is already in use.  */
71      if (link->private_fn != hook)
72        abort ();
73    }
74}
75
76void
77unregister_close_hook (struct close_hook *link)
78{
79  struct close_hook *next = link->private_next;
80  struct close_hook *prev = link->private_prev;
81
82  if (next != NULL && prev != NULL)
83    {
84      /* The link is in use.  Remove it from the doubly linked list.  */
85      prev->private_next = next;
86      next->private_prev = prev;
87      /* Clear the link, to mark it unused.  */
88      link->private_next = NULL;
89      link->private_prev = NULL;
90      link->private_fn = NULL;
91    }
92}
93
94#endif
95