diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | autoconf.h.in | 3 | ||||
-rwxr-xr-x | configure | 3 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/Makefile.in | 9 | ||||
-rw-r--r-- | src/gdbmclose.c | 2 | ||||
-rw-r--r-- | src/gdbmopen.c | 46 | ||||
-rw-r--r-- | src/gdbmreorg.c | 2 | ||||
-rw-r--r-- | src/lock.c | 146 | ||||
-rw-r--r-- | src/proto.h | 19 | ||||
-rw-r--r-- | src/systems.h | 82 |
12 files changed, 204 insertions, 122 deletions
@@ -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 @@ -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. */ |