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-2014 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 General Public
13 License as published by the Free Software Foundation; either
14 version 3 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 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>. */
27 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
30 # define WIN32_LEAN_AND_MEAN
36 # include "msvc-nothrow.h"
38 /* Determine the current size of a file. Because the other braindead
39 * APIs we'll call need lower/upper 32 bit pairs, keep the file size
43 file_size (HANDLE h, DWORD * lower, DWORD * upper)
45 *lower = GetFileSize (h, upper);
49 /* LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. */
50 # ifndef LOCKFILE_FAIL_IMMEDIATELY
51 # define LOCKFILE_FAIL_IMMEDIATELY 1
56 do_lock (HANDLE h, int non_blocking, int exclusive)
59 DWORD size_lower, size_upper;
63 /* We're going to lock the whole file, so get the file size. */
64 res = file_size (h, &size_lower, &size_upper);
68 /* Start offset is 0, and also zero the remaining members of this struct. */
69 memset (&ovlp, 0, sizeof ovlp);
72 flags |= LOCKFILE_FAIL_IMMEDIATELY;
74 flags |= LOCKFILE_EXCLUSIVE_LOCK;
76 return LockFileEx (h, flags, 0, size_lower, size_upper, &ovlp);
79 /* Unlock reader or exclusive lock. */
84 DWORD size_lower, size_upper;
86 res = file_size (h, &size_lower, &size_upper);
90 return UnlockFile (h, 0, 0, size_lower, size_upper);
93 /* Now our BSD-like flock operation. */
95 flock (int fd, int operation)
97 HANDLE h = (HANDLE) _get_osfhandle (fd);
101 if (h == INVALID_HANDLE_VALUE)
107 non_blocking = operation & LOCK_NB;
108 operation &= ~LOCK_NB;
113 res = do_lock (h, non_blocking, 0);
116 res = do_lock (h, non_blocking, 1);
126 /* Map Windows errors into Unix errnos. As usual MSDN fails to
127 * document the permissible error codes.
131 DWORD err = GetLastError ();
134 /* This means someone else is holding a lock. */
135 case ERROR_LOCK_VIOLATION:
140 case ERROR_NOT_ENOUGH_MEMORY:
144 case ERROR_BAD_COMMAND:
148 /* Unlikely to be other errors, but at least don't lose the
163 # ifdef HAVE_STRUCT_FLOCK_L_TYPE
164 /* We know how to implement flock in terms of fcntl. */
168 # ifdef HAVE_UNISTD_H
176 flock (int fd, int operation)
181 if (operation & LOCK_NB)
185 operation &= ~LOCK_NB;
187 memset (&fl, 0, sizeof fl);
188 fl.l_whence = SEEK_SET;
189 /* l_start & l_len are 0, which as a special case means "whole file". */
207 r = fcntl (fd, cmd, &fl);
208 if (r == -1 && errno == EACCES)
214 # else /* !HAVE_STRUCT_FLOCK_L_TYPE */
216 # error "This platform lacks flock function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
218 # endif /* !HAVE_STRUCT_FLOCK_L_TYPE */
220 #endif /* !Windows */