1 /* Emulate fsync on platforms that lack it, primarily Windows and
2    cross-compilers like MinGW.
3 
4    This is derived from sqlite3 sources.
5    https://www.sqlite.org/src/finfo?name=src/os_win.c
6    https://www.sqlite.org/copyright.html
7 
8    Written by Richard W.M. Jones <rjones.at.redhat.com>
9 
10    Copyright (C) 2008-2018 Free Software Foundation, Inc.
11 
12    This library is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public
14    License as published by the Free Software Foundation; either
15    version 3 of the License, or (at your option) any later version.
16 
17    This library is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    General Public License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
24 
25 #include <config.h>
26 #include <unistd.h>
27 
28 #if defined _WIN32 && ! defined __CYGWIN__
29 
30 /* FlushFileBuffers */
31 # define WIN32_LEAN_AND_MEAN
32 # include <windows.h>
33 
34 # include <errno.h>
35 
36 /* Get _get_osfhandle.  */
37 # if GNULIB_MSVC_NOTHROW
38 #  include "msvc-nothrow.h"
39 # else
40 #  include <io.h>
41 # endif
42 
43 int
fsync(int fd)44 fsync (int fd)
45 {
46   HANDLE h = (HANDLE) _get_osfhandle (fd);
47   DWORD err;
48 
49   if (h == INVALID_HANDLE_VALUE)
50     {
51       errno = EBADF;
52       return -1;
53     }
54 
55   if (!FlushFileBuffers (h))
56     {
57       /* Translate some Windows errors into rough approximations of Unix
58        * errors.  MSDN is useless as usual - in this case it doesn't
59        * document the full range of errors.
60        */
61       err = GetLastError ();
62       switch (err)
63         {
64         case ERROR_ACCESS_DENIED:
65           /* For a read-only handle, fsync should succeed, even though we have
66              no way to sync the access-time changes.  */
67           return 0;
68 
69           /* eg. Trying to fsync a tty. */
70         case ERROR_INVALID_HANDLE:
71           errno = EINVAL;
72           break;
73 
74         default:
75           errno = EIO;
76         }
77       return -1;
78     }
79 
80   return 0;
81 }
82 
83 #else /* !Windows */
84 
85 # error "This platform lacks fsync function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
86 
87 #endif /* !Windows */
88