1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/* lock.c - Implement basic file locking for GDBM. */
/* This file is part of GDBM, the GNU data base manager.
Copyright (C) 2008, 2011, 2013 Free Software Foundation, Inc.
GDBM is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GDBM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDBM. If not, see <http://www.gnu.org/licenses/>. */
/* Include system configuration before all else. */
#include "autoconf.h"
#include "gdbmdefs.h"
#include <errno.h>
#if HAVE_FLOCK
# ifndef LOCK_SH
# define LOCK_SH 1
# endif
# ifndef LOCK_EX
# define LOCK_EX 2
# endif
# ifndef LOCK_NB
# define LOCK_NB 4
# endif
# ifndef LOCK_UN
# define LOCK_UN 8
# endif
#endif
#if defined(F_SETLK) && defined(F_RDLCK) && defined(F_WRLCK)
# define HAVE_FCNTL_LOCK 1
#else
# define HAVE_FCNTL_LOCK 0
#endif
#if 0
int
gdbm_locked (GDBM_FILE dbf)
{
return (dbf->lock_type != LOCKING_NONE);
}
#endif
void
_gdbm_unlock_file (GDBM_FILE dbf)
{
#if HAVE_FCNTL_LOCK
struct flock fl;
#endif
switch (dbf->lock_type)
{
case LOCKING_FLOCK:
#if HAVE_FLOCK
flock (dbf->desc, LOCK_UN);
#endif
break;
case LOCKING_LOCKF:
#if HAVE_LOCKF
lockf (dbf->desc, F_ULOCK, (off_t)0L);
#endif
break;
case LOCKING_FCNTL:
#if HAVE_FCNTL_LOCK
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = fl.l_len = (off_t)0L;
fcntl (dbf->desc, F_SETLK, &fl);
#endif
break;
case LOCKING_NONE:
break;
}
dbf->lock_type = LOCKING_NONE;
}
/* Try each supported locking mechanism. */
int
_gdbm_lock_file (GDBM_FILE dbf)
{
#if HAVE_FCNTL_LOCK
struct flock fl;
#endif
int lock_val = -1;
#if HAVE_FLOCK
if (dbf->read_write == GDBM_READER)
lock_val = flock (dbf->desc, LOCK_SH + LOCK_NB);
else
lock_val = flock (dbf->desc, LOCK_EX + LOCK_NB);
if ((lock_val == -1) && (errno == EWOULDBLOCK))
{
dbf->lock_type = LOCKING_NONE;
return lock_val;
}
else if (lock_val != -1)
{
dbf->lock_type = LOCKING_FLOCK;
return lock_val;
}
#endif
#if HAVE_LOCKF
/* Mask doesn't matter for lockf. */
lock_val = lockf (dbf->desc, F_LOCK, (off_t)0L);
if ((lock_val == -1) && (errno == EDEADLK))
{
dbf->lock_type = LOCKING_NONE;
return lock_val;
}
else if (lock_val != -1)
{
dbf->lock_type = LOCKING_LOCKF;
return lock_val;
}
#endif
#if HAVE_FCNTL_LOCK
/* If we're still here, try fcntl. */
if (dbf->read_write == GDBM_READER)
fl.l_type = F_RDLCK;
else
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = fl.l_len = (off_t)0L;
lock_val = fcntl (dbf->desc, F_SETLK, &fl);
if (lock_val != -1)
dbf->lock_type = LOCKING_FCNTL;
#endif
if (lock_val == -1)
dbf->lock_type = LOCKING_NONE;
return lock_val;
}
|