]> git.cworth.org Git - tar/blob - lib/close.c
Imported Upstream version 1.21
[tar] / lib / close.c
1 /* close replacement.
2    Copyright (C) 2008 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 #include <config.h>
18
19 /* Specification.  */
20 #include <unistd.h>
21
22 #if GNULIB_SYS_SOCKET
23 # define WIN32_LEAN_AND_MEAN
24 # include <sys/socket.h>
25 #endif
26
27 #if HAVE__GL_CLOSE_FD_MAYBE_SOCKET
28
29 /* Get set_winsock_errno, FD_TO_SOCKET etc. */
30 #include "w32sock.h"
31
32 static int
33 _gl_close_fd_maybe_socket (int fd)
34 {
35   SOCKET sock = FD_TO_SOCKET (fd);
36   WSANETWORKEVENTS ev;
37
38   ev.lNetworkEvents = 0xDEADBEEF;
39   WSAEnumNetworkEvents (sock, NULL, &ev);
40   if (ev.lNetworkEvents != 0xDEADBEEF)
41     {
42       /* FIXME: other applications, like squid, use an undocumented
43          _free_osfhnd free function.  But this is not enough: The 'osfile'
44          flags for fd also needs to be cleared, but it is hard to access it.
45          Instead, here we just close twice the file descriptor.  */
46       if (closesocket (sock))
47         {
48           set_winsock_errno ();
49           return -1;
50         }
51       else
52         {
53           /* This call frees the file descriptor and does a
54              CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails.  */
55           _close (fd);
56           return 0;
57         }
58     }
59   else
60     return _close (fd);
61 }
62 #endif
63
64 /* Override close() to call into other gnulib modules.  */
65
66 int
67 rpl_close (int fd)
68 #undef close
69 {
70 #if HAVE__GL_CLOSE_FD_MAYBE_SOCKET
71   int retval = _gl_close_fd_maybe_socket (fd);
72 #else
73   int retval = close (fd);
74 #endif
75
76 #ifdef FCHDIR_REPLACEMENT
77   if (retval >= 0)
78     _gl_unregister_fd (fd);
79 #endif
80
81   return retval;
82 }