17c478bd9Sstevel@tonic-gate /*
2*e9af4bc0SJohn Beck ** Copyright (c) 1999-2002, 2004, 2009 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate **	All rights reserved.
47c478bd9Sstevel@tonic-gate **
57c478bd9Sstevel@tonic-gate ** By using this file, you agree to the terms and conditions set
67c478bd9Sstevel@tonic-gate ** forth in the LICENSE file which can be found at the top level of
77c478bd9Sstevel@tonic-gate ** the sendmail distribution.
87c478bd9Sstevel@tonic-gate */
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate #include <sm/gen.h>
11*e9af4bc0SJohn Beck SM_RCSID("@(#)$Id: smdb1.c,v 8.62 2009/11/12 23:04:18 ca Exp $")
127c478bd9Sstevel@tonic-gate 
137c478bd9Sstevel@tonic-gate #include <unistd.h>
147c478bd9Sstevel@tonic-gate #include <stdlib.h>
157c478bd9Sstevel@tonic-gate #include <fcntl.h>
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #include <sendmail/sendmail.h>
187c478bd9Sstevel@tonic-gate #include <libsmdb/smdb.h>
197c478bd9Sstevel@tonic-gate 
207c478bd9Sstevel@tonic-gate #if (DB_VERSION_MAJOR == 1)
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate # define SMDB1_FILE_EXTENSION "db"
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate struct smdb_db1_struct
257c478bd9Sstevel@tonic-gate {
267c478bd9Sstevel@tonic-gate 	DB	*smdb1_db;
277c478bd9Sstevel@tonic-gate 	int	smdb1_lock_fd;
287c478bd9Sstevel@tonic-gate 	bool	smdb1_cursor_in_use;
297c478bd9Sstevel@tonic-gate };
307c478bd9Sstevel@tonic-gate typedef struct smdb_db1_struct SMDB_DB1_DATABASE;
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate struct smdb_db1_cursor
337c478bd9Sstevel@tonic-gate {
347c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE	*db;
357c478bd9Sstevel@tonic-gate };
367c478bd9Sstevel@tonic-gate typedef struct smdb_db1_cursor SMDB_DB1_CURSOR;
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate static DBTYPE		smdb_type_to_db1_type __P((SMDB_DBTYPE));
397c478bd9Sstevel@tonic-gate static unsigned int	smdb_put_flags_to_db1_flags __P((SMDB_FLAG));
407c478bd9Sstevel@tonic-gate static int		smdb_cursor_get_flags_to_smdb1 __P((SMDB_FLAG));
417c478bd9Sstevel@tonic-gate static SMDB_DB1_DATABASE *smdb1_malloc_database __P((void));
427c478bd9Sstevel@tonic-gate static int		smdb1_close __P((SMDB_DATABASE *));
437c478bd9Sstevel@tonic-gate static int		smdb1_del __P((SMDB_DATABASE *, SMDB_DBENT *, unsigned int));
447c478bd9Sstevel@tonic-gate static int		smdb1_fd __P((SMDB_DATABASE *, int *));
457c478bd9Sstevel@tonic-gate static int		smdb1_lockfd __P((SMDB_DATABASE *));
467c478bd9Sstevel@tonic-gate static int		smdb1_get __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
477c478bd9Sstevel@tonic-gate static int		smdb1_put __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
487c478bd9Sstevel@tonic-gate static int		smdb1_set_owner __P((SMDB_DATABASE *, uid_t, gid_t));
497c478bd9Sstevel@tonic-gate static int		smdb1_sync __P((SMDB_DATABASE *, unsigned int));
507c478bd9Sstevel@tonic-gate static int		smdb1_cursor_close __P((SMDB_CURSOR *));
517c478bd9Sstevel@tonic-gate static int		smdb1_cursor_del __P((SMDB_CURSOR *, unsigned int));
527c478bd9Sstevel@tonic-gate static int		smdb1_cursor_get __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
537c478bd9Sstevel@tonic-gate static int		smdb1_cursor_put __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
547c478bd9Sstevel@tonic-gate static int		smdb1_cursor __P((SMDB_DATABASE *, SMDB_CURSOR **, unsigned int));
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate **  SMDB_TYPE_TO_DB1_TYPE -- Translates smdb database type to db1 type.
587c478bd9Sstevel@tonic-gate **
597c478bd9Sstevel@tonic-gate **	Parameters:
607c478bd9Sstevel@tonic-gate **		type -- The type to translate.
617c478bd9Sstevel@tonic-gate **
627c478bd9Sstevel@tonic-gate **	Returns:
637c478bd9Sstevel@tonic-gate **		The DB1 type that corresponsds to the passed in SMDB type.
647c478bd9Sstevel@tonic-gate **		Returns -1 if there is no equivalent type.
657c478bd9Sstevel@tonic-gate **
667c478bd9Sstevel@tonic-gate */
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate static DBTYPE
smdb_type_to_db1_type(type)697c478bd9Sstevel@tonic-gate smdb_type_to_db1_type(type)
707c478bd9Sstevel@tonic-gate 	SMDB_DBTYPE type;
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate 	if (type == SMDB_TYPE_DEFAULT)
737c478bd9Sstevel@tonic-gate 		return DB_HASH;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
767c478bd9Sstevel@tonic-gate 		return DB_HASH;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
797c478bd9Sstevel@tonic-gate 		return DB_BTREE;
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	/* Should never get here thanks to test in smdb_db_open() */
827c478bd9Sstevel@tonic-gate 	return DB_HASH;
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate **  SMDB_PUT_FLAGS_TO_DB1_FLAGS -- Translates smdb put flags to db1 put flags.
867c478bd9Sstevel@tonic-gate **
877c478bd9Sstevel@tonic-gate **	Parameters:
887c478bd9Sstevel@tonic-gate **		flags -- The flags to translate.
897c478bd9Sstevel@tonic-gate **
907c478bd9Sstevel@tonic-gate **	Returns:
917c478bd9Sstevel@tonic-gate **		The db1 flags that are equivalent to the smdb flags.
927c478bd9Sstevel@tonic-gate **
937c478bd9Sstevel@tonic-gate **	Notes:
947c478bd9Sstevel@tonic-gate **		Any invalid flags are ignored.
957c478bd9Sstevel@tonic-gate **
967c478bd9Sstevel@tonic-gate */
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate static unsigned int
smdb_put_flags_to_db1_flags(flags)997c478bd9Sstevel@tonic-gate smdb_put_flags_to_db1_flags(flags)
1007c478bd9Sstevel@tonic-gate 	SMDB_FLAG flags;
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	int return_flags;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	return_flags = 0;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	if (bitset(SMDBF_NO_OVERWRITE, flags))
1077c478bd9Sstevel@tonic-gate 		return_flags |= R_NOOVERWRITE;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	return return_flags;
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate /*
1127c478bd9Sstevel@tonic-gate **  SMDB_CURSOR_GET_FLAGS_TO_SMDB1
1137c478bd9Sstevel@tonic-gate **
1147c478bd9Sstevel@tonic-gate **	Parameters:
1157c478bd9Sstevel@tonic-gate **		flags -- The flags to translate.
1167c478bd9Sstevel@tonic-gate **
1177c478bd9Sstevel@tonic-gate **	Returns:
1187c478bd9Sstevel@tonic-gate **		The db1 flags that are equivalent to the smdb flags.
1197c478bd9Sstevel@tonic-gate **
1207c478bd9Sstevel@tonic-gate **	Notes:
1217c478bd9Sstevel@tonic-gate **		Returns -1 if we don't support the flag.
1227c478bd9Sstevel@tonic-gate **
1237c478bd9Sstevel@tonic-gate */
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate static int
smdb_cursor_get_flags_to_smdb1(flags)1267c478bd9Sstevel@tonic-gate smdb_cursor_get_flags_to_smdb1(flags)
1277c478bd9Sstevel@tonic-gate 	SMDB_FLAG flags;
1287c478bd9Sstevel@tonic-gate {
1297c478bd9Sstevel@tonic-gate 	switch(flags)
1307c478bd9Sstevel@tonic-gate 	{
1317c478bd9Sstevel@tonic-gate 		case SMDB_CURSOR_GET_FIRST:
1327c478bd9Sstevel@tonic-gate 			return R_FIRST;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 		case SMDB_CURSOR_GET_LAST:
1357c478bd9Sstevel@tonic-gate 			return R_LAST;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 		case SMDB_CURSOR_GET_NEXT:
1387c478bd9Sstevel@tonic-gate 			return R_NEXT;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 		case SMDB_CURSOR_GET_RANGE:
1417c478bd9Sstevel@tonic-gate 			return R_CURSOR;
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 		default:
1447c478bd9Sstevel@tonic-gate 			return -1;
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate **  The rest of these functions correspond to the interface laid out in smdb.h.
1507c478bd9Sstevel@tonic-gate */
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate static SMDB_DB1_DATABASE *
smdb1_malloc_database()1537c478bd9Sstevel@tonic-gate smdb1_malloc_database()
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	db1 = (SMDB_DB1_DATABASE *) malloc(sizeof(SMDB_DB1_DATABASE));
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	if (db1 != NULL)
1607c478bd9Sstevel@tonic-gate 	{
1617c478bd9Sstevel@tonic-gate 		db1->smdb1_lock_fd = -1;
1627c478bd9Sstevel@tonic-gate 		db1->smdb1_cursor_in_use = false;
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	return db1;
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate static int
smdb1_close(database)1697c478bd9Sstevel@tonic-gate smdb1_close(database)
1707c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
1717c478bd9Sstevel@tonic-gate {
1727c478bd9Sstevel@tonic-gate 	int result;
1737c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
1747c478bd9Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	result = db->close(db);
1777c478bd9Sstevel@tonic-gate 	if (db1->smdb1_lock_fd != -1)
1787c478bd9Sstevel@tonic-gate 		(void) close(db1->smdb1_lock_fd);
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	free(db1);
1817c478bd9Sstevel@tonic-gate 	database->smdb_impl = NULL;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	return result;
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate static int
smdb1_del(database,key,flags)1877c478bd9Sstevel@tonic-gate smdb1_del(database, key, flags)
1887c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
1897c478bd9Sstevel@tonic-gate 	SMDB_DBENT *key;
1907c478bd9Sstevel@tonic-gate 	unsigned int flags;
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
1937c478bd9Sstevel@tonic-gate 	DBT dbkey;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
1967c478bd9Sstevel@tonic-gate 	dbkey.data = key->data;
1977c478bd9Sstevel@tonic-gate 	dbkey.size = key->size;
1987c478bd9Sstevel@tonic-gate 	return db->del(db, &dbkey, flags);
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate static int
smdb1_fd(database,fd)2027c478bd9Sstevel@tonic-gate smdb1_fd(database, fd)
2037c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
2047c478bd9Sstevel@tonic-gate 	int *fd;
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	*fd = db->fd(db);
2097c478bd9Sstevel@tonic-gate 	if (*fd == -1)
2107c478bd9Sstevel@tonic-gate 		return errno;
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	return SMDBE_OK;
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate static int
smdb1_lockfd(database)2167c478bd9Sstevel@tonic-gate smdb1_lockfd(database)
2177c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	return db1->smdb1_lock_fd;
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate static int
smdb1_get(database,key,data,flags)2267c478bd9Sstevel@tonic-gate smdb1_get(database, key, data, flags)
2277c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
2287c478bd9Sstevel@tonic-gate 	SMDB_DBENT *key;
2297c478bd9Sstevel@tonic-gate 	SMDB_DBENT *data;
2307c478bd9Sstevel@tonic-gate 	unsigned int flags;
2317c478bd9Sstevel@tonic-gate {
2327c478bd9Sstevel@tonic-gate 	int result;
2337c478bd9Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
2347c478bd9Sstevel@tonic-gate 	DBT dbkey, dbdata;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
2377c478bd9Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
2387c478bd9Sstevel@tonic-gate 	dbkey.data = key->data;
2397c478bd9Sstevel@tonic-gate 	dbkey.size = key->size;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	result = db->get(db, &dbkey, &dbdata, flags);
2427c478bd9Sstevel@tonic-gate 	if (result != 0)
2437c478bd9Sstevel@tonic-gate 	{
2447c478bd9Sstevel@tonic-gate 		if (result == 1)
2457c478bd9Sstevel@tonic-gate 			return SMDBE_NOT_FOUND;
2467c478bd9Sstevel@tonic-gate 		return errno;
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 	data->data = dbdata.data;
2497c478bd9Sstevel@tonic-gate 	data->size = dbdata.size;
2507c478bd9Sstevel@tonic-gate 	return SMDBE_OK;
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate static int
smdb1_put(database,key,data,flags)2547c478bd9Sstevel@tonic-gate smdb1_put(database, key, data, flags)
2557c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
2567c478bd9Sstevel@tonic-gate 	SMDB_DBENT *key;
2577c478bd9Sstevel@tonic-gate 	SMDB_DBENT *data;
2587c478bd9Sstevel@tonic-gate 	unsigned int flags;
2597c478bd9Sstevel@tonic-gate {
2607c478bd9Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
2617c478bd9Sstevel@tonic-gate 	DBT dbkey, dbdata;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
2647c478bd9Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
2657c478bd9Sstevel@tonic-gate 	dbkey.data = key->data;
2667c478bd9Sstevel@tonic-gate 	dbkey.size = key->size;
2677c478bd9Sstevel@tonic-gate 	dbdata.data = data->data;
2687c478bd9Sstevel@tonic-gate 	dbdata.size = data->size;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	return db->put(db, &dbkey, &dbdata,
2717c478bd9Sstevel@tonic-gate 		       smdb_put_flags_to_db1_flags(flags));
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate static int
smdb1_set_owner(database,uid,gid)2757c478bd9Sstevel@tonic-gate smdb1_set_owner(database, uid, gid)
2767c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
2777c478bd9Sstevel@tonic-gate 	uid_t uid;
2787c478bd9Sstevel@tonic-gate 	gid_t gid;
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate # if HASFCHOWN
2817c478bd9Sstevel@tonic-gate 	int fd;
2827c478bd9Sstevel@tonic-gate 	int result;
2837c478bd9Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	fd = db->fd(db);
2867c478bd9Sstevel@tonic-gate 	if (fd == -1)
2877c478bd9Sstevel@tonic-gate 		return errno;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	result = fchown(fd, uid, gid);
2907c478bd9Sstevel@tonic-gate 	if (result < 0)
2917c478bd9Sstevel@tonic-gate 		return errno;
2927c478bd9Sstevel@tonic-gate # endif /* HASFCHOWN */
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	return SMDBE_OK;
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate static int
smdb1_sync(database,flags)2987c478bd9Sstevel@tonic-gate smdb1_sync(database, flags)
2997c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
3007c478bd9Sstevel@tonic-gate 	unsigned int flags;
3017c478bd9Sstevel@tonic-gate {
3027c478bd9Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	return db->sync(db, flags);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate static int
smdb1_cursor_close(cursor)3087c478bd9Sstevel@tonic-gate smdb1_cursor_close(cursor)
3097c478bd9Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
3107c478bd9Sstevel@tonic-gate {
3117c478bd9Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
3127c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	if (!db1->smdb1_cursor_in_use)
3157c478bd9Sstevel@tonic-gate 		return SMDBE_NOT_A_VALID_CURSOR;
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	db1->smdb1_cursor_in_use = false;
3187c478bd9Sstevel@tonic-gate 	free(cursor);
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	return SMDBE_OK;
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate static int
smdb1_cursor_del(cursor,flags)3247c478bd9Sstevel@tonic-gate smdb1_cursor_del(cursor, flags)
3257c478bd9Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
3267c478bd9Sstevel@tonic-gate 	unsigned int flags;
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
3297c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
3307c478bd9Sstevel@tonic-gate 	DB *db = db1->smdb1_db;
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	return db->del(db, NULL, R_CURSOR);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate static int
smdb1_cursor_get(cursor,key,value,flags)3367c478bd9Sstevel@tonic-gate smdb1_cursor_get(cursor, key, value, flags)
3377c478bd9Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
3387c478bd9Sstevel@tonic-gate 	SMDB_DBENT *key;
3397c478bd9Sstevel@tonic-gate 	SMDB_DBENT *value;
3407c478bd9Sstevel@tonic-gate 	SMDB_FLAG flags;
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate 	int db1_flags;
3437c478bd9Sstevel@tonic-gate 	int result;
3447c478bd9Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
3457c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
3467c478bd9Sstevel@tonic-gate 	DB *db = db1->smdb1_db;
3477c478bd9Sstevel@tonic-gate 	DBT dbkey, dbdata;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
3507c478bd9Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	db1_flags = smdb_cursor_get_flags_to_smdb1(flags);
3537c478bd9Sstevel@tonic-gate 	result = db->seq(db, &dbkey, &dbdata, db1_flags);
3547c478bd9Sstevel@tonic-gate 	if (result == -1)
3557c478bd9Sstevel@tonic-gate 		return errno;
3567c478bd9Sstevel@tonic-gate 	if (result == 1)
3577c478bd9Sstevel@tonic-gate 		return SMDBE_LAST_ENTRY;
3587c478bd9Sstevel@tonic-gate 	value->data = dbdata.data;
3597c478bd9Sstevel@tonic-gate 	value->size = dbdata.size;
3607c478bd9Sstevel@tonic-gate 	key->data = dbkey.data;
3617c478bd9Sstevel@tonic-gate 	key->size = dbkey.size;
3627c478bd9Sstevel@tonic-gate 	return SMDBE_OK;
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate static int
smdb1_cursor_put(cursor,key,value,flags)3667c478bd9Sstevel@tonic-gate smdb1_cursor_put(cursor, key, value, flags)
3677c478bd9Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
3687c478bd9Sstevel@tonic-gate 	SMDB_DBENT *key;
3697c478bd9Sstevel@tonic-gate 	SMDB_DBENT *value;
3707c478bd9Sstevel@tonic-gate 	SMDB_FLAG flags;
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
3737c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
3747c478bd9Sstevel@tonic-gate 	DB *db = db1->smdb1_db;
3757c478bd9Sstevel@tonic-gate 	DBT dbkey, dbdata;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
3787c478bd9Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
3797c478bd9Sstevel@tonic-gate 	dbkey.data = key->data;
3807c478bd9Sstevel@tonic-gate 	dbkey.size = key->size;
3817c478bd9Sstevel@tonic-gate 	dbdata.data = value->data;
3827c478bd9Sstevel@tonic-gate 	dbdata.size = value->size;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	return db->put(db, &dbkey, &dbdata, R_CURSOR);
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate static int
smdb1_cursor(database,cursor,flags)3887c478bd9Sstevel@tonic-gate smdb1_cursor(database, cursor, flags)
3897c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
3907c478bd9Sstevel@tonic-gate 	SMDB_CURSOR **cursor;
3917c478bd9Sstevel@tonic-gate 	unsigned int flags;
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
3947c478bd9Sstevel@tonic-gate 	SMDB_CURSOR *cur;
3957c478bd9Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	if (db1->smdb1_cursor_in_use)
3987c478bd9Sstevel@tonic-gate 		return SMDBE_ONLY_SUPPORTS_ONE_CURSOR;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR));
401*e9af4bc0SJohn Beck 	if (db1_cursor == NULL)
402*e9af4bc0SJohn Beck 		return SMDBE_MALLOC;
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
4057c478bd9Sstevel@tonic-gate 	if (cur == NULL)
406*e9af4bc0SJohn Beck 	{
407*e9af4bc0SJohn Beck 		free(db1_cursor);
4087c478bd9Sstevel@tonic-gate 		return SMDBE_MALLOC;
409*e9af4bc0SJohn Beck 	}
4107c478bd9Sstevel@tonic-gate 
411*e9af4bc0SJohn Beck 	db1->smdb1_cursor_in_use = true;
412*e9af4bc0SJohn Beck 	db1_cursor->db = db1;
4137c478bd9Sstevel@tonic-gate 	cur->smdbc_impl = db1_cursor;
4147c478bd9Sstevel@tonic-gate 	cur->smdbc_close = smdb1_cursor_close;
4157c478bd9Sstevel@tonic-gate 	cur->smdbc_del = smdb1_cursor_del;
4167c478bd9Sstevel@tonic-gate 	cur->smdbc_get = smdb1_cursor_get;
4177c478bd9Sstevel@tonic-gate 	cur->smdbc_put = smdb1_cursor_put;
4187c478bd9Sstevel@tonic-gate 	*cursor = cur;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	return SMDBE_OK;
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate /*
4237c478bd9Sstevel@tonic-gate **  SMDB_DB_OPEN -- Opens a db1 database.
4247c478bd9Sstevel@tonic-gate **
4257c478bd9Sstevel@tonic-gate **	Parameters:
4267c478bd9Sstevel@tonic-gate **		database -- An unallocated database pointer to a pointer.
4277c478bd9Sstevel@tonic-gate **		db_name -- The name of the database without extension.
4287c478bd9Sstevel@tonic-gate **		mode -- File permisions on the database if created.
4297c478bd9Sstevel@tonic-gate **		mode_mask -- Mode bits that must match on an existing database.
4307c478bd9Sstevel@tonic-gate **		sff -- Flags for safefile.
4317c478bd9Sstevel@tonic-gate **		type -- The type of database to open
4327c478bd9Sstevel@tonic-gate **			See smdb_type_to_db1_type for valid types.
4337c478bd9Sstevel@tonic-gate **		user_info -- Information on the user to use for file
4347c478bd9Sstevel@tonic-gate **			    permissions.
4357c478bd9Sstevel@tonic-gate **		db_params --
4367c478bd9Sstevel@tonic-gate **			An SMDB_DBPARAMS struct including params. These
4377c478bd9Sstevel@tonic-gate **			are processed according to the type of the
4387c478bd9Sstevel@tonic-gate **			database. Currently supported params (only for
4397c478bd9Sstevel@tonic-gate **			HASH type) are:
4407c478bd9Sstevel@tonic-gate **			   num_elements
4417c478bd9Sstevel@tonic-gate **			   cache_size
4427c478bd9Sstevel@tonic-gate **
4437c478bd9Sstevel@tonic-gate **	Returns:
4447c478bd9Sstevel@tonic-gate **		SMDBE_OK -- Success, otherwise errno.
4457c478bd9Sstevel@tonic-gate */
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate int
smdb_db_open(database,db_name,mode,mode_mask,sff,type,user_info,db_params)4487c478bd9Sstevel@tonic-gate smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
4497c478bd9Sstevel@tonic-gate 	     db_params)
4507c478bd9Sstevel@tonic-gate 	SMDB_DATABASE **database;
4517c478bd9Sstevel@tonic-gate 	char *db_name;
4527c478bd9Sstevel@tonic-gate 	int mode;
4537c478bd9Sstevel@tonic-gate 	int mode_mask;
4547c478bd9Sstevel@tonic-gate 	long sff;
4557c478bd9Sstevel@tonic-gate 	SMDB_DBTYPE type;
4567c478bd9Sstevel@tonic-gate 	SMDB_USER_INFO *user_info;
4577c478bd9Sstevel@tonic-gate 	SMDB_DBPARAMS *db_params;
4587c478bd9Sstevel@tonic-gate {
4597c478bd9Sstevel@tonic-gate 	bool lockcreated = false;
4607c478bd9Sstevel@tonic-gate 	int db_fd;
4617c478bd9Sstevel@tonic-gate 	int lock_fd;
4627c478bd9Sstevel@tonic-gate 	int result;
4637c478bd9Sstevel@tonic-gate 	void *params;
4647c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *smdb_db;
4657c478bd9Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1;
4667c478bd9Sstevel@tonic-gate 	DB *db;
4677c478bd9Sstevel@tonic-gate 	HASHINFO hash_info;
4687c478bd9Sstevel@tonic-gate 	BTREEINFO btree_info;
4697c478bd9Sstevel@tonic-gate 	DBTYPE db_type;
4707c478bd9Sstevel@tonic-gate 	struct stat stat_info;
4717c478bd9Sstevel@tonic-gate 	char db_file_name[MAXPATHLEN];
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	if (type == NULL ||
4747c478bd9Sstevel@tonic-gate 	    (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) != 0 &&
4757c478bd9Sstevel@tonic-gate 	     strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) != 0))
4767c478bd9Sstevel@tonic-gate 		return SMDBE_UNKNOWN_DB_TYPE;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	result = smdb_add_extension(db_file_name, sizeof db_file_name,
4797c478bd9Sstevel@tonic-gate 				    db_name, SMDB1_FILE_EXTENSION);
4807c478bd9Sstevel@tonic-gate 	if (result != SMDBE_OK)
4817c478bd9Sstevel@tonic-gate 		return result;
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask,
4847c478bd9Sstevel@tonic-gate 				 sff, user_info, &stat_info);
4857c478bd9Sstevel@tonic-gate 	if (result != SMDBE_OK)
4867c478bd9Sstevel@tonic-gate 		return result;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	if (stat_info.st_mode == ST_MODE_NOFILE &&
4897c478bd9Sstevel@tonic-gate 	    bitset(mode, O_CREAT))
4907c478bd9Sstevel@tonic-gate 		lockcreated = true;
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	lock_fd = -1;
4937c478bd9Sstevel@tonic-gate 	result = smdb_lock_file(&lock_fd, db_name, mode, sff,
4947c478bd9Sstevel@tonic-gate 				SMDB1_FILE_EXTENSION);
4957c478bd9Sstevel@tonic-gate 	if (result != SMDBE_OK)
4967c478bd9Sstevel@tonic-gate 		return result;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if (lockcreated)
4997c478bd9Sstevel@tonic-gate 	{
5007c478bd9Sstevel@tonic-gate 		mode |= O_TRUNC;
5017c478bd9Sstevel@tonic-gate 		mode &= ~(O_CREAT|O_EXCL);
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	*database = NULL;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	smdb_db = smdb_malloc_database();
5077c478bd9Sstevel@tonic-gate 	db1 = smdb1_malloc_database();
5087c478bd9Sstevel@tonic-gate 	if (smdb_db == NULL || db1 == NULL)
509*e9af4bc0SJohn Beck 	{
510*e9af4bc0SJohn Beck 		(void) smdb_unlock_file(lock_fd);
511*e9af4bc0SJohn Beck 		smdb_free_database(smdb_db);
512*e9af4bc0SJohn Beck 		free(db1);
5137c478bd9Sstevel@tonic-gate 		return SMDBE_MALLOC;
514*e9af4bc0SJohn Beck 	}
5157c478bd9Sstevel@tonic-gate 	db1->smdb1_lock_fd = lock_fd;
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	params = NULL;
5187c478bd9Sstevel@tonic-gate 	if (db_params != NULL &&
5197c478bd9Sstevel@tonic-gate 	    (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) == 0))
5207c478bd9Sstevel@tonic-gate 	{
5217c478bd9Sstevel@tonic-gate 		(void) memset(&hash_info, '\0', sizeof hash_info);
5227c478bd9Sstevel@tonic-gate 		hash_info.nelem = db_params->smdbp_num_elements;
5237c478bd9Sstevel@tonic-gate 		hash_info.cachesize = db_params->smdbp_cache_size;
5247c478bd9Sstevel@tonic-gate 		params = &hash_info;
5257c478bd9Sstevel@tonic-gate 	}
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	if (db_params != NULL &&
5287c478bd9Sstevel@tonic-gate 	    (strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) == 0))
5297c478bd9Sstevel@tonic-gate 	{
5307c478bd9Sstevel@tonic-gate 		(void) memset(&btree_info, '\0', sizeof btree_info);
5317c478bd9Sstevel@tonic-gate 		btree_info.cachesize = db_params->smdbp_cache_size;
5327c478bd9Sstevel@tonic-gate 		if (db_params->smdbp_allow_dup)
5337c478bd9Sstevel@tonic-gate 			btree_info.flags |= R_DUP;
5347c478bd9Sstevel@tonic-gate 		params = &btree_info;
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	db_type = smdb_type_to_db1_type(type);
5387c478bd9Sstevel@tonic-gate 	db = dbopen(db_file_name, mode, DBMMODE, db_type, params);
5397c478bd9Sstevel@tonic-gate 	if (db != NULL)
5407c478bd9Sstevel@tonic-gate 	{
5417c478bd9Sstevel@tonic-gate 		db_fd = db->fd(db);
5427c478bd9Sstevel@tonic-gate 		result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd,
5437c478bd9Sstevel@tonic-gate 					  &stat_info);
5447c478bd9Sstevel@tonic-gate 	}
5457c478bd9Sstevel@tonic-gate 	else
5467c478bd9Sstevel@tonic-gate 	{
5477c478bd9Sstevel@tonic-gate 		if (errno == 0)
5487c478bd9Sstevel@tonic-gate 			result = SMDBE_BAD_OPEN;
5497c478bd9Sstevel@tonic-gate 		else
5507c478bd9Sstevel@tonic-gate 			result = errno;
5517c478bd9Sstevel@tonic-gate 	}
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	if (result == SMDBE_OK)
5547c478bd9Sstevel@tonic-gate 	{
5557c478bd9Sstevel@tonic-gate 		/* Everything is ok. Setup driver */
5567c478bd9Sstevel@tonic-gate 		db1->smdb1_db = db;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 		smdb_db->smdb_close = smdb1_close;
5597c478bd9Sstevel@tonic-gate 		smdb_db->smdb_del = smdb1_del;
5607c478bd9Sstevel@tonic-gate 		smdb_db->smdb_fd = smdb1_fd;
5617c478bd9Sstevel@tonic-gate 		smdb_db->smdb_lockfd = smdb1_lockfd;
5627c478bd9Sstevel@tonic-gate 		smdb_db->smdb_get = smdb1_get;
5637c478bd9Sstevel@tonic-gate 		smdb_db->smdb_put = smdb1_put;
5647c478bd9Sstevel@tonic-gate 		smdb_db->smdb_set_owner = smdb1_set_owner;
5657c478bd9Sstevel@tonic-gate 		smdb_db->smdb_sync = smdb1_sync;
5667c478bd9Sstevel@tonic-gate 		smdb_db->smdb_cursor = smdb1_cursor;
5677c478bd9Sstevel@tonic-gate 		smdb_db->smdb_impl = db1;
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 		*database = smdb_db;
5707c478bd9Sstevel@tonic-gate 		return SMDBE_OK;
5717c478bd9Sstevel@tonic-gate 	}
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	if (db != NULL)
5747c478bd9Sstevel@tonic-gate 		(void) db->close(db);
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	/* Error opening database */
5777c478bd9Sstevel@tonic-gate 	(void) smdb_unlock_file(db1->smdb1_lock_fd);
5787c478bd9Sstevel@tonic-gate 	free(db1);
5797c478bd9Sstevel@tonic-gate 	smdb_free_database(smdb_db);
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	return result;
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate #endif /* (DB_VERSION_MAJOR == 1) */
585