aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Downs <downsj@downsj.com>2008-11-30 07:29:12 +0000
committerJason Downs <downsj@downsj.com>2008-11-30 07:29:12 +0000
commit75e98477a3854da8e582493f4888b3dca8d257d4 (patch)
treec18accfef04030f856b9d8841c90bbcefef6a2d6
parent5a88187f15f70c5d7914469b3e39e58259f59c01 (diff)
downloadgdbm-75e98477a3854da8e582493f4888b3dca8d257d4.tar.gz
gdbm-75e98477a3854da8e582493f4888b3dca8d257d4.tar.bz2
Implement a new basic locking mechanism for GDBM. Add _gdbm_lock_file() and
_gdbm_unlock_file(), which will try to use flock(), lockf(), and fcntl() to lock the file. From ChangeLog: * configure.ac: Add test for lockf. * src/lock.c: New file, adds _gdbm_unlock_file() and _gdbm_lock_file() routines. These attempt to use flock(), lockf(), and fcntl() locking. * src/proto.h: Add new prototypes. * src/systems.h: Remove file locking macros. * src/gdbmopen.c: Rewrite locking code, use _gdbm_lock_file(). * src/gdbmclose.c, src/gdbmreorg.c: Use _gdbm_unlock_file().
-rw-r--r--ChangeLog11
-rw-r--r--autoconf.h.in3
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile.in9
-rw-r--r--src/gdbmclose.c2
-rw-r--r--src/gdbmopen.c46
-rw-r--r--src/gdbmreorg.c2
-rw-r--r--src/lock.c146
-rw-r--r--src/proto.h19
-rw-r--r--src/systems.h82
12 files changed, 204 insertions, 122 deletions
diff --git a/ChangeLog b/ChangeLog
index 80ddee1..f5fc571 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Sat Nov 29 23:22:24 PST 2008 Jason Downs (downsj@downsj.com)
+ * configure.ac: Add test for lockf.
+
+ * src/lock.c: New file, adds _gdbm_unlock_file() and
+ _gdbm_lock_file() routines. These attempt to use flock(),
+ lockf(), and fcntl() locking.
+ * src/proto.h: Add new prototypes.
+ * src/systems.h: Remove file locking macros.
+ * src/gdbmopen.c: Rewrite locking code, use _gdbm_lock_file().
+ * src/gdbmclose.c, src/gdbmreorg.c: Use _gdbm_unlock_file().
+
Sat Nov 29 21:19:32 PST 2008 Jason Downs (downsj@downsj.com)
* configure.ac: Add test for sys/termios.h
diff --git a/autoconf.h.in b/autoconf.h.in
index 1068bee..27e9850 100644
--- a/autoconf.h.in
+++ b/autoconf.h.in
@@ -27,6 +27,9 @@
/* Define to 1 if you have the `ndbm' library (-lndbm). */
#undef HAVE_LIBNDBM
+/* Define to 1 if you have the `lockf' function. */
+#undef HAVE_LOCKF
+
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
diff --git a/configure b/configure
index 7b0843d..ac9eb97 100755
--- a/configure
+++ b/configure
@@ -20035,7 +20035,8 @@ fi
-for ac_func in rename ftruncate flock fsync
+
+for ac_func in rename ftruncate flock lockf fsync
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
diff --git a/configure.ac b/configure.ac
index 453b150..594fe67 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,7 +69,7 @@ AC_CHECK_HEADERS([stdlib.h string.h sys/file.h unistd.h fcntl.h sys/types.h memo
AC_CHECK_LIB(dbm, main)
AC_CHECK_LIB(ndbm, main)
-AC_CHECK_FUNCS([rename ftruncate flock fsync])
+AC_CHECK_FUNCS([rename ftruncate flock lockf fsync])
if test x$mapped_io = xyes
then
diff --git a/src/Makefile.am b/src/Makefile.am
index 455ce65..44de71a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,6 +64,7 @@ libgdbm_la_SOURCES = \
flatfile.c\
global.c\
hash.c\
+ lock.c\
mmap.c\
update.c\
version.c
diff --git a/src/Makefile.in b/src/Makefile.in
index 5fad07f..f8907c1 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -74,7 +74,7 @@ am_libgdbm_la_OBJECTS = gdbmopen.lo gdbmdelete.lo gdbmfetch.lo \
gdbmstore.lo gdbmclose.lo gdbmreorg.lo gdbmseq.lo gdbmsync.lo \
gdbmerrno.lo gdbmexists.lo gdbmfdesc.lo gdbmsetopt.lo \
bucket.lo falloc.lo findkey.lo flatfile.lo global.lo hash.lo \
- mmap.lo update.lo version.lo
+ lock.lo mmap.lo update.lo version.lo
libgdbm_la_OBJECTS = $(am_libgdbm_la_OBJECTS)
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
@@ -96,8 +96,9 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/gdbmsetopt.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gdbmstore.Plo ./$(DEPDIR)/gdbmsync.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/global.Plo ./$(DEPDIR)/hash.Plo \
-@AMDEP_TRUE@ ./$(DEPDIR)/mmap.Plo ./$(DEPDIR)/testgdbm.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/update.Plo ./$(DEPDIR)/version.Plo
+@AMDEP_TRUE@ ./$(DEPDIR)/lock.Plo ./$(DEPDIR)/mmap.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/testgdbm.Po ./$(DEPDIR)/update.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/version.Plo
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \
@@ -261,6 +262,7 @@ libgdbm_la_SOURCES = \
flatfile.c\
global.c\
hash.c\
+ lock.c\
mmap.c\
update.c\
version.c
@@ -386,6 +388,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdbmsync.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/global.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testgdbm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update.Plo@am__quote@
diff --git a/src/gdbmclose.c b/src/gdbmclose.c
index 2eb50bf..c9ddf0f 100644
--- a/src/gdbmclose.c
+++ b/src/gdbmclose.c
@@ -41,7 +41,7 @@ gdbm_close (gdbm_file_info *dbf)
#endif
if (dbf->file_locking)
{
- UNLOCK_FILE(dbf);
+ _gdbm_unlock_file (dbf);
}
close (dbf->desc);
free (dbf->name);
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index e2838c2..9992b6f 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -159,43 +159,35 @@ gdbm_open (char *file, int block_size, int flags, int mode,
/* Get the status of the file. */
fstat (dbf->desc, &file_stat);
- /* Lock the file in the approprate way. */
- if ((flags & GDBM_OPENMASK) == GDBM_READER)
- {
- if (file_stat.st_size == 0)
- {
- close (dbf->desc);
- free (dbf->name);
- free (dbf);
- gdbm_errno = GDBM_EMPTY_DATABASE;
- return NULL;
- }
- if (dbf->file_locking)
- {
- /* Sets lock_val to 0 for success. See systems.h. */
- READLOCK_FILE(dbf);
- }
- }
- else if (dbf->file_locking)
- {
- /* Sets lock_val to 0 for success. See systems.h. */
- WRITELOCK_FILE(dbf);
- }
- if (dbf->file_locking && (lock_val != 0))
+ /* Zero-length file can't be a reader... */
+ if (((flags & GDBM_OPENMASK) == GDBM_READER) && (file_stat.st_size == 0))
{
close (dbf->desc);
free (dbf->name);
free (dbf);
- if ((flags & GDBM_OPENMASK) == GDBM_READER)
- gdbm_errno = GDBM_CANT_BE_READER;
- else
- gdbm_errno = GDBM_CANT_BE_WRITER;
+ gdbm_errno = GDBM_EMPTY_DATABASE;
return NULL;
}
/* Record the kind of user. */
dbf->read_write = (flags & GDBM_OPENMASK);
+ /* Lock the file in the appropriate way. */
+ if (dbf->file_locking)
+ {
+ if (_gdbm_lock_file (dbf) == -1)
+ {
+ close (dbf->desc);
+ free (dbf->name);
+ free (dbf);
+ if ((flags & GDBM_OPENMASK) == GDBM_READER)
+ gdbm_errno = GDBM_CANT_BE_READER;
+ else
+ gdbm_errno = GDBM_CANT_BE_WRITER;
+ return NULL;
+ }
+ }
+
/* If we do have a write lock and it was a GDBM_NEWDB, it is
now time to truncate the file. */
if (need_trunc && file_stat.st_size != 0)
diff --git a/src/gdbmreorg.c b/src/gdbmreorg.c
index fe58a66..fccffff 100644
--- a/src/gdbmreorg.c
+++ b/src/gdbmreorg.c
@@ -161,7 +161,7 @@ gdbm_reorganize (gdbm_file_info *dbf)
/* Fix up DBF to have the correct information for the new file. */
if (dbf->file_locking)
{
- UNLOCK_FILE(dbf);
+ _gdbm_unlock_file (dbf);
}
close (dbf->desc);
free (dbf->header);
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;
+}
diff --git a/src/proto.h b/src/proto.h
index 6232312..90b28ed 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -43,12 +43,16 @@ void _gdbm_fatal (gdbm_file_info *, const char *);
int _gdbm_init_cache (gdbm_file_info *, int);
/* From mmap.c */
-int _gdbm_mapped_init (gdbm_file_info *dbf);
-void _gdbm_mapped_unmap (gdbm_file_info *dbf);
-ssize_t _gdbm_mapped_read(gdbm_file_info *dbf, void *buffer, size_t len);
-ssize_t _gdbm_mapped_write(gdbm_file_info *dbf, void *buffer, size_t len);
-off_t _gdbm_mapped_lseek(gdbm_file_info *dbf, off_t offset, int whence);
-int _gdbm_mapped_sync(gdbm_file_info *dbf);
+int _gdbm_mapped_init (gdbm_file_info *);
+void _gdbm_mapped_unmap (gdbm_file_info *);
+ssize_t _gdbm_mapped_read (gdbm_file_info *, void *, size_t);
+ssize_t _gdbm_mapped_write (gdbm_file_info *, void *, size_t);
+off_t _gdbm_mapped_lseek (gdbm_file_info *, off_t, int);
+int _gdbm_mapped_sync (gdbm_file_info *);
+
+/* From lock.c */
+void _gdbm_unlock_file (gdbm_file_info *);
+int _gdbm_lock_file (gdbm_file_info *);
/* The user callable routines.... */
void gdbm_close (gdbm_file_info *);
@@ -63,3 +67,6 @@ int gdbm_exists (gdbm_file_info *, datum);
void gdbm_sync (gdbm_file_info *);
int gdbm_setopt (gdbm_file_info *, int, int *, int);
int gdbm_fdesc (gdbm_file_info *);
+int gdbm_export (gdbm_file_info *, const char *, int, int);
+int gdbm_import (gdbm_file_info *, const char *, int);
+
diff --git a/src/systems.h b/src/systems.h
index 6725471..8136e25 100644
--- a/src/systems.h
+++ b/src/systems.h
@@ -49,88 +49,6 @@
#define L_SET SEEK_SET
#endif
-/* Do we have flock? (BSD...) */
-
-#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
-
-#define UNLOCK_FILE(dbf) flock (dbf->desc, LOCK_UN)
-#define READLOCK_FILE(dbf) lock_val = flock (dbf->desc, LOCK_SH + LOCK_NB)
-#define WRITELOCK_FILE(dbf) lock_val = flock (dbf->desc, LOCK_EX + LOCK_NB)
-
-#else
-
-/* Assume it is done like System V. */
-
-#if defined(F_SETLK64) && (defined(_LARGE_FILES) || _FILE_OFFSET_BITS == 64)
-#define UNLOCK_FILE(dbf) \
- { \
- struct flock64 flock; \
- flock.l_type = F_UNLCK; \
- flock.l_whence = SEEK_SET; \
- flock.l_start = flock.l_len = 0L; \
- fcntl (dbf->desc, F_SETLK64, &flock); \
- }
-#define READLOCK_FILE(dbf) \
- { \
- struct flock64 flock; \
- flock.l_type = F_RDLCK; \
- flock.l_whence = SEEK_SET; \
- flock.l_start = flock.l_len = 0L; \
- lock_val = fcntl (dbf->desc, F_SETLK64, &flock); \
- }
-#define WRITELOCK_FILE(dbf) \
- { \
- struct flock64 flock; \
- flock.l_type = F_WRLCK; \
- flock.l_whence = SEEK_SET; \
- flock.l_start = flock.l_len = 0L; \
- lock_val = fcntl (dbf->desc, F_SETLK64, &flock); \
- }
-#else
-#define UNLOCK_FILE(dbf) \
- { \
- struct flock flock; \
- flock.l_type = F_UNLCK; \
- flock.l_whence = SEEK_SET; \
- flock.l_start = flock.l_len = 0L; \
- fcntl (dbf->desc, F_SETLK, &flock); \
- }
-#define READLOCK_FILE(dbf) \
- { \
- struct flock flock; \
- flock.l_type = F_RDLCK; \
- flock.l_whence = SEEK_SET; \
- flock.l_start = flock.l_len = 0L; \
- lock_val = fcntl (dbf->desc, F_SETLK, &flock); \
- }
-#define WRITELOCK_FILE(dbf) \
- { \
- struct flock flock; \
- flock.l_type = F_WRLCK; \
- flock.l_whence = SEEK_SET; \
- flock.l_start = flock.l_len = 0L; \
- lock_val = fcntl (dbf->desc, F_SETLK, &flock); \
- }
-#endif
-
-#endif
-
/* Default block size. Some systems do not have blocksize in their
stat record. This code uses the BSD blocksize from stat. */

Return to:

Send suggestions and report system problems to the System administrator.