Commit e70212c1 e70212c14a55b8e5e55eb3ad44513fd402553026 by Sergey Poznyakoff

Fix locking of Berkeley databases.

* include/mailutils/locker.h (mu_locker_lock_mode): New proto.
* libmailutils/base/locker.c (_mu_locker_lock): Rename to
mu_locker_lock_mode.  All callers updated.
* libmu_dbm/berkeley.c (bdb_file) <locker>: New member.
(do_bdb_open): New function.  Lock the database file before opening it.
Drop support for version 2.
(_bdb_open): Rewrite as a wrapper over do_bdb_open.
* mu/dbm.c (dbm_doc): Document the "dump" subcommand.

* NEWS: Version 2.99.96
* configure.ac: Likewise.
1 parent fb53814d
GNU mailutils NEWS -- history of user-visible changes. 2011-12-31
GNU mailutils NEWS -- history of user-visible changes. 2012-02-26
Copyright (C) 2002-2012 Free Software Foundation, Inc.
See the end of file for copying conditions.
Please send mailutils bug reports to <bug-mailutils@gnu.org>.
Version 2.99.95 (Git)
Version 2.99.96 (Git)
This version is a major rewrite of GNU Mailutils. Quite a few parts
of the basic framework were rewritten from scratch, while some others
......
......@@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License along
dnl with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
AC_PREREQ(2.63)
AC_INIT([GNU Mailutils], [2.99.95], [bug-mailutils@gnu.org], [mailutils])
AC_INIT([GNU Mailutils], [2.99.96], [bug-mailutils@gnu.org], [mailutils])
AC_CONFIG_SRCDIR([libmailutils/mailbox/mailbox.c])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([gnits 1.11 dist-bzip2 dist-xz std-options silent-rules])
......
......@@ -133,6 +133,7 @@ enum mu_locker_mode
locking otherwise */
};
extern int mu_locker_lock_mode (mu_locker_t, enum mu_locker_mode);
extern int mu_locker_lock (mu_locker_t);
extern int mu_locker_touchlock (mu_locker_t);
extern int mu_locker_unlock (mu_locker_t);
......
......@@ -547,7 +547,7 @@ mu_locker_destroy (mu_locker_t *plocker)
}
int
_mu_locker_lock (mu_locker_t lock, enum mu_locker_mode mode)
mu_locker_lock_mode (mu_locker_t lock, enum mu_locker_mode mode)
{
int rc;
unsigned type;
......@@ -598,7 +598,7 @@ _mu_locker_lock (mu_locker_t lock, enum mu_locker_mode mode)
int
mu_locker_lock (mu_locker_t lock)
{
return _mu_locker_lock (lock, mu_lck_exc);
return mu_locker_lock_mode (lock, mu_lck_exc);
}
int
......
......@@ -26,6 +26,7 @@
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/stream.h>
#include <mailutils/locker.h>
#include "mudbm.h"
#if defined(WITH_BDB)
......@@ -35,6 +36,7 @@ struct bdb_file
{
DB *db;
DBC *dbc;
mu_locker_t locker;
};
static int
......@@ -59,57 +61,71 @@ _bdb_get_fd (mu_dbm_file_t db, int *pag, int *dir)
}
static int
_bdb_open (mu_dbm_file_t mdb, int flags, int mode)
{
struct bdb_file *bdb_file;
int f, rc;
DB *db;
do_bdb_open (mu_dbm_file_t mdb, int flags, int mode)
{
struct bdb_file *bdb_file = mdb->db_descr;
int f, rc, locker_flags;
enum mu_locker_mode locker_mode;
switch (flags)
{
case MU_STREAM_CREAT:
f = DB_CREATE|DB_TRUNCATE;
locker_mode = mu_lck_exc;
break;
case MU_STREAM_READ:
f = DB_RDONLY;
locker_mode = mu_lck_shr;
break;
case MU_STREAM_RDWR:
f = DB_CREATE;
locker_mode = mu_lck_exc;
break;
default:
return EINVAL;
}
#if WITH_BDB == 2
rc = db_open (db->db_name, DB_HASH, f, mode, NULL, NULL, &db);
#ifdef DB_FCNTL_LOCKING
f |= DB_FCNTL_LOCKING;
locker_flags = MU_LOCKER_KERNEL;
#else
rc = db_create (&db, NULL, 0);
if (rc != 0 || db == NULL)
return MU_ERR_FAILURE;
# if DB_VERSION_MAJOR == 3
rc = db->open (db, mdb->db_name, NULL, DB_HASH, f, mode);
# else
rc = db->open (db, NULL, mdb->db_name, NULL, DB_HASH, f, mode);
# endif
locker_flags = 0;
#endif
rc = mu_locker_create (&bdb_file->locker, mdb->db_name,
locker_flags|MU_LOCKER_RETRY);
if (rc)
return MU_ERR_FAILURE;
return rc;
bdb_file = malloc (sizeof *bdb_file);
if (!bdb_file)
rc = mu_locker_lock_mode (bdb_file->locker, locker_mode);
switch (rc)
{
db->close (db, 0);
return ENOMEM;
}
bdb_file->db = db;
bdb_file->dbc = NULL;
case 0:
break;
mdb->db_descr = bdb_file;
case EACCES:
mu_locker_destroy (&bdb_file->locker);
break;
default:
return rc;
}
rc = db_create (&bdb_file->db, NULL, 0);
if (rc != 0 || bdb_file->db == NULL)
return MU_ERR_FAILURE;
#if DB_VERSION_MAJOR == 3
rc = bdb_file->db->open (bdb_file->db, mdb->db_name, NULL, DB_HASH, f, mode);
#else
rc = bdb_file->db->open (bdb_file->db, NULL, mdb->db_name, NULL, DB_HASH,
f, mode);
#endif
if (rc)
return MU_ERR_FAILURE;
return 0;
}
......@@ -119,7 +135,13 @@ _bdb_close (mu_dbm_file_t db)
if (db->db_descr)
{
struct bdb_file *bdb_file = db->db_descr;
bdb_file->db->close (bdb_file->db, 0);
if (bdb_file->db)
bdb_file->db->close (bdb_file->db, 0);
if (bdb_file->locker)
{
mu_locker_unlock (bdb_file->locker);
mu_locker_destroy (&bdb_file->locker);
}
free (bdb_file);
db->db_descr = NULL;
}
......@@ -127,6 +149,23 @@ _bdb_close (mu_dbm_file_t db)
}
static int
_bdb_open (mu_dbm_file_t mdb, int flags, int mode)
{
int rc;
struct bdb_file *bdb_file;
bdb_file = calloc (1, sizeof *bdb_file);
if (!bdb_file)
return ENOMEM;
mdb->db_descr = bdb_file;
rc = do_bdb_open (mdb, flags, mode);
if (rc)
_bdb_close (mdb);
return rc;
}
static int
_bdb_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum *ret)
{
......
......@@ -35,6 +35,7 @@ static char dbm_doc[] = N_("mu dbm - DBM management tool\n"
"Valid COMMANDs are:\n"
"\n"
" create or load - create the database\n"
" dump - dump the database\n"
" list - list contents of the database\n"
" delete - delete specified keys from the database\n"
" add - add records to the database\n"
......