aboutsummaryrefslogtreecommitdiff
path: root/lib/mf-dbm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mf-dbm.c')
-rw-r--r--lib/mf-dbm.c658
1 files changed, 0 insertions, 658 deletions
diff --git a/lib/mf-dbm.c b/lib/mf-dbm.c
deleted file mode 100644
index a42c96ff..00000000
--- a/lib/mf-dbm.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/* This file is part of Mailfromd.
- Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006, 2007, 2008, 2009,
- 2010 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, see <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#include <errno.h>
-#include <mailutils/error.h>
-#include <mailutils/errno.h>
-#include <mf-dbm.h>
-#include "libmf.h"
-
-#ifndef MU_ERR_EXISTS
-# define MU_ERR_EXISTS EEXIST
-#endif
-
-size_t lock_retry_count_option = 3;
-time_t lock_retry_timeout_option = 1;
-static mu_debug_handle_t debug_handle;
-
-void
-libdbm_init()
-{
- debug_handle = mu_debug_register_category("dbm");
-}
-
-int
-mf_fcheck_perm(int fd, int mode)
-{
- struct stat st;
-
- if (fstat (fd, &st) == -1) {
- if (errno == ENOENT)
- return ENOENT;
- else
- return MU_ERR_FAILURE;
- }
- if ((st.st_mode & 0777) != mode)
- return errno = EACCES;
- return 0;
-}
-
-int
-mf_check_perm(const char *name, int mode)
-{
- struct stat st;
-
- if (mode == 0)
- return 0;
- if (stat(name, &st) == -1) {
- if (errno == ENOENT)
- return ENOENT;
- else
- return MU_ERR_FAILURE;
- }
- if ((st.st_mode & 0777) != mode)
- return errno = EACCES;
-
- return 0;
-}
-
-#if defined(WITH_GDBM)
-
-int
-mf_dbm_open(char *name, MF_DBM_FILE *db, int flags, int mode, int *ro)
-{
- int rc;
- int f;
- size_t i;
- GDBM_FILE gdbm;
-
- rc = mf_check_perm(name, mode);
- if (rc && rc != ENOENT)
- return MU_ERR_UNSAFE_PERMS;
-
- if (ro)
- *ro = 0;
-
- switch (flags) {
- case MU_STREAM_CREAT:
- f = GDBM_NEWDB;
- break;
-
- case MU_STREAM_READ:
- f = GDBM_READER;
- break;
-
- case MU_STREAM_RDWR:
- f = GDBM_WRCREAT;
- break;
-
- default:
- errno = EINVAL;
- return 1;
- }
-
- for (i = 0; i < lock_retry_count_option; i++) {
- gdbm = gdbm_open(name, 512, f, mode, NULL);
- if (gdbm || errno != EAGAIN)
- break;
- sleep(lock_retry_timeout_option);
- }
-
- if (!gdbm) {
- if (ro) {
- gdbm = gdbm_open(name, 512, GDBM_READER, mode, NULL);
- if (gdbm)
- *ro = 1;
- }
- }
-
- rc = (gdbm == NULL) ? MU_ERR_FAILURE : 0;
-
- if (rc == 0) {
- db->db = gdbm;
- db->name = strdup(name);
- }
-
- return rc;
-}
-
-int
-mf_dbm_close(MF_DBM_FILE *db)
-{
- gdbm_close(db->db);
- free(db->name);
- return 0;
-}
-
-int
-mf_dbm_fetch(MF_DBM_FILE *db, MF_DBM_DATUM key, MF_DBM_DATUM *ret)
-{
- *ret = gdbm_fetch(db->db, key);
- if (ret->dptr == NULL)
- return MU_ERR_NOENT;
- return 0;
-}
-
-int
-mf_dbm_delete(MF_DBM_FILE *db, MF_DBM_DATUM key)
-{
- return gdbm_delete(db->db, key) ? MU_ERR_FAILURE : 0;
-}
-
-int
-mf_dbm_insert(MF_DBM_FILE *db, MF_DBM_DATUM key, MF_DBM_DATUM contents, int replace)
-{
- switch (gdbm_store(db->db, key, contents,
- replace ? GDBM_REPLACE : GDBM_INSERT)) {
- case -1:
- return MU_ERR_FAILURE;
-
- case 0:
- return 0;
-
- case 1:
- return MU_ERR_EXISTS;
- }
- return MU_ERR_FAILURE;
-}
-
-int
-mf_dbm_firstkey(MF_DBM_FILE *db, MF_DBM_DATUM *pkey)
-{
- *pkey = gdbm_firstkey(db->db);
- return (pkey->dptr == NULL) ? MU_ERR_NOENT : 0;
-}
-
-int
-mf_dbm_nextkey(MF_DBM_FILE *db, MF_DBM_DATUM prevkey, MF_DBM_DATUM *pkey)
-{
- *pkey = gdbm_nextkey(db->db, prevkey);
- return (pkey->dptr == NULL) ? MU_ERR_NOENT : 0;
-}
-
-void
-mf_dbm_datum_free(MF_DBM_DATUM *datum)
-{
- void *ptr = MF_DATUM_PTR(*datum);
- if (ptr)
- free(ptr);
- MF_DATUM_PTR(*datum) = 0;
-}
-
-const char *
-mf_dbm_strerror()
-{
- if (errno == MU_ERR_UNSAFE_PERMS)
- return mu_strerror(errno);
- return gdbm_strerror(gdbm_errno);
-}
-
-#elif defined(WITH_BDB)
-
-int mf_dbm_errno;
-
-static int
-try_lock(int fd, int type, struct flock *fl)
-{
- int i, rc;
-
- for (i = 0; i < lock_retry_count_option; i++) {
- alarm(lock_retry_timeout_option);
- rc = fcntl(fd, F_SETLKW, fl);
- alarm(0);
- if (rc == 0)
- return 0;
- }
- return errno;
-}
-
-static int
-lock_file(const char *name, int fd, int type)
-{
- int rc = 0;
- struct flock fl;
-
- if (type == F_UNLCK)
- mu_debug(debug_handle, MU_DEBUG_TRACE1,
- ("unlocking %s", name));
- else
- mu_debug(debug_handle, MU_DEBUG_TRACE1,
- ("locking %s for %s",
- name,
- (type == F_RDLCK) ? "reading" : "writing"));
-
- memset(&fl, 0, sizeof fl);
- fl.l_whence = SEEK_SET;
- fl.l_type = type;
-
- rc = try_lock(fd, type, &fl);
- if (!rc)
- return 0;
-
- fl.l_pid = 0;
- if (fcntl(fd, F_GETLK, &fl) != -1) {
- if (fl.l_type == F_UNLCK) {
- memset (&fl, 0, sizeof fl);
- fl.l_whence = SEEK_SET;
- fl.l_type = type;
- rc = try_lock (fd, type, &fl);
- if (rc)
- mu_error(_("%s: cannot acquire lock: %s"),
- name, mu_strerror (rc));
- } else if (fl.l_pid) {
- if (kill(fl.l_pid, 0) == 0)
- mu_error(_("%s is locked (%d) "
- "by process ID %lu"),
- name,
- fl.l_type,
- (unsigned long) fl.l_pid);
- else if (errno == ESRCH) {
- mu_error (_("%s is locked by "
- "nonexisting process "
- "ID %lu; "
- "retrying"),
- name,
- (unsigned long) fl.l_pid);
- if (unlink(name))
- mu_error (_("cannot unlink "
- "file %s: %s"),
- name,
- mu_strerror(errno));
- else {
- rc = try_lock(fd, type, &fl);
- if (rc)
- mu_error (_("%s: cannot acquire lock: %s"),
- name,
- mu_strerror(rc));
- }
- } else
- mu_error (_("%s seems locked "
- "by process ID %lu, "
- "but its validity cannot "
- "be verified: %s"),
- name,
- (unsigned long) fl.l_pid,
- mu_strerror(errno));
- } else
- mu_error (_("%s: cannot acquire lock: %s"),
- name, mu_strerror(rc));
- } else
- mu_error (_("cannot obtain locker info for %s: %s"),
- name, mu_strerror (errno));
- return rc;
-}
-
-#ifndef DB_FCNTL_LOCKING
-#define LOCK_SUFFIX ".lock"
-
-static int
-make_lockfile(char *name, int lktype, int *pfd, char **plockname)
-{
- int rc;
- int fd;
- char *p, *lockname;
- size_t size, namesize;
-
- size = strlen(mailfromd_state_dir);
- if (strlen(name) > size
- && memcmp(name, mailfromd_state_dir, size) == 0
- && name[size] == '/')
- p = name + size + 1;
- else
- p = name;
-
- namesize = size + 1 + strlen(p) + sizeof LOCK_SUFFIX;
- lockname = malloc(namesize);
- if (!lockname)
- return errno;
- strcpy(lockname, mailfromd_state_dir);
- strcat(lockname, "/");
- strcat(lockname, p);
- strcat(lockname, LOCK_SUFFIX);
- for (p = lockname + size + 1; *p; p++)
- if (*p == '/')
- *p = '-';
-
- fd = open(lockname, O_CREAT|O_RDWR, 0600);
- if (fd == -1) {
- free(lockname);
- return errno;
- }
-
- rc = lock_file(lockname, fd, lktype);
- if (rc) {
- free(lockname);
- return rc;
- }
-
- *plockname = lockname;
- *pfd = fd;
- return 0;
-}
-#endif
-
-static void
-mf_dbm_errcall_fcn
-#if DB_VERSION_MAJOR == 3
- (const char *errpfx, char *msg)
-#elif DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 2
- (const char *errpfx, char *msg)
-#else
- (const DB_ENV *env, const char *errpfx, const char *msg)
-#endif
-{
- if (errpfx)
- mu_error("%s: %s: %s", errpfx, _("Berkeley DB error"), msg);
- else
- mu_error("%s: %s", _("Berkeley DB error"), msg);
-}
-
-#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
-# define DB_TXN_NULL NULL,
-#else
-# define DB_TXN_NULL
-#endif
-
-int
-mf_dbm_open(char *name, MF_DBM_FILE *dbm, int flags, int mode, int *ro)
-{
- int f = 0;
- DB *db = NULL;
- int oflags;
-# define LKTYPE(o) (((o) & O_RDWR) ? F_WRLCK : F_RDLCK)
-
- mu_debug(debug_handle, MU_DEBUG_TRACE2, ("opening database %s", name));
- mf_dbm_errno = mf_check_perm(name, mode);
-
- if (mf_dbm_errno && mf_dbm_errno != ENOENT)
- return EACCES;
-
- if (ro)
- *ro = 0;
-
- switch (flags) {
- case MU_STREAM_CREAT:
- f = DB_CREATE | DB_TRUNCATE;
- oflags = O_CREAT | O_TRUNC | O_RDWR;
- break;
-
- case MU_STREAM_READ:
- if (mf_dbm_errno == ENOENT)
- return MU_ERR_FAILURE;
- f = DB_RDONLY;
- oflags = O_RDONLY;
- break;
-
- case MU_STREAM_RDWR:
- f = DB_CREATE;
- oflags = O_CREAT | O_RDWR;
- if (mf_dbm_errno == ENOENT)
- f |= DB_TRUNCATE;
- break;
-
- default:
- mf_dbm_errno = EINVAL;
- return MU_ERR_FAILURE;
- }
-
- dbm->lockname = NULL;
-#ifdef DB_FCNTL_LOCKING
- f |= DB_FCNTL_LOCKING;
-
- dbm->lockfd = open(name, oflags, mode);
- if (dbm->lockfd == -1) {
- mf_dbm_errno = errno;
- return MU_ERR_FAILURE;
- }
- mf_dbm_errno = lock_file(name, dbm->lockfd, LKTYPE(oflags));
- if (mf_dbm_errno) {
- mu_error(_("cannot lock file %s: %s"),
- name, mu_strerror(mf_dbm_errno));
- close(dbm->lockfd);
- return MU_ERR_FAILURE;
- }
-#else
- mf_dbm_errno = make_lockfile(name, LKTYPE(oflags), &dbm->lockfd,
- &dbm->lockname);
- if (mf_dbm_errno) {
- mu_error(_("cannot lock file %s: %s"),
- name, mu_strerror(mf_dbm_errno));
- return MU_ERR_FAILURE;
- }
-#endif
-
-#if DB_VERSION_MAJOR == 2
- mf_dbm_errno = db_open(name, DB_HASH, f, mode, NULL, NULL, &db);
-#else
- mf_dbm_errno = db_create(&db, NULL, 0);
- if (mf_dbm_errno != 0 || db == NULL)
- return MU_ERR_FAILURE;
-# if DB_VERSION_MAJOR == 3
- mf_dbm_errno = db->open(db, name, NULL, DB_HASH, f, mode);
-# else
- mf_dbm_errno = db->open(db, DB_TXN_NULL name, NULL, DB_HASH, f, mode);
-# endif
-#endif
- if (mf_dbm_errno) {
- if (dbm->lockname) {
- unlink(dbm->lockname);
- free(dbm->lockname);
- }
- close(dbm->lockfd);
- return MU_ERR_FAILURE;
- }
-
- db->sync(db, 0);
-
-#if DB_VERSION_MAJOR > 2
- if (mu_debug_level_p(debug_handle, MU_DEBUG_TRACE0))
- db->set_errcall (db, mf_dbm_errcall_fcn);
-#endif
-
- dbm->name = strdup(name);
- dbm->db = db;
- dbm->dbc = NULL;
-
- return 0;
-}
-
-int
-mf_dbm_close(MF_DBM_FILE *db)
-{
- mu_debug(debug_handle, MU_DEBUG_TRACE2,
- ("closing database %s", db->name));
- if (db->dbc) {
- mf_dbm_errno = db->dbc->c_close(db->dbc);
- db->dbc = NULL;
- if (mf_dbm_errno)
- return MU_ERR_FAILURE;
- }
-
- db->db->sync(db->db, 0);
- mf_dbm_errno = db->db->close(db->db, 0);
- if (db->lockname) {
- mu_debug(debug_handle, MU_DEBUG_TRACE2,
- ("removing lock file %s", db->lockname));
- unlink(db->lockname);
- free(db->lockname);
- }
- close(db->lockfd);
-
- free(db->name);
- return (mf_dbm_errno == 0) ? 0 : MU_ERR_FAILURE;
-}
-
-int
-mf_dbm_fetch(MF_DBM_FILE *db, MF_DBM_DATUM key, MF_DBM_DATUM *ret)
-{
- mf_dbm_errno = db->db->get(db->db, NULL, &key, ret, 0);
- switch (mf_dbm_errno) {
- case 0:
- return 0;
-
- case DB_NOTFOUND:
- return MU_ERR_NOENT;
-
- default:
- return MU_ERR_FAILURE;
- }
-}
-
-int
-mf_dbm_delete(MF_DBM_FILE *dbm, MF_DBM_DATUM key)
-{
- mf_dbm_errno = dbm->db->del(dbm->db, NULL, &key, 0);
- return mf_dbm_errno ? MU_ERR_FAILURE : 0;
-}
-
-int
-mf_dbm_insert(MF_DBM_FILE *dbm, MF_DBM_DATUM key, MF_DBM_DATUM contents, int replace)
-{
- int flags = replace ? 0 : DB_NOOVERWRITE;
- int rc = 0;
-
- mf_dbm_errno = dbm->db->put(dbm->db, NULL, &key, &contents, flags);
- switch (mf_dbm_errno) {
- case 0:
- break;
-
- case DB_KEYEXIST:
- rc = MU_ERR_EXISTS;
- break;
-
- default:
- rc = MU_ERR_FAILURE;
- }
- return rc;
-}
-
-int
-mf_dbm_firstkey(MF_DBM_FILE *db, MF_DBM_DATUM *pkey)
-{
- DBT data;
-
- memset(pkey, 0, sizeof *pkey);
- memset(&data, 0, sizeof data);
-
- if (!db->dbc) {
- mf_dbm_errno = db->db->cursor(db->db, NULL, &db->dbc
- BDB2_CURSOR_LASTARG);
- if (mf_dbm_errno)
- return MU_ERR_FAILURE;
- }
-
- mf_dbm_errno = db->dbc->c_get(db->dbc, pkey, &data, DB_FIRST);
- switch (mf_dbm_errno) {
- case 0:
- return 0;
-
- case DB_NOTFOUND:
- return MU_ERR_NOENT;
-
- default:
- return MU_ERR_FAILURE;
- }
-}
-
-int
-mf_dbm_nextkey(MF_DBM_FILE *db, MF_DBM_DATUM prevkey /*unused*/,
- MF_DBM_DATUM *pkey)
-{
- DBT data;
-
- memset(pkey, 0, sizeof *pkey);
- memset(&data, 0, sizeof data);
-
- if (!db->dbc) {
- mf_dbm_errno = EINVAL;
- return MU_ERR_FAILURE;
- }
-
- mf_dbm_errno = db->dbc->c_get(db->dbc, pkey, &data, DB_NEXT);
-
- switch (mf_dbm_errno) {
- case 0:
- return 0;
-
- case DB_NOTFOUND:
- return MU_ERR_NOENT;
-
- default:
- return MU_ERR_FAILURE;
- }
-}
-
-void
-mf_dbm_datum_free(MF_DBM_DATUM *datum)
-{
- /* empty */
-}
-
-const char *
-mf_dbm_strerror()
-{
-#if DB_VERSION_MAJOR == 2
- switch (mf_dbm_errno) {
- case DB_INCOMPLETE:
- return "Sync didn't finish";
-
- case DB_KEYEMPTY:
- return "The key/data pair was deleted or "
- "was never created by the user";
- break;
-
- case DB_KEYEXIST:
- return "The key/data pair already exists";
-
- case DB_LOCK_DEADLOCK:
- return "Locker killed to resolve deadlock";
-
- case DB_LOCK_NOTGRANTED:
- return "Lock unavailable, no-wait set";
-
- case DB_LOCK_NOTHELD:
- return "Lock not held by locker";
-
- case DB_NOTFOUND:
- return "Key/data pair not found (EOF)";
-
- default:
- return mu_strerror(mf_dbm_errno);
- }
-#else
- if (mf_dbm_errno < 0)
- return db_strerror(mf_dbm_errno);
- else
- return mu_strerror(mf_dbm_errno);
-#endif
-}
-
-#endif

Return to:

Send suggestions and report system problems to the System administrator.