aboutsummaryrefslogtreecommitdiff
path: root/win32/flock.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/flock.c')
-rw-r--r--win32/flock.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/win32/flock.c b/win32/flock.c
new file mode 100644
index 000000000..260b40171
--- /dev/null
+++ b/win32/flock.c
@@ -0,0 +1,132 @@
1/* Emulate flock on platforms that lack it, primarily Windows and MinGW.
2
3 This is derived from sqlite3 sources.
4 https://www.sqlite.org/src/finfo?name=src/os_win.c
5 https://www.sqlite.org/copyright.html
6
7 Written by Richard W.M. Jones <rjones.at.redhat.com>
8
9 Copyright (C) 2008-2025 Free Software Foundation, Inc.
10
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.
15
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.
20
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/>. */
23
24#include "libbb.h"
25#include <sys/file.h>
26
27/* LockFileEx */
28
29# include <errno.h>
30
31/* _get_osfhandle */
32# include <io.h>
33
34/* Determine the current size of a file. Because the other braindead
35 * APIs we'll call need lower/upper 32 bit pairs, keep the file size
36 * like that too.
37 */
38static BOOL
39file_size (HANDLE h, DWORD * lower, DWORD * upper)
40{
41 *lower = GetFileSize (h, upper);
42 return 1;
43}
44
45/* LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. */
46# ifndef LOCKFILE_FAIL_IMMEDIATELY
47# define LOCKFILE_FAIL_IMMEDIATELY 1
48# endif
49
50/* Acquire a lock. */
51static BOOL
52do_lock (HANDLE h, int non_blocking, int exclusive)
53{
54 BOOL res;
55 DWORD size_lower, size_upper;
56 OVERLAPPED ovlp;
57 int flags = 0;
58
59 /* We're going to lock the whole file, so get the file size. */
60 res = file_size (h, &size_lower, &size_upper);
61 if (!res)
62 return 0;
63
64 /* Start offset is 0, and also zero the remaining members of this struct. */
65 memset (&ovlp, 0, sizeof ovlp);
66
67 if (non_blocking)
68 flags |= LOCKFILE_FAIL_IMMEDIATELY;
69 if (exclusive)
70 flags |= LOCKFILE_EXCLUSIVE_LOCK;
71
72 return LockFileEx (h, flags, 0, size_lower, size_upper, &ovlp);
73}
74
75/* Unlock reader or exclusive lock. */
76static BOOL
77do_unlock (HANDLE h)
78{
79 int res;
80 DWORD size_lower, size_upper;
81
82 res = file_size (h, &size_lower, &size_upper);
83 if (!res)
84 return 0;
85
86 return UnlockFile (h, 0, 0, size_lower, size_upper);
87}
88
89/* Now our BSD-like flock operation. */
90int
91flock (int fd, int operation)
92{
93 HANDLE h = (HANDLE) _get_osfhandle (fd);
94 DWORD res;
95 int non_blocking;
96
97 if (h == INVALID_HANDLE_VALUE)
98 {
99 errno = EBADF;
100 return -1;
101 }
102
103 non_blocking = operation & LOCK_NB;
104 operation &= ~LOCK_NB;
105
106 switch (operation)
107 {
108 case LOCK_SH:
109 res = do_lock (h, non_blocking, 0);
110 break;
111 case LOCK_EX:
112 res = do_lock (h, non_blocking, 1);
113 break;
114 case LOCK_UN:
115 res = do_unlock (h);
116 break;
117 default:
118 errno = EINVAL;
119 return -1;
120 }
121
122 /* Map Windows errors into Unix errnos. As usual MSDN fails to
123 * document the permissible error codes.
124 */
125 if (!res)
126 {
127 errno = err_win_to_posix();
128 return -1;
129 }
130
131 return 0;
132}