xref: /onnv-gate/usr/src/cmd/sendmail/libsmdb/smdb1.c (revision 11440:802724e2906a)
10Sstevel@tonic-gate /*
2*11440SJohn.Beck@Sun.COM ** Copyright (c) 1999-2002, 2004, 2009 Sendmail, Inc. and its suppliers.
30Sstevel@tonic-gate **	All rights reserved.
40Sstevel@tonic-gate **
50Sstevel@tonic-gate ** By using this file, you agree to the terms and conditions set
60Sstevel@tonic-gate ** forth in the LICENSE file which can be found at the top level of
70Sstevel@tonic-gate ** the sendmail distribution.
80Sstevel@tonic-gate */
90Sstevel@tonic-gate 
100Sstevel@tonic-gate #include <sm/gen.h>
11*11440SJohn.Beck@Sun.COM SM_RCSID("@(#)$Id: smdb1.c,v 8.62 2009/11/12 23:04:18 ca Exp $")
120Sstevel@tonic-gate 
130Sstevel@tonic-gate #include <unistd.h>
140Sstevel@tonic-gate #include <stdlib.h>
150Sstevel@tonic-gate #include <fcntl.h>
160Sstevel@tonic-gate 
170Sstevel@tonic-gate #include <sendmail/sendmail.h>
180Sstevel@tonic-gate #include <libsmdb/smdb.h>
190Sstevel@tonic-gate 
200Sstevel@tonic-gate #if (DB_VERSION_MAJOR == 1)
210Sstevel@tonic-gate 
220Sstevel@tonic-gate # define SMDB1_FILE_EXTENSION "db"
230Sstevel@tonic-gate 
240Sstevel@tonic-gate struct smdb_db1_struct
250Sstevel@tonic-gate {
260Sstevel@tonic-gate 	DB	*smdb1_db;
270Sstevel@tonic-gate 	int	smdb1_lock_fd;
280Sstevel@tonic-gate 	bool	smdb1_cursor_in_use;
290Sstevel@tonic-gate };
300Sstevel@tonic-gate typedef struct smdb_db1_struct SMDB_DB1_DATABASE;
310Sstevel@tonic-gate 
320Sstevel@tonic-gate struct smdb_db1_cursor
330Sstevel@tonic-gate {
340Sstevel@tonic-gate 	SMDB_DB1_DATABASE	*db;
350Sstevel@tonic-gate };
360Sstevel@tonic-gate typedef struct smdb_db1_cursor SMDB_DB1_CURSOR;
370Sstevel@tonic-gate 
380Sstevel@tonic-gate static DBTYPE		smdb_type_to_db1_type __P((SMDB_DBTYPE));
390Sstevel@tonic-gate static unsigned int	smdb_put_flags_to_db1_flags __P((SMDB_FLAG));
400Sstevel@tonic-gate static int		smdb_cursor_get_flags_to_smdb1 __P((SMDB_FLAG));
410Sstevel@tonic-gate static SMDB_DB1_DATABASE *smdb1_malloc_database __P((void));
420Sstevel@tonic-gate static int		smdb1_close __P((SMDB_DATABASE *));
430Sstevel@tonic-gate static int		smdb1_del __P((SMDB_DATABASE *, SMDB_DBENT *, unsigned int));
440Sstevel@tonic-gate static int		smdb1_fd __P((SMDB_DATABASE *, int *));
450Sstevel@tonic-gate static int		smdb1_lockfd __P((SMDB_DATABASE *));
460Sstevel@tonic-gate static int		smdb1_get __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
470Sstevel@tonic-gate static int		smdb1_put __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
480Sstevel@tonic-gate static int		smdb1_set_owner __P((SMDB_DATABASE *, uid_t, gid_t));
490Sstevel@tonic-gate static int		smdb1_sync __P((SMDB_DATABASE *, unsigned int));
500Sstevel@tonic-gate static int		smdb1_cursor_close __P((SMDB_CURSOR *));
510Sstevel@tonic-gate static int		smdb1_cursor_del __P((SMDB_CURSOR *, unsigned int));
520Sstevel@tonic-gate static int		smdb1_cursor_get __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
530Sstevel@tonic-gate static int		smdb1_cursor_put __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
540Sstevel@tonic-gate static int		smdb1_cursor __P((SMDB_DATABASE *, SMDB_CURSOR **, unsigned int));
550Sstevel@tonic-gate 
560Sstevel@tonic-gate /*
570Sstevel@tonic-gate **  SMDB_TYPE_TO_DB1_TYPE -- Translates smdb database type to db1 type.
580Sstevel@tonic-gate **
590Sstevel@tonic-gate **	Parameters:
600Sstevel@tonic-gate **		type -- The type to translate.
610Sstevel@tonic-gate **
620Sstevel@tonic-gate **	Returns:
630Sstevel@tonic-gate **		The DB1 type that corresponsds to the passed in SMDB type.
640Sstevel@tonic-gate **		Returns -1 if there is no equivalent type.
650Sstevel@tonic-gate **
660Sstevel@tonic-gate */
670Sstevel@tonic-gate 
680Sstevel@tonic-gate static DBTYPE
smdb_type_to_db1_type(type)690Sstevel@tonic-gate smdb_type_to_db1_type(type)
700Sstevel@tonic-gate 	SMDB_DBTYPE type;
710Sstevel@tonic-gate {
720Sstevel@tonic-gate 	if (type == SMDB_TYPE_DEFAULT)
730Sstevel@tonic-gate 		return DB_HASH;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
760Sstevel@tonic-gate 		return DB_HASH;
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
790Sstevel@tonic-gate 		return DB_BTREE;
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	/* Should never get here thanks to test in smdb_db_open() */
820Sstevel@tonic-gate 	return DB_HASH;
830Sstevel@tonic-gate }
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate **  SMDB_PUT_FLAGS_TO_DB1_FLAGS -- Translates smdb put flags to db1 put flags.
860Sstevel@tonic-gate **
870Sstevel@tonic-gate **	Parameters:
880Sstevel@tonic-gate **		flags -- The flags to translate.
890Sstevel@tonic-gate **
900Sstevel@tonic-gate **	Returns:
910Sstevel@tonic-gate **		The db1 flags that are equivalent to the smdb flags.
920Sstevel@tonic-gate **
930Sstevel@tonic-gate **	Notes:
940Sstevel@tonic-gate **		Any invalid flags are ignored.
950Sstevel@tonic-gate **
960Sstevel@tonic-gate */
970Sstevel@tonic-gate 
980Sstevel@tonic-gate static unsigned int
smdb_put_flags_to_db1_flags(flags)990Sstevel@tonic-gate smdb_put_flags_to_db1_flags(flags)
1000Sstevel@tonic-gate 	SMDB_FLAG flags;
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate 	int return_flags;
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	return_flags = 0;
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	if (bitset(SMDBF_NO_OVERWRITE, flags))
1070Sstevel@tonic-gate 		return_flags |= R_NOOVERWRITE;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	return return_flags;
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate **  SMDB_CURSOR_GET_FLAGS_TO_SMDB1
1130Sstevel@tonic-gate **
1140Sstevel@tonic-gate **	Parameters:
1150Sstevel@tonic-gate **		flags -- The flags to translate.
1160Sstevel@tonic-gate **
1170Sstevel@tonic-gate **	Returns:
1180Sstevel@tonic-gate **		The db1 flags that are equivalent to the smdb flags.
1190Sstevel@tonic-gate **
1200Sstevel@tonic-gate **	Notes:
1210Sstevel@tonic-gate **		Returns -1 if we don't support the flag.
1220Sstevel@tonic-gate **
1230Sstevel@tonic-gate */
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate static int
smdb_cursor_get_flags_to_smdb1(flags)1260Sstevel@tonic-gate smdb_cursor_get_flags_to_smdb1(flags)
1270Sstevel@tonic-gate 	SMDB_FLAG flags;
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate 	switch(flags)
1300Sstevel@tonic-gate 	{
1310Sstevel@tonic-gate 		case SMDB_CURSOR_GET_FIRST:
1320Sstevel@tonic-gate 			return R_FIRST;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 		case SMDB_CURSOR_GET_LAST:
1350Sstevel@tonic-gate 			return R_LAST;
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 		case SMDB_CURSOR_GET_NEXT:
1380Sstevel@tonic-gate 			return R_NEXT;
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 		case SMDB_CURSOR_GET_RANGE:
1410Sstevel@tonic-gate 			return R_CURSOR;
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 		default:
1440Sstevel@tonic-gate 			return -1;
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate /*
1490Sstevel@tonic-gate **  The rest of these functions correspond to the interface laid out in smdb.h.
1500Sstevel@tonic-gate */
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate static SMDB_DB1_DATABASE *
smdb1_malloc_database()1530Sstevel@tonic-gate smdb1_malloc_database()
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	db1 = (SMDB_DB1_DATABASE *) malloc(sizeof(SMDB_DB1_DATABASE));
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	if (db1 != NULL)
1600Sstevel@tonic-gate 	{
1610Sstevel@tonic-gate 		db1->smdb1_lock_fd = -1;
1620Sstevel@tonic-gate 		db1->smdb1_cursor_in_use = false;
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	return db1;
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate static int
smdb1_close(database)1690Sstevel@tonic-gate smdb1_close(database)
1700Sstevel@tonic-gate 	SMDB_DATABASE *database;
1710Sstevel@tonic-gate {
1720Sstevel@tonic-gate 	int result;
1730Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
1740Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	result = db->close(db);
1770Sstevel@tonic-gate 	if (db1->smdb1_lock_fd != -1)
1780Sstevel@tonic-gate 		(void) close(db1->smdb1_lock_fd);
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	free(db1);
1810Sstevel@tonic-gate 	database->smdb_impl = NULL;
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 	return result;
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate static int
smdb1_del(database,key,flags)1870Sstevel@tonic-gate smdb1_del(database, key, flags)
1880Sstevel@tonic-gate 	SMDB_DATABASE *database;
1890Sstevel@tonic-gate 	SMDB_DBENT *key;
1900Sstevel@tonic-gate 	unsigned int flags;
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
1930Sstevel@tonic-gate 	DBT dbkey;
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
1960Sstevel@tonic-gate 	dbkey.data = key->data;
1970Sstevel@tonic-gate 	dbkey.size = key->size;
1980Sstevel@tonic-gate 	return db->del(db, &dbkey, flags);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate static int
smdb1_fd(database,fd)2020Sstevel@tonic-gate smdb1_fd(database, fd)
2030Sstevel@tonic-gate 	SMDB_DATABASE *database;
2040Sstevel@tonic-gate 	int *fd;
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	*fd = db->fd(db);
2090Sstevel@tonic-gate 	if (*fd == -1)
2100Sstevel@tonic-gate 		return errno;
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	return SMDBE_OK;
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate static int
smdb1_lockfd(database)2160Sstevel@tonic-gate smdb1_lockfd(database)
2170Sstevel@tonic-gate 	SMDB_DATABASE *database;
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 	return db1->smdb1_lock_fd;
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate static int
smdb1_get(database,key,data,flags)2260Sstevel@tonic-gate smdb1_get(database, key, data, flags)
2270Sstevel@tonic-gate 	SMDB_DATABASE *database;
2280Sstevel@tonic-gate 	SMDB_DBENT *key;
2290Sstevel@tonic-gate 	SMDB_DBENT *data;
2300Sstevel@tonic-gate 	unsigned int flags;
2310Sstevel@tonic-gate {
2320Sstevel@tonic-gate 	int result;
2330Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
2340Sstevel@tonic-gate 	DBT dbkey, dbdata;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
2370Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
2380Sstevel@tonic-gate 	dbkey.data = key->data;
2390Sstevel@tonic-gate 	dbkey.size = key->size;
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	result = db->get(db, &dbkey, &dbdata, flags);
2420Sstevel@tonic-gate 	if (result != 0)
2430Sstevel@tonic-gate 	{
2440Sstevel@tonic-gate 		if (result == 1)
2450Sstevel@tonic-gate 			return SMDBE_NOT_FOUND;
2460Sstevel@tonic-gate 		return errno;
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 	data->data = dbdata.data;
2490Sstevel@tonic-gate 	data->size = dbdata.size;
2500Sstevel@tonic-gate 	return SMDBE_OK;
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate static int
smdb1_put(database,key,data,flags)2540Sstevel@tonic-gate smdb1_put(database, key, data, flags)
2550Sstevel@tonic-gate 	SMDB_DATABASE *database;
2560Sstevel@tonic-gate 	SMDB_DBENT *key;
2570Sstevel@tonic-gate 	SMDB_DBENT *data;
2580Sstevel@tonic-gate 	unsigned int flags;
2590Sstevel@tonic-gate {
2600Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
2610Sstevel@tonic-gate 	DBT dbkey, dbdata;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
2640Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
2650Sstevel@tonic-gate 	dbkey.data = key->data;
2660Sstevel@tonic-gate 	dbkey.size = key->size;
2670Sstevel@tonic-gate 	dbdata.data = data->data;
2680Sstevel@tonic-gate 	dbdata.size = data->size;
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	return db->put(db, &dbkey, &dbdata,
2710Sstevel@tonic-gate 		       smdb_put_flags_to_db1_flags(flags));
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate static int
smdb1_set_owner(database,uid,gid)2750Sstevel@tonic-gate smdb1_set_owner(database, uid, gid)
2760Sstevel@tonic-gate 	SMDB_DATABASE *database;
2770Sstevel@tonic-gate 	uid_t uid;
2780Sstevel@tonic-gate 	gid_t gid;
2790Sstevel@tonic-gate {
2800Sstevel@tonic-gate # if HASFCHOWN
2810Sstevel@tonic-gate 	int fd;
2820Sstevel@tonic-gate 	int result;
2830Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	fd = db->fd(db);
2860Sstevel@tonic-gate 	if (fd == -1)
2870Sstevel@tonic-gate 		return errno;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	result = fchown(fd, uid, gid);
2900Sstevel@tonic-gate 	if (result < 0)
2910Sstevel@tonic-gate 		return errno;
2920Sstevel@tonic-gate # endif /* HASFCHOWN */
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	return SMDBE_OK;
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate static int
smdb1_sync(database,flags)2980Sstevel@tonic-gate smdb1_sync(database, flags)
2990Sstevel@tonic-gate 	SMDB_DATABASE *database;
3000Sstevel@tonic-gate 	unsigned int flags;
3010Sstevel@tonic-gate {
3020Sstevel@tonic-gate 	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	return db->sync(db, flags);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate static int
smdb1_cursor_close(cursor)3080Sstevel@tonic-gate smdb1_cursor_close(cursor)
3090Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
3100Sstevel@tonic-gate {
3110Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
3120Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	if (!db1->smdb1_cursor_in_use)
3150Sstevel@tonic-gate 		return SMDBE_NOT_A_VALID_CURSOR;
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	db1->smdb1_cursor_in_use = false;
3180Sstevel@tonic-gate 	free(cursor);
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	return SMDBE_OK;
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate static int
smdb1_cursor_del(cursor,flags)3240Sstevel@tonic-gate smdb1_cursor_del(cursor, flags)
3250Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
3260Sstevel@tonic-gate 	unsigned int flags;
3270Sstevel@tonic-gate {
3280Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
3290Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
3300Sstevel@tonic-gate 	DB *db = db1->smdb1_db;
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	return db->del(db, NULL, R_CURSOR);
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate static int
smdb1_cursor_get(cursor,key,value,flags)3360Sstevel@tonic-gate smdb1_cursor_get(cursor, key, value, flags)
3370Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
3380Sstevel@tonic-gate 	SMDB_DBENT *key;
3390Sstevel@tonic-gate 	SMDB_DBENT *value;
3400Sstevel@tonic-gate 	SMDB_FLAG flags;
3410Sstevel@tonic-gate {
3420Sstevel@tonic-gate 	int db1_flags;
3430Sstevel@tonic-gate 	int result;
3440Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
3450Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
3460Sstevel@tonic-gate 	DB *db = db1->smdb1_db;
3470Sstevel@tonic-gate 	DBT dbkey, dbdata;
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
3500Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	db1_flags = smdb_cursor_get_flags_to_smdb1(flags);
3530Sstevel@tonic-gate 	result = db->seq(db, &dbkey, &dbdata, db1_flags);
3540Sstevel@tonic-gate 	if (result == -1)
3550Sstevel@tonic-gate 		return errno;
3560Sstevel@tonic-gate 	if (result == 1)
3570Sstevel@tonic-gate 		return SMDBE_LAST_ENTRY;
3580Sstevel@tonic-gate 	value->data = dbdata.data;
3590Sstevel@tonic-gate 	value->size = dbdata.size;
3600Sstevel@tonic-gate 	key->data = dbkey.data;
3610Sstevel@tonic-gate 	key->size = dbkey.size;
3620Sstevel@tonic-gate 	return SMDBE_OK;
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate static int
smdb1_cursor_put(cursor,key,value,flags)3660Sstevel@tonic-gate smdb1_cursor_put(cursor, key, value, flags)
3670Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
3680Sstevel@tonic-gate 	SMDB_DBENT *key;
3690Sstevel@tonic-gate 	SMDB_DBENT *value;
3700Sstevel@tonic-gate 	SMDB_FLAG flags;
3710Sstevel@tonic-gate {
3720Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
3730Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
3740Sstevel@tonic-gate 	DB *db = db1->smdb1_db;
3750Sstevel@tonic-gate 	DBT dbkey, dbdata;
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
3780Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
3790Sstevel@tonic-gate 	dbkey.data = key->data;
3800Sstevel@tonic-gate 	dbkey.size = key->size;
3810Sstevel@tonic-gate 	dbdata.data = value->data;
3820Sstevel@tonic-gate 	dbdata.size = value->size;
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	return db->put(db, &dbkey, &dbdata, R_CURSOR);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate static int
smdb1_cursor(database,cursor,flags)3880Sstevel@tonic-gate smdb1_cursor(database, cursor, flags)
3890Sstevel@tonic-gate 	SMDB_DATABASE *database;
3900Sstevel@tonic-gate 	SMDB_CURSOR **cursor;
3910Sstevel@tonic-gate 	unsigned int flags;
3920Sstevel@tonic-gate {
3930Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
3940Sstevel@tonic-gate 	SMDB_CURSOR *cur;
3950Sstevel@tonic-gate 	SMDB_DB1_CURSOR *db1_cursor;
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	if (db1->smdb1_cursor_in_use)
3980Sstevel@tonic-gate 		return SMDBE_ONLY_SUPPORTS_ONE_CURSOR;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR));
401*11440SJohn.Beck@Sun.COM 	if (db1_cursor == NULL)
402*11440SJohn.Beck@Sun.COM 		return SMDBE_MALLOC;
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
405*11440SJohn.Beck@Sun.COM 	if (cur == NULL)
406*11440SJohn.Beck@Sun.COM 	{
407*11440SJohn.Beck@Sun.COM 		free(db1_cursor);
408*11440SJohn.Beck@Sun.COM 		return SMDBE_MALLOC;
409*11440SJohn.Beck@Sun.COM 	}
4100Sstevel@tonic-gate 
411*11440SJohn.Beck@Sun.COM 	db1->smdb1_cursor_in_use = true;
412*11440SJohn.Beck@Sun.COM 	db1_cursor->db = db1;
4130Sstevel@tonic-gate 	cur->smdbc_impl = db1_cursor;
4140Sstevel@tonic-gate 	cur->smdbc_close = smdb1_cursor_close;
4150Sstevel@tonic-gate 	cur->smdbc_del = smdb1_cursor_del;
4160Sstevel@tonic-gate 	cur->smdbc_get = smdb1_cursor_get;
4170Sstevel@tonic-gate 	cur->smdbc_put = smdb1_cursor_put;
4180Sstevel@tonic-gate 	*cursor = cur;
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	return SMDBE_OK;
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate /*
4230Sstevel@tonic-gate **  SMDB_DB_OPEN -- Opens a db1 database.
4240Sstevel@tonic-gate **
4250Sstevel@tonic-gate **	Parameters:
4260Sstevel@tonic-gate **		database -- An unallocated database pointer to a pointer.
4270Sstevel@tonic-gate **		db_name -- The name of the database without extension.
4280Sstevel@tonic-gate **		mode -- File permisions on the database if created.
4290Sstevel@tonic-gate **		mode_mask -- Mode bits that must match on an existing database.
4300Sstevel@tonic-gate **		sff -- Flags for safefile.
4310Sstevel@tonic-gate **		type -- The type of database to open
4320Sstevel@tonic-gate **			See smdb_type_to_db1_type for valid types.
4330Sstevel@tonic-gate **		user_info -- Information on the user to use for file
4340Sstevel@tonic-gate **			    permissions.
4350Sstevel@tonic-gate **		db_params --
4360Sstevel@tonic-gate **			An SMDB_DBPARAMS struct including params. These
4370Sstevel@tonic-gate **			are processed according to the type of the
4380Sstevel@tonic-gate **			database. Currently supported params (only for
4390Sstevel@tonic-gate **			HASH type) are:
4400Sstevel@tonic-gate **			   num_elements
4410Sstevel@tonic-gate **			   cache_size
4420Sstevel@tonic-gate **
4430Sstevel@tonic-gate **	Returns:
4440Sstevel@tonic-gate **		SMDBE_OK -- Success, otherwise errno.
4450Sstevel@tonic-gate */
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate int
smdb_db_open(database,db_name,mode,mode_mask,sff,type,user_info,db_params)4480Sstevel@tonic-gate smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
4490Sstevel@tonic-gate 	     db_params)
4500Sstevel@tonic-gate 	SMDB_DATABASE **database;
4510Sstevel@tonic-gate 	char *db_name;
4520Sstevel@tonic-gate 	int mode;
4530Sstevel@tonic-gate 	int mode_mask;
4540Sstevel@tonic-gate 	long sff;
4550Sstevel@tonic-gate 	SMDB_DBTYPE type;
4560Sstevel@tonic-gate 	SMDB_USER_INFO *user_info;
4570Sstevel@tonic-gate 	SMDB_DBPARAMS *db_params;
4580Sstevel@tonic-gate {
4590Sstevel@tonic-gate 	bool lockcreated = false;
4600Sstevel@tonic-gate 	int db_fd;
4610Sstevel@tonic-gate 	int lock_fd;
4620Sstevel@tonic-gate 	int result;
4630Sstevel@tonic-gate 	void *params;
4640Sstevel@tonic-gate 	SMDB_DATABASE *smdb_db;
4650Sstevel@tonic-gate 	SMDB_DB1_DATABASE *db1;
4660Sstevel@tonic-gate 	DB *db;
4670Sstevel@tonic-gate 	HASHINFO hash_info;
4680Sstevel@tonic-gate 	BTREEINFO btree_info;
4690Sstevel@tonic-gate 	DBTYPE db_type;
4700Sstevel@tonic-gate 	struct stat stat_info;
4710Sstevel@tonic-gate 	char db_file_name[MAXPATHLEN];
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	if (type == NULL ||
4740Sstevel@tonic-gate 	    (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) != 0 &&
4750Sstevel@tonic-gate 	     strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) != 0))
4760Sstevel@tonic-gate 		return SMDBE_UNKNOWN_DB_TYPE;
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	result = smdb_add_extension(db_file_name, sizeof db_file_name,
4790Sstevel@tonic-gate 				    db_name, SMDB1_FILE_EXTENSION);
4800Sstevel@tonic-gate 	if (result != SMDBE_OK)
4810Sstevel@tonic-gate 		return result;
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate 	result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask,
4840Sstevel@tonic-gate 				 sff, user_info, &stat_info);
4850Sstevel@tonic-gate 	if (result != SMDBE_OK)
4860Sstevel@tonic-gate 		return result;
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	if (stat_info.st_mode == ST_MODE_NOFILE &&
4890Sstevel@tonic-gate 	    bitset(mode, O_CREAT))
4900Sstevel@tonic-gate 		lockcreated = true;
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	lock_fd = -1;
4930Sstevel@tonic-gate 	result = smdb_lock_file(&lock_fd, db_name, mode, sff,
4940Sstevel@tonic-gate 				SMDB1_FILE_EXTENSION);
4950Sstevel@tonic-gate 	if (result != SMDBE_OK)
4960Sstevel@tonic-gate 		return result;
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 	if (lockcreated)
4990Sstevel@tonic-gate 	{
5000Sstevel@tonic-gate 		mode |= O_TRUNC;
5010Sstevel@tonic-gate 		mode &= ~(O_CREAT|O_EXCL);
5020Sstevel@tonic-gate 	}
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	*database = NULL;
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	smdb_db = smdb_malloc_database();
5070Sstevel@tonic-gate 	db1 = smdb1_malloc_database();
5080Sstevel@tonic-gate 	if (smdb_db == NULL || db1 == NULL)
509*11440SJohn.Beck@Sun.COM 	{
510*11440SJohn.Beck@Sun.COM 		(void) smdb_unlock_file(lock_fd);
511*11440SJohn.Beck@Sun.COM 		smdb_free_database(smdb_db);
512*11440SJohn.Beck@Sun.COM 		free(db1);
5130Sstevel@tonic-gate 		return SMDBE_MALLOC;
514*11440SJohn.Beck@Sun.COM 	}
5150Sstevel@tonic-gate 	db1->smdb1_lock_fd = lock_fd;
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	params = NULL;
5180Sstevel@tonic-gate 	if (db_params != NULL &&
5190Sstevel@tonic-gate 	    (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) == 0))
5200Sstevel@tonic-gate 	{
5210Sstevel@tonic-gate 		(void) memset(&hash_info, '\0', sizeof hash_info);
5220Sstevel@tonic-gate 		hash_info.nelem = db_params->smdbp_num_elements;
5230Sstevel@tonic-gate 		hash_info.cachesize = db_params->smdbp_cache_size;
5240Sstevel@tonic-gate 		params = &hash_info;
5250Sstevel@tonic-gate 	}
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	if (db_params != NULL &&
5280Sstevel@tonic-gate 	    (strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) == 0))
5290Sstevel@tonic-gate 	{
5300Sstevel@tonic-gate 		(void) memset(&btree_info, '\0', sizeof btree_info);
5310Sstevel@tonic-gate 		btree_info.cachesize = db_params->smdbp_cache_size;
5320Sstevel@tonic-gate 		if (db_params->smdbp_allow_dup)
5330Sstevel@tonic-gate 			btree_info.flags |= R_DUP;
5340Sstevel@tonic-gate 		params = &btree_info;
5350Sstevel@tonic-gate 	}
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	db_type = smdb_type_to_db1_type(type);
5380Sstevel@tonic-gate 	db = dbopen(db_file_name, mode, DBMMODE, db_type, params);
5390Sstevel@tonic-gate 	if (db != NULL)
5400Sstevel@tonic-gate 	{
5410Sstevel@tonic-gate 		db_fd = db->fd(db);
5420Sstevel@tonic-gate 		result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd,
5430Sstevel@tonic-gate 					  &stat_info);
5440Sstevel@tonic-gate 	}
5450Sstevel@tonic-gate 	else
5460Sstevel@tonic-gate 	{
5470Sstevel@tonic-gate 		if (errno == 0)
5480Sstevel@tonic-gate 			result = SMDBE_BAD_OPEN;
5490Sstevel@tonic-gate 		else
5500Sstevel@tonic-gate 			result = errno;
5510Sstevel@tonic-gate 	}
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	if (result == SMDBE_OK)
5540Sstevel@tonic-gate 	{
5550Sstevel@tonic-gate 		/* Everything is ok. Setup driver */
5560Sstevel@tonic-gate 		db1->smdb1_db = db;
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 		smdb_db->smdb_close = smdb1_close;
5590Sstevel@tonic-gate 		smdb_db->smdb_del = smdb1_del;
5600Sstevel@tonic-gate 		smdb_db->smdb_fd = smdb1_fd;
5610Sstevel@tonic-gate 		smdb_db->smdb_lockfd = smdb1_lockfd;
5620Sstevel@tonic-gate 		smdb_db->smdb_get = smdb1_get;
5630Sstevel@tonic-gate 		smdb_db->smdb_put = smdb1_put;
5640Sstevel@tonic-gate 		smdb_db->smdb_set_owner = smdb1_set_owner;
5650Sstevel@tonic-gate 		smdb_db->smdb_sync = smdb1_sync;
5660Sstevel@tonic-gate 		smdb_db->smdb_cursor = smdb1_cursor;
5670Sstevel@tonic-gate 		smdb_db->smdb_impl = db1;
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 		*database = smdb_db;
5700Sstevel@tonic-gate 		return SMDBE_OK;
5710Sstevel@tonic-gate 	}
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	if (db != NULL)
5740Sstevel@tonic-gate 		(void) db->close(db);
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 	/* Error opening database */
5770Sstevel@tonic-gate 	(void) smdb_unlock_file(db1->smdb1_lock_fd);
5780Sstevel@tonic-gate 	free(db1);
5790Sstevel@tonic-gate 	smdb_free_database(smdb_db);
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	return result;
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate #endif /* (DB_VERSION_MAJOR == 1) */
585