summaryrefslogtreecommitdiff
path: root/libsmdb
diff options
context:
space:
mode:
authorGregory Neil Shapiro <gshapiro@FreeBSD.org>2020-07-14 21:40:53 +0000
committerGregory Neil Shapiro <gshapiro@FreeBSD.org>2020-07-14 21:40:53 +0000
commitcee0d44ab388e12fbd62fdb134d295c58901148a (patch)
treefbe464b241337077b941be7126ad3f3f78b19f7f /libsmdb
parent1c3e417caf2d11608f10043b7e70b6e7ed8711ff (diff)
Diffstat (limited to 'libsmdb')
-rw-r--r--libsmdb/Makefile2
-rw-r--r--libsmdb/Makefile.m42
-rw-r--r--libsmdb/smcdb.c575
-rw-r--r--libsmdb/smdb.c181
-rw-r--r--libsmdb/smdb1.c16
-rw-r--r--libsmdb/smdb2.c107
-rw-r--r--libsmdb/smndbm.c1
7 files changed, 753 insertions, 131 deletions
diff --git a/libsmdb/Makefile b/libsmdb/Makefile
index 13c8af07a52ca..ce0e752abc0a0 100644
--- a/libsmdb/Makefile
+++ b/libsmdb/Makefile
@@ -8,6 +8,8 @@ all: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
clean: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
+check: FRC
+ $(SHELL) $(BUILD) $(OPTIONS) $@
install: FRC
$(SHELL) $(BUILD) $(OPTIONS) $@
diff --git a/libsmdb/Makefile.m4 b/libsmdb/Makefile.m4
index dfd62fa6a37ea..69299e53fce04 100644
--- a/libsmdb/Makefile.m4
+++ b/libsmdb/Makefile.m4
@@ -8,7 +8,7 @@ PREPENDDEF(`confENVDEF', `confMAPDEF')
PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ')
bldPRODUCT_START(`library', `libsmdb')
-define(`bldSOURCES', `smdb.c smdb1.c smdb2.c smndbm.c ')
+define(`bldSOURCES', `smdb.c smdb1.c smdb2.c smndbm.c smcdb.c ')
APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL')
bldPRODUCT_END
diff --git a/libsmdb/smcdb.c b/libsmdb/smcdb.c
new file mode 100644
index 0000000000000..84c1a9e1f90cd
--- /dev/null
+++ b/libsmdb/smcdb.c
@@ -0,0 +1,575 @@
+/*
+** Copyright (c) 2018 Proofpoint, Inc. and its suppliers.
+** All rights reserved.
+**
+** By using this file, you agree to the terms and conditions set
+** forth in the LICENSE file which can be found at the top level of
+** the sendmail distribution.
+*/
+
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: smcdb.c,v 8.55 2013-11-22 20:51:49 ca Exp $")
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sendmail/sendmail.h>
+#include <libsmdb/smdb.h>
+
+#if CDB
+#include <assert.h>
+#include <cdb.h>
+
+typedef struct cdb cdb_map_T, *cdb_map_P;
+typedef struct cdb_make cdb_make_T, *cdb_make_P;
+typedef union sm_cdbs_U sm_cdbs_T, *sm_cdbs_P;
+union sm_cdbs_U
+{
+ cdb_map_T cdbs_cdb_rd;
+ cdb_make_T cdbs_cdb_wr;
+};
+
+struct smdb_cdb_database
+{
+ sm_cdbs_T cdbmap_map;
+ int cdbmap_fd;
+ int smcdb_lock_fd;
+ bool cdbmap_create;
+ unsigned smcdb_pos;
+ int smcdb_n;
+};
+typedef struct smdb_cdb_database SMDB_CDB_DATABASE;
+
+/* static int smdb_type_to_cdb_type __P((SMDB_DBTYPE type)); */
+static int cdb_error_to_smdb __P((int error));
+static SMDB_CDB_DATABASE * smcdb_malloc_database __P((void));
+static int smcdb_close __P((SMDB_DATABASE *database));
+static int smcdb_del __P((SMDB_DATABASE *database, SMDB_DBENT *key, unsigned int flags));
+static int smcdb_fd __P((SMDB_DATABASE *database, int *fd));
+static int smcdb_lockfd __P((SMDB_DATABASE *database));
+static int smcdb_get __P((SMDB_DATABASE *database, SMDB_DBENT *key, SMDB_DBENT *data, unsigned int flags));
+static int smcdb_put __P((SMDB_DATABASE *database, SMDB_DBENT *key, SMDB_DBENT *data, unsigned int flags));
+static int smcdb_set_owner __P((SMDB_DATABASE *database, uid_t uid, gid_t gid));
+static int smcdb_sync __P((SMDB_DATABASE *database, unsigned int flags));
+static int smcdb_cursor_close __P((SMDB_CURSOR *cursor));
+static int smcdb_cursor_del __P((SMDB_CURSOR *cursor, SMDB_FLAG flags));
+static int smcdb_cursor_get __P((SMDB_CURSOR *cursor, SMDB_DBENT *key, SMDB_DBENT *value, SMDB_FLAG flags));
+static int smcdb_cursor_put __P((SMDB_CURSOR *cursor, SMDB_DBENT *key, SMDB_DBENT *value, SMDB_FLAG flags));
+static int smcdb_cursor __P((SMDB_DATABASE *database, SMDB_CURSOR **cursor, SMDB_FLAG flags));
+
+/*
+** SMDB_TYPE_TO_CDB_TYPE -- Translates smdb database type to cdb type.
+**
+** Parameters:
+** type -- The type to translate.
+**
+** Returns:
+** The CDB type that corresponsds to the passed in SMDB type.
+** Returns -1 if there is no equivalent type.
+**
+*/
+
+#if 0
+static int
+smdb_type_to_cdb_type(type)
+ SMDB_DBTYPE type;
+{
+ return 0; /* XXX */
+}
+#endif
+
+/*
+** CDB_ERROR_TO_SMDB -- Translates cdb errors to smdbe errors
+**
+** Parameters:
+** error -- The error to translate.
+**
+** Returns:
+** The SMDBE error corresponding to the cdb error.
+** If we don't have a corresponding error, it returns error.
+**
+*/
+
+static int
+cdb_error_to_smdb(error)
+ int error;
+{
+ int result;
+
+ switch (error)
+ {
+ case 0:
+ result = SMDBE_OK;
+ break;
+
+ default:
+ result = error;
+ }
+ return result;
+}
+
+SMDB_CDB_DATABASE *
+smcdb_malloc_database()
+{
+ SMDB_CDB_DATABASE *cdb;
+
+ cdb = (SMDB_CDB_DATABASE *) malloc(sizeof(SMDB_CDB_DATABASE));
+ if (cdb != NULL)
+ cdb->smcdb_lock_fd = -1;
+
+ return cdb;
+}
+
+static int
+smcdb_close(database)
+ SMDB_DATABASE *database;
+{
+ int result, fd;
+ SMDB_CDB_DATABASE *sm_cdbmap = (SMDB_CDB_DATABASE *) database->smdb_impl;
+
+ if (NULL == sm_cdbmap)
+ return -1;
+ result = 0;
+ if (sm_cdbmap->cdbmap_create)
+ result = cdb_make_finish(&sm_cdbmap->cdbmap_map.cdbs_cdb_wr);
+
+ fd = sm_cdbmap->cdbmap_fd;
+ if (fd >= 0)
+ {
+ close(fd);
+ sm_cdbmap->cdbmap_fd = -1;
+ }
+
+ free(sm_cdbmap);
+ database->smdb_impl = NULL;
+
+ return result;
+}
+
+static int
+smcdb_del(database, key, flags)
+ SMDB_DATABASE *database;
+ SMDB_DBENT *key;
+ unsigned int flags;
+{
+ SMDB_CDB_DATABASE *sm_cdbmap = (SMDB_CDB_DATABASE *) database->smdb_impl;
+
+ assert(sm_cdbmap != NULL);
+ return -1;
+}
+
+static int
+smcdb_fd(database, fd)
+ SMDB_DATABASE *database;
+ int *fd;
+{
+ SMDB_CDB_DATABASE *sm_cdbmap = (SMDB_CDB_DATABASE *) database->smdb_impl;
+ return sm_cdbmap->cdbmap_fd;
+}
+
+static int
+smcdb_lockfd(database)
+ SMDB_DATABASE *database;
+{
+ SMDB_CDB_DATABASE *sm_cdbmap = (SMDB_CDB_DATABASE *) database->smdb_impl;
+
+ return sm_cdbmap->smcdb_lock_fd;
+}
+
+/*
+** allocate/free: who does it: caller or callee?
+** If this code does it: the "last" entry will leak.
+*/
+
+#define DBEALLOC(dbe, l) \
+ do \
+ { \
+ if ((dbe)->size > 0 && l > (dbe)->size) \
+ { \
+ free((dbe)->data); \
+ (dbe)->size = 0; \
+ } \
+ if ((dbe)->size == 0) \
+ { \
+ (dbe)->data = malloc(l); \
+ if ((dbe)->data == NULL) \
+ return SMDBE_MALLOC; \
+ (dbe)->size = l; \
+ } \
+ if (l > (dbe)->size) \
+ return SMDBE_MALLOC; /* XXX bogus */ \
+ } while (0)
+
+
+static int
+smcdb_get(database, key, data, flags)
+ SMDB_DATABASE *database;
+ SMDB_DBENT *key;
+ SMDB_DBENT *data;
+ unsigned int flags;
+{
+ SMDB_CDB_DATABASE *sm_cdbmap = (SMDB_CDB_DATABASE *) database->smdb_impl;
+ size_t l;
+ int ret;
+
+ ret = SM_SUCCESS;
+
+ if (NULL == sm_cdbmap )
+ return -1;
+ /* SM_ASSERT(!sm_cdbmap->cdbmap_create); */
+
+ /* need to lock access? single threaded access! */
+ ret = cdb_find(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd,
+ key->data, key->size);
+ if (ret > 0)
+ {
+ l = cdb_datalen(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd);
+ DBEALLOC(data, l);
+ ret = cdb_read(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd,
+ data->data, l,
+ cdb_datapos(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd));
+ if (ret < 0)
+ ret = -1;
+ else
+ {
+ data->size = l;
+ ret = SM_SUCCESS;
+ }
+ }
+ else
+ ret = -1;
+
+ return ret;
+}
+
+static int
+smcdb_put(database, key, data, flags)
+ SMDB_DATABASE *database;
+ SMDB_DBENT *key;
+ SMDB_DBENT *data;
+ unsigned int flags;
+{
+ int r, cdb_flags;
+ SMDB_CDB_DATABASE *sm_cdbmap = (SMDB_CDB_DATABASE *) database->smdb_impl;
+
+ assert(sm_cdbmap != NULL);
+ if (bitset(SMDBF_NO_OVERWRITE, flags))
+ cdb_flags = CDB_PUT_INSERT;
+ else
+ cdb_flags = CDB_PUT_REPLACE;
+
+ r = cdb_make_put(&sm_cdbmap->cdbmap_map.cdbs_cdb_wr,
+ key->data, key->size, data->data, data->size,
+ cdb_flags);
+ if (r > 0)
+ {
+ if (bitset(SMDBF_NO_OVERWRITE, flags))
+ return SMDBE_DUPLICATE;
+ else
+ return SMDBE_OK;
+ }
+ return r;
+}
+
+
+static int
+smcdb_set_owner(database, uid, gid)
+ SMDB_DATABASE *database;
+ uid_t uid;
+ gid_t gid;
+{
+# if HASFCHOWN
+ int fd;
+ int result;
+ SMDB_CDB_DATABASE *sm_cdbmap = (SMDB_CDB_DATABASE *) database->smdb_impl;
+
+ assert(sm_cdbmap != NULL);
+ fd = sm_cdbmap->cdbmap_fd;
+ if (fd >= 0)
+ {
+ result = fchown(fd, uid, gid);
+ if (result < 0)
+ return errno;
+ }
+# endif /* HASFCHOWN */
+
+ return SMDBE_OK;
+}
+
+static int
+smcdb_sync(database, flags)
+ SMDB_DATABASE *database;
+ unsigned int flags;
+{
+ return 0;
+}
+
+static int
+smcdb_cursor_close(cursor)
+ SMDB_CURSOR *cursor;
+{
+ int ret;
+
+ ret = SMDBE_OK;
+ if (cursor != NULL)
+ free(cursor);
+ return ret;
+}
+
+static int
+smcdb_cursor_del(cursor, flags)
+ SMDB_CURSOR *cursor;
+ SMDB_FLAG flags;
+{
+ return -1;
+}
+
+static int
+smcdb_cursor_get(cursor, key, value, flags)
+ SMDB_CURSOR *cursor;
+ SMDB_DBENT *key;
+ SMDB_DBENT *value;
+ SMDB_FLAG flags;
+{
+ SMDB_CDB_DATABASE *sm_cdbmap;
+ size_t l;
+ int ret;
+
+ ret = SMDBE_OK;
+ sm_cdbmap = cursor->smdbc_impl;
+ ret = cdb_seqnext(&sm_cdbmap->smcdb_pos, &sm_cdbmap->cdbmap_map.cdbs_cdb_rd);
+ if (ret == 0)
+ return SMDBE_LAST_ENTRY;
+ if (ret < 0)
+ return SMDBE_IO_ERROR;
+
+ l = cdb_keylen(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd);
+ DBEALLOC(key, l);
+
+ ret = cdb_read(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd,
+ key->data, l,
+ cdb_keypos(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd));
+ if (ret < 0)
+ return SMDBE_IO_ERROR;
+ key->size = l;
+
+ l = cdb_datalen(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd);
+
+ DBEALLOC(value, l);
+ ret = cdb_read(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd,
+ value->data, l,
+ cdb_datapos(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd));
+ if (ret < 0)
+ return SMDBE_IO_ERROR;
+ value->size = l;
+
+ return SMDBE_OK;
+}
+
+static int
+smcdb_cursor_put(cursor, key, value, flags)
+ SMDB_CURSOR *cursor;
+ SMDB_DBENT *key;
+ SMDB_DBENT *value;
+ SMDB_FLAG flags;
+{
+ return -1;
+}
+
+static int
+smcdb_cursor(database, cursor, flags)
+ SMDB_DATABASE *database;
+ SMDB_CURSOR **cursor;
+ SMDB_FLAG flags;
+{
+ int result;
+ SMDB_CDB_DATABASE *sm_cdbmap;
+
+ result = SMDBE_OK;
+ *cursor = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
+ if (*cursor == NULL)
+ return SMDBE_MALLOC;
+
+ sm_cdbmap = (SMDB_CDB_DATABASE *) database->smdb_impl;
+ (*cursor)->smdbc_close = smcdb_cursor_close;
+ (*cursor)->smdbc_del = smcdb_cursor_del;
+ (*cursor)->smdbc_get = smcdb_cursor_get;
+ (*cursor)->smdbc_put = smcdb_cursor_put;
+ (*cursor)->smdbc_impl = sm_cdbmap;
+
+ cdb_seqinit(&sm_cdbmap->smcdb_pos, &sm_cdbmap->cdbmap_map.cdbs_cdb_rd);
+
+ return result;
+}
+
+/*
+** SMDB_DB_OPEN -- Opens a db database.
+**
+** Parameters:
+** database -- An unallocated database pointer to a pointer.
+** db_name -- The name of the database without extension.
+** mode -- File permisions for a created database.
+** mode_mask -- Mode bits that must match on an opened database.
+** sff -- Flags for safefile.
+** type -- The type of database to open
+** See smdb_type_to_cdb_type for valid types.
+** user_info -- User information for file permissions.
+** db_params --
+** An SMDB_DBPARAMS struct including params. These
+** are processed according to the type of the
+** database. Currently supported params (only for
+** HASH type) are:
+** num_elements
+** cache_size
+**
+** Returns:
+** SMDBE_OK -- Success, other errno:
+** SMDBE_MALLOC -- Cannot allocate memory.
+** SMDBE_BAD_OPEN -- db_open didn't return an error, but
+** somehow the DB pointer is NULL.
+** Anything else: translated error from cdb
+*/
+
+int
+smdb_cdb_open(database, db_name, mode, mode_mask, sff, type, user_info, db_params)
+ SMDB_DATABASE **database;
+ char *db_name;
+ int mode;
+ int mode_mask;
+ long sff;
+ SMDB_DBTYPE type;
+ SMDB_USER_INFO *user_info;
+ SMDB_DBPARAMS *db_params;
+{
+ bool lockcreated = false;
+ int result;
+ int lock_fd;
+ int db_fd;
+ SMDB_DATABASE *smdb_db;
+ SMDB_CDB_DATABASE *sm_cdbmap;
+ struct stat stat_info;
+ char db_file_name[MAXPATHLEN];
+
+ *database = NULL;
+ result = smdb_add_extension(db_file_name, sizeof db_file_name,
+ db_name, SMCDB_FILE_EXTENSION);
+ if (result != SMDBE_OK)
+ return result;
+
+ result = smdb_setup_file(db_name, SMCDB_FILE_EXTENSION,
+ mode_mask, sff, user_info, &stat_info);
+ if (result != SMDBE_OK)
+ return result;
+
+ lock_fd = -1;
+
+ if (stat_info.st_mode == ST_MODE_NOFILE &&
+ bitset(mode, O_CREAT))
+ lockcreated = true;
+
+ result = smdb_lock_file(&lock_fd, db_name, mode, sff,
+ SMCDB_FILE_EXTENSION);
+ if (result != SMDBE_OK)
+ return result;
+
+ if (lockcreated)
+ {
+ mode |= O_TRUNC;
+ mode &= ~(O_CREAT|O_EXCL);
+ }
+
+ smdb_db = smdb_malloc_database();
+ sm_cdbmap = smcdb_malloc_database();
+ if (sm_cdbmap == NULL || smdb_db == NULL)
+ {
+ smdb_unlock_file(lock_fd);
+ smdb_free_database(smdb_db); /* ok to be NULL */
+ if (sm_cdbmap != NULL)
+ free(sm_cdbmap);
+ return SMDBE_MALLOC;
+ }
+
+ sm_cdbmap->smcdb_lock_fd = lock_fd;
+
+#if 0
+ db = NULL;
+ db_flags = 0;
+ if (bitset(O_CREAT, mode))
+ db_flags |= DB_CREATE;
+ if (bitset(O_TRUNC, mode))
+ db_flags |= DB_TRUNCATE;
+ if (mode == O_RDONLY)
+ db_flags |= DB_RDONLY;
+ SM_DB_FLAG_ADD(db_flags);
+#endif
+
+ result = -1; /* smdb_db_open_internal(db_file_name, db_type, db_flags, db_params, &db); */
+ db_fd = open(db_file_name, mode, DBMMODE);
+ if (db_fd == -1)
+ {
+ result = SMDBE_BAD_OPEN;
+ goto error;
+ }
+
+ sm_cdbmap->cdbmap_create = (mode != O_RDONLY);
+ if (mode == O_RDONLY)
+ result = cdb_init(&sm_cdbmap->cdbmap_map.cdbs_cdb_rd, db_fd);
+ else
+ result = cdb_make_start(&sm_cdbmap->cdbmap_map.cdbs_cdb_wr, db_fd);
+ if (result != 0)
+ {
+ result = SMDBE_BAD_OPEN;
+ goto error;
+ }
+
+ if (result == 0)
+ result = SMDBE_OK;
+ else
+ {
+ /* Try and narrow down on the problem */
+ if (result != 0)
+ result = cdb_error_to_smdb(result);
+ else
+ result = SMDBE_BAD_OPEN;
+ }
+
+ if (result == SMDBE_OK)
+ result = smdb_filechanged(db_name, SMCDB_FILE_EXTENSION, db_fd,
+ &stat_info);
+
+ if (result == SMDBE_OK)
+ {
+ /* Everything is ok. Setup driver */
+ /* smdb_db->smcdb_db = sm_cdbmap; */
+
+ smdb_db->smdb_close = smcdb_close;
+ smdb_db->smdb_del = smcdb_del;
+ smdb_db->smdb_fd = smcdb_fd;
+ smdb_db->smdb_lockfd = smcdb_lockfd;
+ smdb_db->smdb_get = smcdb_get;
+ smdb_db->smdb_put = smcdb_put;
+ smdb_db->smdb_set_owner = smcdb_set_owner;
+ smdb_db->smdb_sync = smcdb_sync;
+ smdb_db->smdb_cursor = smcdb_cursor;
+ smdb_db->smdb_impl = sm_cdbmap;
+
+ *database = smdb_db;
+
+ return SMDBE_OK;
+ }
+
+ error:
+ if (sm_cdbmap != NULL)
+ {
+ /* close */
+ }
+
+ smdb_unlock_file(sm_cdbmap->smcdb_lock_fd);
+ free(sm_cdbmap);
+ smdb_free_database(smdb_db);
+
+ return result;
+}
+
+#endif /* CDB */
diff --git a/libsmdb/smdb.c b/libsmdb/smdb.c
index 96473b89b1733..9091b52520fa2 100644
--- a/libsmdb/smdb.c
+++ b/libsmdb/smdb.c
@@ -21,13 +21,13 @@ SM_RCSID("@(#)$Id: smdb.c,v 8.59 2013-11-22 20:51:49 ca Exp $")
static bool smdb_lockfile __P((int, int));
/*
-** SMDB_MALLOC_DATABASE -- Allocates a database structure.
+** SMDB_MALLOC_DATABASE -- Allocates a database structure.
**
** Parameters:
** None
**
** Returns:
-** An pointer to an allocated SMDB_DATABASE structure or
+** A pointer to an allocated SMDB_DATABASE structure or
** NULL if it couldn't allocate the memory.
*/
@@ -44,9 +44,8 @@ smdb_malloc_database()
return db;
}
-
/*
-** SMDB_FREE_DATABASE -- Unallocates a database structure.
+** SMDB_FREE_DATABASE -- Unallocates a database structure.
**
** Parameters:
** database -- a SMDB_DATABASE pointer to deallocate.
@@ -62,6 +61,7 @@ smdb_free_database(database)
if (database != NULL)
free(database);
}
+
/*
** SMDB_LOCKFILE -- lock a file using flock or (shudder) fcntl locking
**
@@ -155,16 +155,16 @@ smdb_lockfile(fd, type)
errno = save_errno;
return false;
}
+
/*
-** SMDB_OPEN_DATABASE -- Opens a database.
+** SMDB_OPEN_DATABASE -- Opens a database.
**
** This opens a database. If type is SMDB_DEFAULT it tries to
-** use a DB1 or DB2 hash. If that isn't available, it will try
-** to use NDBM. If a specific type is given it will try to open
-** a database of that type.
+** use available DB types. If a specific type is given it will
+** try to open a database of that type.
**
** Parameters:
-** database -- An pointer to a SMDB_DATABASE pointer where the
+** database -- A pointer to a SMDB_DATABASE pointer where the
** opened database will be stored. This should
** be unallocated.
** db_name -- The name of the database to open. Do not include
@@ -186,6 +186,20 @@ smdb_lockfile(fd, type)
** error in the comments for the specific open() used.
*/
+struct type2func_s
+{
+ const char *t2f_type;
+ smdb_open_func *t2f_open_fun;
+};
+typedef struct type2func_s type2func_t;
+static type2func_t type2func[] = {
+ { SMDB_TYPE_HASH, smdb_db_open },
+ { SMDB_TYPE_BTREE, smdb_db_open },
+ { SMDB_TYPE_NDBM, smdb_ndbm_open},
+ { SMDB_TYPE_CDB, smdb_cdb_open },
+ { NULL, NULL }
+};
+
int
smdb_open_database(database, db_name, mode, mode_mask, sff, type, user_info,
params)
@@ -198,63 +212,44 @@ smdb_open_database(database, db_name, mode, mode_mask, sff, type, user_info,
SMDB_USER_INFO *user_info;
SMDB_DBPARAMS *params;
{
-#if defined(NEWDB) && defined(NDBM)
- bool type_was_default = false;
-#endif
-
- if (type == SMDB_TYPE_DEFAULT)
- {
-#ifdef NEWDB
-# ifdef NDBM
- type_was_default = true;
-# endif
- type = SMDB_TYPE_HASH;
-#else /* NEWDB */
-# ifdef NDBM
- type = SMDB_TYPE_NDBM;
-# endif /* NDBM */
-#endif /* NEWDB */
- }
-
- if (type == SMDB_TYPE_DEFAULT)
- return SMDBE_UNKNOWN_DB_TYPE;
+ bool type_was_default;
+ int result, i;
+ const char *smdb_type;
+ smdb_open_func *smdb_open_fun;
- if ((strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0) ||
- (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0))
+ result = SMDBE_UNSUPPORTED_DB_TYPE;
+ type_was_default = SMDB_IS_TYPE_DEFAULT(type);
+ for (i = 0; (smdb_type = type2func[i].t2f_type) != NULL; i++)
{
-#ifdef NEWDB
- int result;
-
- result = smdb_db_open(database, db_name, mode, mode_mask, sff,
- type, user_info, params);
-# ifdef NDBM
- if (result == ENOENT && type_was_default)
- type = SMDB_TYPE_NDBM;
- else
-# endif /* NDBM */
- return result;
-#else /* NEWDB */
- return SMDBE_UNSUPPORTED_DB_TYPE;
-#endif /* NEWDB */
- }
-
- if (strncmp(type, SMDB_TYPE_NDBM, SMDB_TYPE_NDBM_LEN) == 0)
- {
-#ifdef NDBM
- int result;
-
- result = smdb_ndbm_open(database, db_name, mode, mode_mask,
- sff, type, user_info, params);
- return result;
-#else /* NDBM */
- return SMDBE_UNSUPPORTED_DB_TYPE;
-#endif /* NDBM */
+ if (!type_was_default && strcmp(type, smdb_type) != 0)
+ continue;
+ smdb_open_fun = type2func[i].t2f_open_fun;
+ if (smdb_open_fun == NULL)
+ {
+ if (type_was_default)
+ continue;
+ else
+ return SMDBE_UNSUPPORTED_DB_TYPE;
+ }
+ result = (*smdb_open_fun)(database, db_name, mode, mode_mask, sff,
+ (char *)smdb_type, user_info, params);
+ if (!((result == ENOENT
+ || result == EINVAL
+#ifdef EFTYPE
+ || result == EFTYPE
+#endif
+ )
+ && type_was_default))
+ goto ret;
}
-
return SMDBE_UNKNOWN_DB_TYPE;
+
+ ret:
+ return result;
}
+
/*
-** SMDB_ADD_EXTENSION -- Adds an extension to a file name.
+** SMDB_ADD_EXTENSION -- Adds an extension to a file name.
**
** Just adds a . followed by a string to a db_name if there
** is room and the db_name does not already have that extension.
@@ -488,8 +483,9 @@ smdb_filechanged(db_name, extension, db_fd, stat_info)
return result;
return filechanged(db_file_name, db_fd, stat_info);
}
+
/*
-** SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types.
+** SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types.
**
** Parameters:
** None
@@ -499,18 +495,62 @@ smdb_filechanged(db_name, extension, db_fd, stat_info)
*/
void
-smdb_print_available_types()
+smdb_print_available_types(ext)
+ bool ext;
{
-#ifdef NDBM
- printf("dbm\n");
-#endif /* NDBM */
-#ifdef NEWDB
- printf("hash\n");
- printf("btree\n");
-#endif /* NEWDB */
+# define PEXT1 ((ext) ? ":" : "")
+# define PEXT2(x) ((ext) ? x : "")
+
+#if NDBM
+ printf("%s%s%s\n", SMDB_TYPE_NDBM, PEXT1, PEXT2(SMNDB_DIR_FILE_EXTENSION));
+#endif
+#if NEWDB
+/* # if SMDB1_FILE_EXTENSION == SMDB2_FILE_EXTENSION */
+ printf("%s%s%s\n", SMDB_TYPE_HASH, PEXT1, PEXT2(SMDB1_FILE_EXTENSION));
+ printf("%s%s%s\n", SMDB_TYPE_BTREE, PEXT1, PEXT2(SMDB1_FILE_EXTENSION));
+#endif
+#if CDB
+ printf("%s%s%s\n", SMDB_TYPE_CDB, PEXT1, PEXT2(SMCDB_FILE_EXTENSION));
+#endif
+#ifdef SMDB_TYPE_IMPL
+ printf("%s%s%s\n", SMDB_TYPE_IMPL, PEXT1, "");
+#endif
+}
+
+/*
+** SMDB_IS_DB_TYPE -- Does a name match an available DB type?
+**
+** Parameters:
+** type -- The name of the database type.
+**
+** Returns:
+** true iff match
+*/
+
+bool
+smdb_is_db_type(db_type)
+ const char *db_type;
+{
+#if NDBM
+ if (strcmp(db_type, SMDB_TYPE_NDBM) == 0)
+ return true;
+#endif
+#if NEWDB
+ if (strcmp(db_type, SMDB_TYPE_HASH) == 0)
+ return true;
+ if (strcmp(db_type, SMDB_TYPE_BTREE) == 0)
+ return true;
+#endif
+#if CDB
+ if (strcmp(db_type, SMDB_TYPE_CDB) == 0)
+ return true;
+#endif
+ return false;
}
+
+
/*
-** SMDB_DB_DEFINITION -- Given a database type, return database definition
+** SMDB_DB_DEFINITION -- Given a database type, return database definition
**
** Reads though a structure making an association with the database
** type and the required cpp define from sendmail/README.
@@ -534,6 +574,7 @@ static dbtype DatabaseDefs[] =
{ SMDB_TYPE_HASH, "NEWDB" },
{ SMDB_TYPE_BTREE, "NEWDB" },
{ SMDB_TYPE_NDBM, "NDBM" },
+ { SMDB_TYPE_CDB, "CDB" },
{ NULL, "OOPS" }
};
diff --git a/libsmdb/smdb1.c b/libsmdb/smdb1.c
index 9d4e958032a7e..85dc7fcaf74cf 100644
--- a/libsmdb/smdb1.c
+++ b/libsmdb/smdb1.c
@@ -19,8 +19,6 @@ SM_RCSID("@(#)$Id: smdb1.c,v 8.63 2013-11-22 20:51:49 ca Exp $")
#if (DB_VERSION_MAJOR == 1)
-# define SMDB1_FILE_EXTENSION "db"
-
struct smdb_db1_struct
{
DB *smdb1_db;
@@ -72,10 +70,10 @@ smdb_type_to_db1_type(type)
if (type == SMDB_TYPE_DEFAULT)
return DB_HASH;
- if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
+ if (SMDB_IS_TYPE_HASH(type))
return DB_HASH;
- if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
+ if (SMDB_IS_TYPE_BTREE(type))
return DB_BTREE;
/* Should never get here thanks to test in smdb_db_open() */
@@ -471,8 +469,8 @@ smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
char db_file_name[MAXPATHLEN];
if (type == NULL ||
- (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) != 0 &&
- strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) != 0))
+ (!SMDB_IS_TYPE_HASH(type) && !SMDB_IS_TYPE_BTREE(type)
+ ))
return SMDBE_UNKNOWN_DB_TYPE;
result = smdb_add_extension(db_file_name, sizeof db_file_name,
@@ -515,8 +513,7 @@ smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
db1->smdb1_lock_fd = lock_fd;
params = NULL;
- if (db_params != NULL &&
- (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) == 0))
+ if (db_params != NULL && SMDB_IS_TYPE_HASH(type))
{
(void) memset(&hash_info, '\0', sizeof hash_info);
hash_info.nelem = db_params->smdbp_num_elements;
@@ -524,8 +521,7 @@ smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
params = &hash_info;
}
- if (db_params != NULL &&
- (strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) == 0))
+ if (db_params != NULL && SMDB_IS_TYPE_BTREE(type))
{
(void) memset(&btree_info, '\0', sizeof btree_info);
btree_info.cachesize = db_params->smdbp_cache_size;
diff --git a/libsmdb/smdb2.c b/libsmdb/smdb2.c
index 403040307a97a..d208efb403242 100644
--- a/libsmdb/smdb2.c
+++ b/libsmdb/smdb2.c
@@ -20,8 +20,6 @@ SM_RCSID("@(#)$Id: smdb2.c,v 8.83 2013-11-22 20:51:49 ca Exp $")
#if (DB_VERSION_MAJOR >= 2)
-# define SMDB2_FILE_EXTENSION "db"
-
struct smdb_db2_database
{
DB *smdb2_db;
@@ -41,17 +39,17 @@ typedef struct smdb_db2_database SMDB_DB2_DATABASE;
**
*/
-DBTYPE
+static DBTYPE
smdb_type_to_db2_type(type)
SMDB_DBTYPE type;
{
if (type == SMDB_TYPE_DEFAULT)
return DB_HASH;
- if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
+ if (SMDB_IS_TYPE_HASH(type))
return DB_HASH;
- if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
+ if (SMDB_IS_TYPE_BTREE(type))
return DB_BTREE;
return DB_UNKNOWN;
@@ -64,11 +62,11 @@ smdb_type_to_db2_type(type)
**
** Returns:
** The SMDBE error corresponding to the db2 error.
-** If we don't have a corresponding error, it returs errno.
+** If we don't have a corresponding error, it returns errno.
**
*/
-int
+static int
db2_error_to_smdb(error)
int error;
{
@@ -80,55 +78,55 @@ db2_error_to_smdb(error)
case DB_INCOMPLETE:
result = SMDBE_INCOMPLETE;
break;
-# endif /* DB_INCOMPLETE */
+# endif
# ifdef DB_NOTFOUND
case DB_NOTFOUND:
result = SMDBE_NOT_FOUND;
break;
-# endif /* DB_NOTFOUND */
+# endif
# ifdef DB_KEYEMPTY
case DB_KEYEMPTY:
result = SMDBE_KEY_EMPTY;
break;
-# endif /* DB_KEYEMPTY */
+# endif
# ifdef DB_KEYEXIST
case DB_KEYEXIST:
result = SMDBE_KEY_EXIST;
break;
-# endif /* DB_KEYEXIST */
+# endif
# ifdef DB_LOCK_DEADLOCK
case DB_LOCK_DEADLOCK:
result = SMDBE_LOCK_DEADLOCK;
break;
-# endif /* DB_LOCK_DEADLOCK */
+# endif
# ifdef DB_LOCK_NOTGRANTED
case DB_LOCK_NOTGRANTED:
result = SMDBE_LOCK_NOT_GRANTED;
break;
-# endif /* DB_LOCK_NOTGRANTED */
+# endif
# ifdef DB_LOCK_NOTHELD
case DB_LOCK_NOTHELD:
result = SMDBE_LOCK_NOT_HELD;
break;
-# endif /* DB_LOCK_NOTHELD */
+# endif
# ifdef DB_RUNRECOVERY
case DB_RUNRECOVERY:
result = SMDBE_RUN_RECOVERY;
break;
-# endif /* DB_RUNRECOVERY */
+# endif
# ifdef DB_OLD_VERSION
case DB_OLD_VERSION:
result = SMDBE_OLD_VERSION;
break;
-# endif /* DB_OLD_VERSION */
+# endif
case 0:
result = SMDBE_OK;
@@ -153,7 +151,7 @@ db2_error_to_smdb(error)
**
*/
-unsigned int
+static unsigned int
smdb_put_flags_to_db2_flags(flags)
SMDB_FLAG flags;
{
@@ -181,7 +179,7 @@ smdb_put_flags_to_db2_flags(flags)
**
*/
-int
+static int
smdb_cursor_get_flags_to_db2(flags)
SMDB_FLAG flags;
{
@@ -209,7 +207,7 @@ smdb_cursor_get_flags_to_db2(flags)
** interface laid out in smdb.h.
*/
-SMDB_DB2_DATABASE *
+static SMDB_DB2_DATABASE *
smdb2_malloc_database()
{
SMDB_DB2_DATABASE *db2;
@@ -221,7 +219,7 @@ smdb2_malloc_database()
return db2;
}
-int
+static int
smdb2_close(database)
SMDB_DATABASE *database;
{
@@ -239,7 +237,7 @@ smdb2_close(database)
return result;
}
-int
+static int
smdb2_del(database, key, flags)
SMDB_DATABASE *database;
SMDB_DBENT *key;
@@ -254,7 +252,7 @@ smdb2_del(database, key, flags)
return db2_error_to_smdb(db->del(db, NULL, &dbkey, flags));
}
-int
+static int
smdb2_fd(database, fd)
SMDB_DATABASE *database;
int *fd;
@@ -264,7 +262,7 @@ smdb2_fd(database, fd)
return db2_error_to_smdb(db->fd(db, fd));
}
-int
+static int
smdb2_lockfd(database)
SMDB_DATABASE *database;
{
@@ -273,7 +271,7 @@ smdb2_lockfd(database)
return db2->smdb2_lock_fd;
}
-int
+static int
smdb2_get(database, key, data, flags)
SMDB_DATABASE *database;
SMDB_DBENT *key;
@@ -295,7 +293,7 @@ smdb2_get(database, key, data, flags)
return db2_error_to_smdb(result);
}
-int
+static int
smdb2_put(database, key, data, flags)
SMDB_DATABASE *database;
SMDB_DBENT *key;
@@ -317,7 +315,7 @@ smdb2_put(database, key, data, flags)
}
-int
+static int
smdb2_set_owner(database, uid, gid)
SMDB_DATABASE *database;
uid_t uid;
@@ -340,7 +338,7 @@ smdb2_set_owner(database, uid, gid)
return SMDBE_OK;
}
-int
+static int
smdb2_sync(database, flags)
SMDB_DATABASE *database;
unsigned int flags;
@@ -350,7 +348,7 @@ smdb2_sync(database, flags)
return db2_error_to_smdb(db->sync(db, flags));
}
-int
+static int
smdb2_cursor_close(cursor)
SMDB_CURSOR *cursor;
{
@@ -362,7 +360,7 @@ smdb2_cursor_close(cursor)
return ret;
}
-int
+static int
smdb2_cursor_del(cursor, flags)
SMDB_CURSOR *cursor;
SMDB_FLAG flags;
@@ -372,7 +370,7 @@ smdb2_cursor_del(cursor, flags)
return db2_error_to_smdb(dbc->c_del(dbc, 0));
}
-int
+static int
smdb2_cursor_get(cursor, key, value, flags)
SMDB_CURSOR *cursor;
SMDB_DBENT *key;
@@ -398,7 +396,7 @@ smdb2_cursor_get(cursor, key, value, flags)
return db2_error_to_smdb(result);
}
-int
+static int
smdb2_cursor_put(cursor, key, value, flags)
SMDB_CURSOR *cursor;
SMDB_DBENT *key;
@@ -418,7 +416,7 @@ smdb2_cursor_put(cursor, key, value, flags)
return db2_error_to_smdb(dbc->c_put(dbc, &dbkey, &dbdata, 0));
}
-int
+static int
smdb2_cursor(database, cursor, flags)
SMDB_DATABASE *database;
SMDB_CURSOR **cursor;
@@ -430,9 +428,9 @@ smdb2_cursor(database, cursor, flags)
# if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
result = db->cursor(db, NULL, &db2_cursor, 0);
-# else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
+# else
result = db->cursor(db, NULL, &db2_cursor);
-# endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
+# endif
if (result != 0)
return db2_error_to_smdb(result);
@@ -477,6 +475,26 @@ smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
# endif /* DB_VERSION_MAJOR == 2 */
# if DB_VERSION_MAJOR > 2
+
+static void
+db_err_cb(
+#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
+ dbenv,
+#endif
+ errpfx, msg)
+#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
+ const DB_ENV *dbenv;
+ const char *errpfx;
+ const char *msg;
+#else
+ const char *errpfx;
+ char *msg;
+#endif
+{
+ /* do not print/log any errors... */
+ return;
+}
+
static int
smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
char *db_name;
@@ -491,41 +509,31 @@ smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
if (result != 0 || *db == NULL)
return result;
+ (*db)->set_errcall(*db, db_err_cb);
if (db_params != NULL)
{
result = (*db)->set_cachesize(*db, 0,
db_params->smdbp_cache_size, 0);
if (result != 0)
- {
- (void) (*db)->close((*db), 0);
- *db = NULL;
- return db2_error_to_smdb(result);
- }
+ goto error;
if (db_type == DB_HASH)
{
result = (*db)->set_h_nelem(*db, db_params->smdbp_num_elements);
if (result != 0)
- {
- (void) (*db)->close(*db, 0);
- *db = NULL;
- return db2_error_to_smdb(result);
- }
+ goto error;
}
if (db_params->smdbp_allow_dup)
{
result = (*db)->set_flags(*db, DB_DUP);
if (result != 0)
- {
- (void) (*db)->close(*db, 0);
- *db = NULL;
- return db2_error_to_smdb(result);
- }
+ goto error;
}
}
result = (*db)->open(*db,
DBTXN /* transaction for DB 4.1 */
db_name, NULL, db_type, db_flags, DBMMODE);
+ error:
if (result != 0)
{
(void) (*db)->close(*db, 0);
@@ -534,6 +542,7 @@ smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
return db2_error_to_smdb(result);
}
# endif /* DB_VERSION_MAJOR > 2 */
+
/*
** SMDB_DB_OPEN -- Opens a db database.
**
diff --git a/libsmdb/smndbm.c b/libsmdb/smndbm.c
index 579c5f55171ed..bd7bce54cf7f5 100644
--- a/libsmdb/smndbm.c
+++ b/libsmdb/smndbm.c
@@ -19,7 +19,6 @@ SM_RCSID("@(#)$Id: smndbm.c,v 8.55 2013-11-22 20:51:49 ca Exp $")
#ifdef NDBM
-# define SMNDB_DIR_FILE_EXTENSION "dir"
# define SMNDB_PAG_FILE_EXTENSION "pag"
struct smdb_dbm_database_struct