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