aboutsummaryrefslogtreecommitdiff
path: root/src/lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lock.c')
-rw-r--r--src/lock.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/lock.c b/src/lock.c
new file mode 100644
index 0000000..08ca168
--- /dev/null
+++ b/src/lock.c
@@ -0,0 +1,146 @@
+/* lock.c - Implement basic file locking for GDBM. */
+
+/* This file is part of GDBM, the GNU data base manager.
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Include system configuration before all else. */
+#include "autoconf.h"
+
+#include "gdbmdefs.h"
+#include "gdbmerrno.h"
+#include "extern.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_SETLK64)) && defined(F_RDLCK) && defined(F_WRLCK)
+#define HAVE_FCNTL_LOCK 1
+#else
+#define HAVE_FCNTL_LOCK 0
+#endif
+
+#if defined(F_SETLK64) && (defined(_LARGE_FILES) || _FILE_OFFSET_BITS == 64)
+#define _FLOCK flock64
+#define _SETLK F_SETLK64
+#else
+#define _FLOCK flock
+#define _SETLK F_SETLK
+#endif
+
+#define LOCKING_NONE 0
+#define LOCKING_FLOCK 1
+#define LOCKING_LOCKF 2
+#define LOCKING_FCNTL 3
+
+static int _gdbm_lock_type = LOCKING_NONE;
+
+void
+_gdbm_unlock_file (gdbm_file_info *dbf)
+{
+#if HAVE_FCNTL_LOCK
+ struct _FLOCK flock;
+#endif
+
+ switch (_gdbm_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
+ flock.l_type = F_UNLCK;
+ flock.l_whence = SEEK_SET;
+ flock.l_start = flock.l_len = (off_t)0L;
+ fcntl (dbf->desc, _SETLK, &flock);
+#endif
+ break;
+ }
+}
+
+/* Try each supported locking mechanism. */
+int
+_gdbm_lock_file (gdbm_file_info *dbf)
+{
+#if HAVE_FCNTL_LOCK
+ struct _FLOCK flock;
+#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)
+ {
+ _gdbm_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)
+ {
+ _gdbm_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)
+ flock.l_type = F_RDLCK;
+ else
+ flock.l_type = F_WRLCK;
+ flock.l_whence = SEEK_SET;
+ flock.l_start = flock.l_len = (off_t)0L;
+ lock_val = fcntl (dbf->desc, _SETLK, &flock);
+ if (lock_val != -1)
+ _gdbm_lock_type = LOCKING_FCNTL;
+#endif
+
+ if (lock_val == -1)
+ _gdbm_lock_type = LOCKING_NONE;
+ return lock_val;
+}

Return to:

Send suggestions and report system problems to the System administrator.