1 /* Emulate flock on platforms that lack it, primarily Windows and MinGW.
3 This is derived from sqlite3 sources.
4 http://www.sqlite.org/cvstrac/rlog?f=sqlite/src/os_win.c
5 http://www.sqlite.org/copyright.html
7 Written by Richard W.M. Jones <rjones.at.redhat.com>
9 Copyright (C) 2008-2017 Free Software Foundation, Inc.
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public License
22 along with this program. If not, see <https://www.gnu.org/licenses/>. */
27 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
30 # define WIN32_LEAN_AND_MEAN
36 # if GNULIB_MSVC_NOTHROW
37 # include "msvc-nothrow.h"
42 /* Determine the current size of a file. Because the other braindead
43 * APIs we'll call need lower/upper 32 bit pairs, keep the file size
47 file_size (HANDLE h
, DWORD
* lower
, DWORD
* upper
)
49 *lower
= GetFileSize (h
, upper
);
53 /* LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. */
54 # ifndef LOCKFILE_FAIL_IMMEDIATELY
55 # define LOCKFILE_FAIL_IMMEDIATELY 1
60 do_lock (HANDLE h
, int non_blocking
, int exclusive
)
63 DWORD size_lower
, size_upper
;
67 /* We're going to lock the whole file, so get the file size. */
68 res
= file_size (h
, &size_lower
, &size_upper
);
72 /* Start offset is 0, and also zero the remaining members of this struct. */
73 memset (&ovlp
, 0, sizeof ovlp
);
76 flags
|= LOCKFILE_FAIL_IMMEDIATELY
;
78 flags
|= LOCKFILE_EXCLUSIVE_LOCK
;
80 return LockFileEx (h
, flags
, 0, size_lower
, size_upper
, &ovlp
);
83 /* Unlock reader or exclusive lock. */
88 DWORD size_lower
, size_upper
;
90 res
= file_size (h
, &size_lower
, &size_upper
);
94 return UnlockFile (h
, 0, 0, size_lower
, size_upper
);
97 /* Now our BSD-like flock operation. */
99 flock (int fd
, int operation
)
101 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
105 if (h
== INVALID_HANDLE_VALUE
)
111 non_blocking
= operation
& LOCK_NB
;
112 operation
&= ~LOCK_NB
;
117 res
= do_lock (h
, non_blocking
, 0);
120 res
= do_lock (h
, non_blocking
, 1);
130 /* Map Windows errors into Unix errnos. As usual MSDN fails to
131 * document the permissible error codes.
135 DWORD err
= GetLastError ();
138 /* This means someone else is holding a lock. */
139 case ERROR_LOCK_VIOLATION
:
144 case ERROR_NOT_ENOUGH_MEMORY
:
148 case ERROR_BAD_COMMAND
:
152 /* Unlikely to be other errors, but at least don't lose the
167 # ifdef HAVE_STRUCT_FLOCK_L_TYPE
168 /* We know how to implement flock in terms of fcntl. */
172 # ifdef HAVE_UNISTD_H
180 flock (int fd
, int operation
)
185 if (operation
& LOCK_NB
)
189 operation
&= ~LOCK_NB
;
191 memset (&fl
, 0, sizeof fl
);
192 fl
.l_whence
= SEEK_SET
;
193 /* l_start & l_len are 0, which as a special case means "whole file". */
211 r
= fcntl (fd
, cmd
, &fl
);
212 if (r
== -1 && errno
== EACCES
)
218 # else /* !HAVE_STRUCT_FLOCK_L_TYPE */
220 # error "This platform lacks flock function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
222 # endif /* !HAVE_STRUCT_FLOCK_L_TYPE */
224 #endif /* !Windows */