164562Sgshapiro/*
2261363Sgshapiro** Copyright (c) 1999-2002, 2004, 2009 Proofpoint, Inc. and its suppliers.
364562Sgshapiro**	All rights reserved.
464562Sgshapiro**
564562Sgshapiro** By using this file, you agree to the terms and conditions set
664562Sgshapiro** forth in the LICENSE file which can be found at the top level of
764562Sgshapiro** the sendmail distribution.
864562Sgshapiro*/
964562Sgshapiro
1090792Sgshapiro#include <sm/gen.h>
11266692SgshapiroSM_RCSID("@(#)$Id: smdb1.c,v 8.63 2013-11-22 20:51:49 ca Exp $")
1264562Sgshapiro
1364562Sgshapiro#include <unistd.h>
1464562Sgshapiro#include <stdlib.h>
1564562Sgshapiro#include <fcntl.h>
1664562Sgshapiro
1764562Sgshapiro#include <sendmail/sendmail.h>
1864562Sgshapiro#include <libsmdb/smdb.h>
1964562Sgshapiro
2064562Sgshapiro#if (DB_VERSION_MAJOR == 1)
2164562Sgshapiro
2264562Sgshapiro# define SMDB1_FILE_EXTENSION "db"
2364562Sgshapiro
2464562Sgshapirostruct smdb_db1_struct
2564562Sgshapiro{
2664562Sgshapiro	DB	*smdb1_db;
2764562Sgshapiro	int	smdb1_lock_fd;
2864562Sgshapiro	bool	smdb1_cursor_in_use;
2964562Sgshapiro};
3064562Sgshapirotypedef struct smdb_db1_struct SMDB_DB1_DATABASE;
3164562Sgshapiro
3264562Sgshapirostruct smdb_db1_cursor
3364562Sgshapiro{
3464562Sgshapiro	SMDB_DB1_DATABASE	*db;
3564562Sgshapiro};
3664562Sgshapirotypedef struct smdb_db1_cursor SMDB_DB1_CURSOR;
3764562Sgshapiro
38141858Sgshapirostatic DBTYPE		smdb_type_to_db1_type __P((SMDB_DBTYPE));
39141858Sgshapirostatic unsigned int	smdb_put_flags_to_db1_flags __P((SMDB_FLAG));
40141858Sgshapirostatic int		smdb_cursor_get_flags_to_smdb1 __P((SMDB_FLAG));
41141858Sgshapirostatic SMDB_DB1_DATABASE *smdb1_malloc_database __P((void));
42141858Sgshapirostatic int		smdb1_close __P((SMDB_DATABASE *));
43141858Sgshapirostatic int		smdb1_del __P((SMDB_DATABASE *, SMDB_DBENT *, unsigned int));
44141858Sgshapirostatic int		smdb1_fd __P((SMDB_DATABASE *, int *));
45141858Sgshapirostatic int		smdb1_lockfd __P((SMDB_DATABASE *));
46141858Sgshapirostatic int		smdb1_get __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
47141858Sgshapirostatic int		smdb1_put __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
48141858Sgshapirostatic int		smdb1_set_owner __P((SMDB_DATABASE *, uid_t, gid_t));
49141858Sgshapirostatic int		smdb1_sync __P((SMDB_DATABASE *, unsigned int));
50141858Sgshapirostatic int		smdb1_cursor_close __P((SMDB_CURSOR *));
51141858Sgshapirostatic int		smdb1_cursor_del __P((SMDB_CURSOR *, unsigned int));
52141858Sgshapirostatic int		smdb1_cursor_get __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
53141858Sgshapirostatic int		smdb1_cursor_put __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
54141858Sgshapirostatic int		smdb1_cursor __P((SMDB_DATABASE *, SMDB_CURSOR **, unsigned int));
55141858Sgshapiro
5690792Sgshapiro/*
5764562Sgshapiro**  SMDB_TYPE_TO_DB1_TYPE -- Translates smdb database type to db1 type.
5864562Sgshapiro**
5964562Sgshapiro**	Parameters:
6064562Sgshapiro**		type -- The type to translate.
6164562Sgshapiro**
6264562Sgshapiro**	Returns:
6364562Sgshapiro**		The DB1 type that corresponsds to the passed in SMDB type.
6464562Sgshapiro**		Returns -1 if there is no equivalent type.
6564562Sgshapiro**
6664562Sgshapiro*/
6764562Sgshapiro
68141858Sgshapirostatic DBTYPE
6964562Sgshapirosmdb_type_to_db1_type(type)
7064562Sgshapiro	SMDB_DBTYPE type;
7164562Sgshapiro{
7264562Sgshapiro	if (type == SMDB_TYPE_DEFAULT)
7364562Sgshapiro		return DB_HASH;
7464562Sgshapiro
7564562Sgshapiro	if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
7664562Sgshapiro		return DB_HASH;
7764562Sgshapiro
7864562Sgshapiro	if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
7964562Sgshapiro		return DB_BTREE;
8064562Sgshapiro
8164562Sgshapiro	/* Should never get here thanks to test in smdb_db_open() */
8264562Sgshapiro	return DB_HASH;
8364562Sgshapiro}
8490792Sgshapiro/*
8564562Sgshapiro**  SMDB_PUT_FLAGS_TO_DB1_FLAGS -- Translates smdb put flags to db1 put flags.
8664562Sgshapiro**
8764562Sgshapiro**	Parameters:
8864562Sgshapiro**		flags -- The flags to translate.
8964562Sgshapiro**
9064562Sgshapiro**	Returns:
9164562Sgshapiro**		The db1 flags that are equivalent to the smdb flags.
9264562Sgshapiro**
9364562Sgshapiro**	Notes:
9464562Sgshapiro**		Any invalid flags are ignored.
9564562Sgshapiro**
9664562Sgshapiro*/
9764562Sgshapiro
98141858Sgshapirostatic unsigned int
9964562Sgshapirosmdb_put_flags_to_db1_flags(flags)
10064562Sgshapiro	SMDB_FLAG flags;
10164562Sgshapiro{
10264562Sgshapiro	int return_flags;
10364562Sgshapiro
10464562Sgshapiro	return_flags = 0;
10564562Sgshapiro
10664562Sgshapiro	if (bitset(SMDBF_NO_OVERWRITE, flags))
10764562Sgshapiro		return_flags |= R_NOOVERWRITE;
10864562Sgshapiro
10964562Sgshapiro	return return_flags;
11064562Sgshapiro}
11190792Sgshapiro/*
11264562Sgshapiro**  SMDB_CURSOR_GET_FLAGS_TO_SMDB1
11364562Sgshapiro**
11464562Sgshapiro**	Parameters:
11564562Sgshapiro**		flags -- The flags to translate.
11664562Sgshapiro**
11764562Sgshapiro**	Returns:
11864562Sgshapiro**		The db1 flags that are equivalent to the smdb flags.
11964562Sgshapiro**
12064562Sgshapiro**	Notes:
12164562Sgshapiro**		Returns -1 if we don't support the flag.
12264562Sgshapiro**
12364562Sgshapiro*/
12464562Sgshapiro
125141858Sgshapirostatic int
12664562Sgshapirosmdb_cursor_get_flags_to_smdb1(flags)
12764562Sgshapiro	SMDB_FLAG flags;
12864562Sgshapiro{
12964562Sgshapiro	switch(flags)
13064562Sgshapiro	{
13164562Sgshapiro		case SMDB_CURSOR_GET_FIRST:
13264562Sgshapiro			return R_FIRST;
13364562Sgshapiro
13464562Sgshapiro		case SMDB_CURSOR_GET_LAST:
13564562Sgshapiro			return R_LAST;
13664562Sgshapiro
13764562Sgshapiro		case SMDB_CURSOR_GET_NEXT:
13864562Sgshapiro			return R_NEXT;
13964562Sgshapiro
14064562Sgshapiro		case SMDB_CURSOR_GET_RANGE:
14164562Sgshapiro			return R_CURSOR;
14264562Sgshapiro
14364562Sgshapiro		default:
14464562Sgshapiro			return -1;
14564562Sgshapiro	}
14664562Sgshapiro}
14764562Sgshapiro
14890792Sgshapiro/*
14990792Sgshapiro**  The rest of these functions correspond to the interface laid out in smdb.h.
15090792Sgshapiro*/
15190792Sgshapiro
152141858Sgshapirostatic SMDB_DB1_DATABASE *
15364562Sgshapirosmdb1_malloc_database()
15464562Sgshapiro{
15564562Sgshapiro	SMDB_DB1_DATABASE *db1;
15664562Sgshapiro
15764562Sgshapiro	db1 = (SMDB_DB1_DATABASE *) malloc(sizeof(SMDB_DB1_DATABASE));
15864562Sgshapiro
15964562Sgshapiro	if (db1 != NULL)
16064562Sgshapiro	{
16164562Sgshapiro		db1->smdb1_lock_fd = -1;
16290792Sgshapiro		db1->smdb1_cursor_in_use = false;
16364562Sgshapiro	}
16464562Sgshapiro
16564562Sgshapiro	return db1;
16664562Sgshapiro}
16764562Sgshapiro
168141858Sgshapirostatic int
16964562Sgshapirosmdb1_close(database)
17064562Sgshapiro	SMDB_DATABASE *database;
17164562Sgshapiro{
17290792Sgshapiro	int result;
17364562Sgshapiro	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
17464562Sgshapiro	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
17564562Sgshapiro
17690792Sgshapiro	result = db->close(db);
17764562Sgshapiro	if (db1->smdb1_lock_fd != -1)
17864562Sgshapiro		(void) close(db1->smdb1_lock_fd);
17964562Sgshapiro
18064562Sgshapiro	free(db1);
18164562Sgshapiro	database->smdb_impl = NULL;
18264562Sgshapiro
18390792Sgshapiro	return result;
18464562Sgshapiro}
18564562Sgshapiro
186141858Sgshapirostatic int
18764562Sgshapirosmdb1_del(database, key, flags)
18864562Sgshapiro	SMDB_DATABASE *database;
18964562Sgshapiro	SMDB_DBENT *key;
19090792Sgshapiro	unsigned int flags;
19164562Sgshapiro{
19264562Sgshapiro	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
19371345Sgshapiro	DBT dbkey;
19464562Sgshapiro
19590792Sgshapiro	(void) memset(&dbkey, '\0', sizeof dbkey);
19671345Sgshapiro	dbkey.data = key->data;
19771345Sgshapiro	dbkey.size = key->size;
19871345Sgshapiro	return db->del(db, &dbkey, flags);
19964562Sgshapiro}
20064562Sgshapiro
201141858Sgshapirostatic int
20264562Sgshapirosmdb1_fd(database, fd)
20364562Sgshapiro	SMDB_DATABASE *database;
20464562Sgshapiro	int *fd;
20564562Sgshapiro{
20664562Sgshapiro	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
20764562Sgshapiro
20864562Sgshapiro	*fd = db->fd(db);
20964562Sgshapiro	if (*fd == -1)
21064562Sgshapiro		return errno;
21164562Sgshapiro
21264562Sgshapiro	return SMDBE_OK;
21364562Sgshapiro}
21464562Sgshapiro
215141858Sgshapirostatic int
21666494Sgshapirosmdb1_lockfd(database)
21766494Sgshapiro	SMDB_DATABASE *database;
21866494Sgshapiro{
21966494Sgshapiro	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
22066494Sgshapiro
22166494Sgshapiro	return db1->smdb1_lock_fd;
22266494Sgshapiro}
22366494Sgshapiro
22466494Sgshapiro
225141858Sgshapirostatic int
22664562Sgshapirosmdb1_get(database, key, data, flags)
22764562Sgshapiro	SMDB_DATABASE *database;
22864562Sgshapiro	SMDB_DBENT *key;
22964562Sgshapiro	SMDB_DBENT *data;
23090792Sgshapiro	unsigned int flags;
23164562Sgshapiro{
23264562Sgshapiro	int result;
23364562Sgshapiro	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
23471345Sgshapiro	DBT dbkey, dbdata;
23564562Sgshapiro
23690792Sgshapiro	(void) memset(&dbdata, '\0', sizeof dbdata);
23790792Sgshapiro	(void) memset(&dbkey, '\0', sizeof dbkey);
23871345Sgshapiro	dbkey.data = key->data;
23971345Sgshapiro	dbkey.size = key->size;
24071345Sgshapiro
24171345Sgshapiro	result = db->get(db, &dbkey, &dbdata, flags);
24264562Sgshapiro	if (result != 0)
24364562Sgshapiro	{
24464562Sgshapiro		if (result == 1)
24564562Sgshapiro			return SMDBE_NOT_FOUND;
24664562Sgshapiro		return errno;
24764562Sgshapiro	}
24871345Sgshapiro	data->data = dbdata.data;
24971345Sgshapiro	data->size = dbdata.size;
25064562Sgshapiro	return SMDBE_OK;
25164562Sgshapiro}
25264562Sgshapiro
253141858Sgshapirostatic int
25464562Sgshapirosmdb1_put(database, key, data, flags)
25564562Sgshapiro	SMDB_DATABASE *database;
25664562Sgshapiro	SMDB_DBENT *key;
25764562Sgshapiro	SMDB_DBENT *data;
25890792Sgshapiro	unsigned int flags;
25964562Sgshapiro{
26064562Sgshapiro	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
26171345Sgshapiro	DBT dbkey, dbdata;
26264562Sgshapiro
26390792Sgshapiro	(void) memset(&dbdata, '\0', sizeof dbdata);
26490792Sgshapiro	(void) memset(&dbkey, '\0', sizeof dbkey);
26571345Sgshapiro	dbkey.data = key->data;
26671345Sgshapiro	dbkey.size = key->size;
26771345Sgshapiro	dbdata.data = data->data;
26871345Sgshapiro	dbdata.size = data->size;
26971345Sgshapiro
27071345Sgshapiro	return db->put(db, &dbkey, &dbdata,
27171345Sgshapiro		       smdb_put_flags_to_db1_flags(flags));
27264562Sgshapiro}
27364562Sgshapiro
274141858Sgshapirostatic int
27564562Sgshapirosmdb1_set_owner(database, uid, gid)
27664562Sgshapiro	SMDB_DATABASE *database;
27764562Sgshapiro	uid_t uid;
27864562Sgshapiro	gid_t gid;
27964562Sgshapiro{
28064562Sgshapiro# if HASFCHOWN
28164562Sgshapiro	int fd;
28264562Sgshapiro	int result;
28364562Sgshapiro	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
28464562Sgshapiro
28564562Sgshapiro	fd = db->fd(db);
28664562Sgshapiro	if (fd == -1)
28764562Sgshapiro		return errno;
28864562Sgshapiro
28964562Sgshapiro	result = fchown(fd, uid, gid);
29064562Sgshapiro	if (result < 0)
29164562Sgshapiro		return errno;
29264562Sgshapiro# endif /* HASFCHOWN */
29364562Sgshapiro
29464562Sgshapiro	return SMDBE_OK;
29564562Sgshapiro}
29664562Sgshapiro
297141858Sgshapirostatic int
29864562Sgshapirosmdb1_sync(database, flags)
29964562Sgshapiro	SMDB_DATABASE *database;
30090792Sgshapiro	unsigned int flags;
30164562Sgshapiro{
30264562Sgshapiro	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
30364562Sgshapiro
30464562Sgshapiro	return db->sync(db, flags);
30564562Sgshapiro}
30664562Sgshapiro
307141858Sgshapirostatic int
30864562Sgshapirosmdb1_cursor_close(cursor)
30964562Sgshapiro	SMDB_CURSOR *cursor;
31064562Sgshapiro{
31164562Sgshapiro	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
31264562Sgshapiro	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
31364562Sgshapiro
31464562Sgshapiro	if (!db1->smdb1_cursor_in_use)
31564562Sgshapiro		return SMDBE_NOT_A_VALID_CURSOR;
31664562Sgshapiro
31790792Sgshapiro	db1->smdb1_cursor_in_use = false;
31864562Sgshapiro	free(cursor);
31964562Sgshapiro
32064562Sgshapiro	return SMDBE_OK;
32164562Sgshapiro}
32264562Sgshapiro
323141858Sgshapirostatic int
32464562Sgshapirosmdb1_cursor_del(cursor, flags)
32564562Sgshapiro	SMDB_CURSOR *cursor;
32690792Sgshapiro	unsigned int flags;
32764562Sgshapiro{
32864562Sgshapiro	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
32964562Sgshapiro	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
33064562Sgshapiro	DB *db = db1->smdb1_db;
33164562Sgshapiro
33264562Sgshapiro	return db->del(db, NULL, R_CURSOR);
33364562Sgshapiro}
33464562Sgshapiro
335141858Sgshapirostatic int
33664562Sgshapirosmdb1_cursor_get(cursor, key, value, flags)
33764562Sgshapiro	SMDB_CURSOR *cursor;
33864562Sgshapiro	SMDB_DBENT *key;
33964562Sgshapiro	SMDB_DBENT *value;
34064562Sgshapiro	SMDB_FLAG flags;
34164562Sgshapiro{
34264562Sgshapiro	int db1_flags;
34364562Sgshapiro	int result;
34464562Sgshapiro	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
34564562Sgshapiro	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
34664562Sgshapiro	DB *db = db1->smdb1_db;
34771345Sgshapiro	DBT dbkey, dbdata;
34864562Sgshapiro
34990792Sgshapiro	(void) memset(&dbdata, '\0', sizeof dbdata);
35090792Sgshapiro	(void) memset(&dbkey, '\0', sizeof dbkey);
35171345Sgshapiro
35264562Sgshapiro	db1_flags = smdb_cursor_get_flags_to_smdb1(flags);
35371345Sgshapiro	result = db->seq(db, &dbkey, &dbdata, db1_flags);
35464562Sgshapiro	if (result == -1)
35564562Sgshapiro		return errno;
35664562Sgshapiro	if (result == 1)
35764562Sgshapiro		return SMDBE_LAST_ENTRY;
35871345Sgshapiro	value->data = dbdata.data;
35971345Sgshapiro	value->size = dbdata.size;
36071345Sgshapiro	key->data = dbkey.data;
36171345Sgshapiro	key->size = dbkey.size;
36264562Sgshapiro	return SMDBE_OK;
36364562Sgshapiro}
36464562Sgshapiro
365141858Sgshapirostatic int
36664562Sgshapirosmdb1_cursor_put(cursor, key, value, flags)
36764562Sgshapiro	SMDB_CURSOR *cursor;
36864562Sgshapiro	SMDB_DBENT *key;
36964562Sgshapiro	SMDB_DBENT *value;
37064562Sgshapiro	SMDB_FLAG flags;
37164562Sgshapiro{
37264562Sgshapiro	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
37364562Sgshapiro	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
37464562Sgshapiro	DB *db = db1->smdb1_db;
37571345Sgshapiro	DBT dbkey, dbdata;
37664562Sgshapiro
37790792Sgshapiro	(void) memset(&dbdata, '\0', sizeof dbdata);
37890792Sgshapiro	(void) memset(&dbkey, '\0', sizeof dbkey);
37971345Sgshapiro	dbkey.data = key->data;
38071345Sgshapiro	dbkey.size = key->size;
38171345Sgshapiro	dbdata.data = value->data;
38271345Sgshapiro	dbdata.size = value->size;
38371345Sgshapiro
38471345Sgshapiro	return db->put(db, &dbkey, &dbdata, R_CURSOR);
38564562Sgshapiro}
38664562Sgshapiro
387141858Sgshapirostatic int
38864562Sgshapirosmdb1_cursor(database, cursor, flags)
38964562Sgshapiro	SMDB_DATABASE *database;
39064562Sgshapiro	SMDB_CURSOR **cursor;
39190792Sgshapiro	unsigned int flags;
39264562Sgshapiro{
39364562Sgshapiro	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
39464562Sgshapiro	SMDB_CURSOR *cur;
39564562Sgshapiro	SMDB_DB1_CURSOR *db1_cursor;
39664562Sgshapiro
39764562Sgshapiro	if (db1->smdb1_cursor_in_use)
39864562Sgshapiro		return SMDBE_ONLY_SUPPORTS_ONE_CURSOR;
39964562Sgshapiro
40064562Sgshapiro	db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR));
401203004Sgshapiro	if (db1_cursor == NULL)
402203004Sgshapiro		return SMDBE_MALLOC;
40364562Sgshapiro
40464562Sgshapiro	cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
40564562Sgshapiro	if (cur == NULL)
406203004Sgshapiro	{
407203004Sgshapiro		free(db1_cursor);
40864562Sgshapiro		return SMDBE_MALLOC;
409203004Sgshapiro	}
41064562Sgshapiro
411203004Sgshapiro	db1->smdb1_cursor_in_use = true;
412203004Sgshapiro	db1_cursor->db = db1;
41364562Sgshapiro	cur->smdbc_impl = db1_cursor;
41464562Sgshapiro	cur->smdbc_close = smdb1_cursor_close;
41564562Sgshapiro	cur->smdbc_del = smdb1_cursor_del;
41664562Sgshapiro	cur->smdbc_get = smdb1_cursor_get;
41764562Sgshapiro	cur->smdbc_put = smdb1_cursor_put;
41864562Sgshapiro	*cursor = cur;
41964562Sgshapiro
42064562Sgshapiro	return SMDBE_OK;
42164562Sgshapiro}
42290792Sgshapiro/*
42364562Sgshapiro**  SMDB_DB_OPEN -- Opens a db1 database.
42464562Sgshapiro**
42564562Sgshapiro**	Parameters:
42664562Sgshapiro**		database -- An unallocated database pointer to a pointer.
42764562Sgshapiro**		db_name -- The name of the database without extension.
42864562Sgshapiro**		mode -- File permisions on the database if created.
42964562Sgshapiro**		mode_mask -- Mode bits that must match on an existing database.
43064562Sgshapiro**		sff -- Flags for safefile.
43164562Sgshapiro**		type -- The type of database to open
43264562Sgshapiro**			See smdb_type_to_db1_type for valid types.
43364562Sgshapiro**		user_info -- Information on the user to use for file
43464562Sgshapiro**			    permissions.
43564562Sgshapiro**		db_params --
43664562Sgshapiro**			An SMDB_DBPARAMS struct including params. These
43764562Sgshapiro**			are processed according to the type of the
43864562Sgshapiro**			database. Currently supported params (only for
43964562Sgshapiro**			HASH type) are:
44064562Sgshapiro**			   num_elements
44164562Sgshapiro**			   cache_size
44264562Sgshapiro**
44364562Sgshapiro**	Returns:
44464562Sgshapiro**		SMDBE_OK -- Success, otherwise errno.
44564562Sgshapiro*/
44664562Sgshapiro
44764562Sgshapiroint
44864562Sgshapirosmdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
44964562Sgshapiro	     db_params)
45064562Sgshapiro	SMDB_DATABASE **database;
45164562Sgshapiro	char *db_name;
45264562Sgshapiro	int mode;
45364562Sgshapiro	int mode_mask;
45464562Sgshapiro	long sff;
45564562Sgshapiro	SMDB_DBTYPE type;
45664562Sgshapiro	SMDB_USER_INFO *user_info;
45764562Sgshapiro	SMDB_DBPARAMS *db_params;
45864562Sgshapiro{
45994334Sgshapiro	bool lockcreated = false;
46064562Sgshapiro	int db_fd;
46164562Sgshapiro	int lock_fd;
46264562Sgshapiro	int result;
46364562Sgshapiro	void *params;
46464562Sgshapiro	SMDB_DATABASE *smdb_db;
46564562Sgshapiro	SMDB_DB1_DATABASE *db1;
46664562Sgshapiro	DB *db;
46764562Sgshapiro	HASHINFO hash_info;
46864562Sgshapiro	BTREEINFO btree_info;
46964562Sgshapiro	DBTYPE db_type;
47064562Sgshapiro	struct stat stat_info;
47198121Sgshapiro	char db_file_name[MAXPATHLEN];
47264562Sgshapiro
47364562Sgshapiro	if (type == NULL ||
47464562Sgshapiro	    (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) != 0 &&
47564562Sgshapiro	     strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) != 0))
47664562Sgshapiro		return SMDBE_UNKNOWN_DB_TYPE;
47764562Sgshapiro
47898121Sgshapiro	result = smdb_add_extension(db_file_name, sizeof db_file_name,
47964562Sgshapiro				    db_name, SMDB1_FILE_EXTENSION);
48064562Sgshapiro	if (result != SMDBE_OK)
48164562Sgshapiro		return result;
48264562Sgshapiro
48364562Sgshapiro	result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask,
48464562Sgshapiro				 sff, user_info, &stat_info);
48564562Sgshapiro	if (result != SMDBE_OK)
48664562Sgshapiro		return result;
48764562Sgshapiro
48894334Sgshapiro	if (stat_info.st_mode == ST_MODE_NOFILE &&
48994334Sgshapiro	    bitset(mode, O_CREAT))
49094334Sgshapiro		lockcreated = true;
49194334Sgshapiro
49264562Sgshapiro	lock_fd = -1;
49364562Sgshapiro	result = smdb_lock_file(&lock_fd, db_name, mode, sff,
49464562Sgshapiro				SMDB1_FILE_EXTENSION);
49564562Sgshapiro	if (result != SMDBE_OK)
49664562Sgshapiro		return result;
49764562Sgshapiro
49894334Sgshapiro	if (lockcreated)
49994334Sgshapiro	{
50094334Sgshapiro		mode |= O_TRUNC;
50194334Sgshapiro		mode &= ~(O_CREAT|O_EXCL);
50294334Sgshapiro	}
50394334Sgshapiro
50464562Sgshapiro	*database = NULL;
50564562Sgshapiro
50664562Sgshapiro	smdb_db = smdb_malloc_database();
50764562Sgshapiro	db1 = smdb1_malloc_database();
50864562Sgshapiro	if (smdb_db == NULL || db1 == NULL)
509203004Sgshapiro	{
510203004Sgshapiro		(void) smdb_unlock_file(lock_fd);
511203004Sgshapiro		smdb_free_database(smdb_db);
512203004Sgshapiro		free(db1);
51364562Sgshapiro		return SMDBE_MALLOC;
514203004Sgshapiro	}
51564562Sgshapiro	db1->smdb1_lock_fd = lock_fd;
51664562Sgshapiro
51764562Sgshapiro	params = NULL;
51864562Sgshapiro	if (db_params != NULL &&
51964562Sgshapiro	    (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) == 0))
52064562Sgshapiro	{
52190792Sgshapiro		(void) memset(&hash_info, '\0', sizeof hash_info);
52264562Sgshapiro		hash_info.nelem = db_params->smdbp_num_elements;
52364562Sgshapiro		hash_info.cachesize = db_params->smdbp_cache_size;
52464562Sgshapiro		params = &hash_info;
52564562Sgshapiro	}
52664562Sgshapiro
52764562Sgshapiro	if (db_params != NULL &&
52864562Sgshapiro	    (strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) == 0))
52964562Sgshapiro	{
53090792Sgshapiro		(void) memset(&btree_info, '\0', sizeof btree_info);
53164562Sgshapiro		btree_info.cachesize = db_params->smdbp_cache_size;
53264562Sgshapiro		if (db_params->smdbp_allow_dup)
53364562Sgshapiro			btree_info.flags |= R_DUP;
53464562Sgshapiro		params = &btree_info;
53564562Sgshapiro	}
53664562Sgshapiro
53764562Sgshapiro	db_type = smdb_type_to_db1_type(type);
53898121Sgshapiro	db = dbopen(db_file_name, mode, DBMMODE, db_type, params);
53964562Sgshapiro	if (db != NULL)
54064562Sgshapiro	{
54164562Sgshapiro		db_fd = db->fd(db);
54264562Sgshapiro		result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd,
54364562Sgshapiro					  &stat_info);
54464562Sgshapiro	}
54564562Sgshapiro	else
54664562Sgshapiro	{
54764562Sgshapiro		if (errno == 0)
54864562Sgshapiro			result = SMDBE_BAD_OPEN;
54964562Sgshapiro		else
55064562Sgshapiro			result = errno;
55164562Sgshapiro	}
55264562Sgshapiro
55364562Sgshapiro	if (result == SMDBE_OK)
55464562Sgshapiro	{
55564562Sgshapiro		/* Everything is ok. Setup driver */
55664562Sgshapiro		db1->smdb1_db = db;
55764562Sgshapiro
55864562Sgshapiro		smdb_db->smdb_close = smdb1_close;
55964562Sgshapiro		smdb_db->smdb_del = smdb1_del;
56064562Sgshapiro		smdb_db->smdb_fd = smdb1_fd;
56166494Sgshapiro		smdb_db->smdb_lockfd = smdb1_lockfd;
56264562Sgshapiro		smdb_db->smdb_get = smdb1_get;
56364562Sgshapiro		smdb_db->smdb_put = smdb1_put;
56464562Sgshapiro		smdb_db->smdb_set_owner = smdb1_set_owner;
56564562Sgshapiro		smdb_db->smdb_sync = smdb1_sync;
56664562Sgshapiro		smdb_db->smdb_cursor = smdb1_cursor;
56764562Sgshapiro		smdb_db->smdb_impl = db1;
56864562Sgshapiro
56964562Sgshapiro		*database = smdb_db;
57064562Sgshapiro		return SMDBE_OK;
57164562Sgshapiro	}
57264562Sgshapiro
57364562Sgshapiro	if (db != NULL)
57464562Sgshapiro		(void) db->close(db);
57564562Sgshapiro
57664562Sgshapiro	/* Error opening database */
57764562Sgshapiro	(void) smdb_unlock_file(db1->smdb1_lock_fd);
57864562Sgshapiro	free(db1);
57964562Sgshapiro	smdb_free_database(smdb_db);
58064562Sgshapiro
58164562Sgshapiro	return result;
58264562Sgshapiro}
58364562Sgshapiro
58464562Sgshapiro#endif /* (DB_VERSION_MAJOR == 1) */
585