10Sstevel@tonic-gate /*
2*11440SJohn.Beck@Sun.COM ** Copyright (c) 1999-2003, 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: smdb2.c,v 8.80 2009/11/12 23:07:49 ca Exp $")
120Sstevel@tonic-gate
130Sstevel@tonic-gate #include <fcntl.h>
140Sstevel@tonic-gate #include <stdlib.h>
150Sstevel@tonic-gate #include <unistd.h>
160Sstevel@tonic-gate
170Sstevel@tonic-gate
180Sstevel@tonic-gate #include <sendmail/sendmail.h>
190Sstevel@tonic-gate #include <libsmdb/smdb.h>
200Sstevel@tonic-gate
210Sstevel@tonic-gate #if (DB_VERSION_MAJOR >= 2)
220Sstevel@tonic-gate
230Sstevel@tonic-gate # define SMDB2_FILE_EXTENSION "db"
240Sstevel@tonic-gate
250Sstevel@tonic-gate struct smdb_db2_database
260Sstevel@tonic-gate {
270Sstevel@tonic-gate DB *smdb2_db;
280Sstevel@tonic-gate int smdb2_lock_fd;
290Sstevel@tonic-gate };
300Sstevel@tonic-gate typedef struct smdb_db2_database SMDB_DB2_DATABASE;
310Sstevel@tonic-gate
320Sstevel@tonic-gate /*
330Sstevel@tonic-gate ** SMDB_TYPE_TO_DB2_TYPE -- Translates smdb database type to db2 type.
340Sstevel@tonic-gate **
350Sstevel@tonic-gate ** Parameters:
360Sstevel@tonic-gate ** type -- The type to translate.
370Sstevel@tonic-gate **
380Sstevel@tonic-gate ** Returns:
390Sstevel@tonic-gate ** The DB2 type that corresponsds to the passed in SMDB type.
400Sstevel@tonic-gate ** Returns -1 if there is no equivalent type.
410Sstevel@tonic-gate **
420Sstevel@tonic-gate */
430Sstevel@tonic-gate
440Sstevel@tonic-gate DBTYPE
smdb_type_to_db2_type(type)450Sstevel@tonic-gate smdb_type_to_db2_type(type)
460Sstevel@tonic-gate SMDB_DBTYPE type;
470Sstevel@tonic-gate {
480Sstevel@tonic-gate if (type == SMDB_TYPE_DEFAULT)
490Sstevel@tonic-gate return DB_HASH;
500Sstevel@tonic-gate
510Sstevel@tonic-gate if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
520Sstevel@tonic-gate return DB_HASH;
530Sstevel@tonic-gate
540Sstevel@tonic-gate if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
550Sstevel@tonic-gate return DB_BTREE;
560Sstevel@tonic-gate
570Sstevel@tonic-gate return DB_UNKNOWN;
580Sstevel@tonic-gate }
590Sstevel@tonic-gate /*
600Sstevel@tonic-gate ** DB2_ERROR_TO_SMDB -- Translates db2 errors to smdbe errors
610Sstevel@tonic-gate **
620Sstevel@tonic-gate ** Parameters:
630Sstevel@tonic-gate ** error -- The error to translate.
640Sstevel@tonic-gate **
650Sstevel@tonic-gate ** Returns:
660Sstevel@tonic-gate ** The SMDBE error corresponding to the db2 error.
670Sstevel@tonic-gate ** If we don't have a corresponding error, it returs errno.
680Sstevel@tonic-gate **
690Sstevel@tonic-gate */
700Sstevel@tonic-gate
710Sstevel@tonic-gate int
db2_error_to_smdb(error)720Sstevel@tonic-gate db2_error_to_smdb(error)
730Sstevel@tonic-gate int error;
740Sstevel@tonic-gate {
750Sstevel@tonic-gate int result;
760Sstevel@tonic-gate
770Sstevel@tonic-gate switch (error)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate # ifdef DB_INCOMPLETE
800Sstevel@tonic-gate case DB_INCOMPLETE:
810Sstevel@tonic-gate result = SMDBE_INCOMPLETE;
820Sstevel@tonic-gate break;
830Sstevel@tonic-gate # endif /* DB_INCOMPLETE */
840Sstevel@tonic-gate
850Sstevel@tonic-gate # ifdef DB_NOTFOUND
860Sstevel@tonic-gate case DB_NOTFOUND:
870Sstevel@tonic-gate result = SMDBE_NOT_FOUND;
880Sstevel@tonic-gate break;
890Sstevel@tonic-gate # endif /* DB_NOTFOUND */
900Sstevel@tonic-gate
910Sstevel@tonic-gate # ifdef DB_KEYEMPTY
920Sstevel@tonic-gate case DB_KEYEMPTY:
930Sstevel@tonic-gate result = SMDBE_KEY_EMPTY;
940Sstevel@tonic-gate break;
950Sstevel@tonic-gate # endif /* DB_KEYEMPTY */
960Sstevel@tonic-gate
970Sstevel@tonic-gate # ifdef DB_KEYEXIST
980Sstevel@tonic-gate case DB_KEYEXIST:
990Sstevel@tonic-gate result = SMDBE_KEY_EXIST;
1000Sstevel@tonic-gate break;
1010Sstevel@tonic-gate # endif /* DB_KEYEXIST */
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate # ifdef DB_LOCK_DEADLOCK
1040Sstevel@tonic-gate case DB_LOCK_DEADLOCK:
1050Sstevel@tonic-gate result = SMDBE_LOCK_DEADLOCK;
1060Sstevel@tonic-gate break;
1070Sstevel@tonic-gate # endif /* DB_LOCK_DEADLOCK */
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate # ifdef DB_LOCK_NOTGRANTED
1100Sstevel@tonic-gate case DB_LOCK_NOTGRANTED:
1110Sstevel@tonic-gate result = SMDBE_LOCK_NOT_GRANTED;
1120Sstevel@tonic-gate break;
1130Sstevel@tonic-gate # endif /* DB_LOCK_NOTGRANTED */
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate # ifdef DB_LOCK_NOTHELD
1160Sstevel@tonic-gate case DB_LOCK_NOTHELD:
1170Sstevel@tonic-gate result = SMDBE_LOCK_NOT_HELD;
1180Sstevel@tonic-gate break;
1190Sstevel@tonic-gate # endif /* DB_LOCK_NOTHELD */
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate # ifdef DB_RUNRECOVERY
1220Sstevel@tonic-gate case DB_RUNRECOVERY:
1230Sstevel@tonic-gate result = SMDBE_RUN_RECOVERY;
1240Sstevel@tonic-gate break;
1250Sstevel@tonic-gate # endif /* DB_RUNRECOVERY */
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate # ifdef DB_OLD_VERSION
1280Sstevel@tonic-gate case DB_OLD_VERSION:
1290Sstevel@tonic-gate result = SMDBE_OLD_VERSION;
1300Sstevel@tonic-gate break;
1310Sstevel@tonic-gate # endif /* DB_OLD_VERSION */
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate case 0:
1340Sstevel@tonic-gate result = SMDBE_OK;
1350Sstevel@tonic-gate break;
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate default:
1380Sstevel@tonic-gate result = error;
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate return result;
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate ** SMDB_PUT_FLAGS_TO_DB2_FLAGS -- Translates smdb put flags to db2 put flags.
1440Sstevel@tonic-gate **
1450Sstevel@tonic-gate ** Parameters:
1460Sstevel@tonic-gate ** flags -- The flags to translate.
1470Sstevel@tonic-gate **
1480Sstevel@tonic-gate ** Returns:
1490Sstevel@tonic-gate ** The db2 flags that are equivalent to the smdb flags.
1500Sstevel@tonic-gate **
1510Sstevel@tonic-gate ** Notes:
1520Sstevel@tonic-gate ** Any invalid flags are ignored.
1530Sstevel@tonic-gate **
1540Sstevel@tonic-gate */
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate unsigned int
smdb_put_flags_to_db2_flags(flags)1570Sstevel@tonic-gate smdb_put_flags_to_db2_flags(flags)
1580Sstevel@tonic-gate SMDB_FLAG flags;
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate int return_flags;
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate return_flags = 0;
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate if (bitset(SMDBF_NO_OVERWRITE, flags))
1650Sstevel@tonic-gate return_flags |= DB_NOOVERWRITE;
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate return return_flags;
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate ** SMDB_CURSOR_GET_FLAGS_TO_DB2 -- Translates smdb cursor get flags to db2
1710Sstevel@tonic-gate ** getflags.
1720Sstevel@tonic-gate **
1730Sstevel@tonic-gate ** Parameters:
1740Sstevel@tonic-gate ** flags -- The flags to translate.
1750Sstevel@tonic-gate **
1760Sstevel@tonic-gate ** Returns:
1770Sstevel@tonic-gate ** The db2 flags that are equivalent to the smdb flags.
1780Sstevel@tonic-gate **
1790Sstevel@tonic-gate ** Notes:
1800Sstevel@tonic-gate ** -1 is returned if flag is unknown.
1810Sstevel@tonic-gate **
1820Sstevel@tonic-gate */
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate int
smdb_cursor_get_flags_to_db2(flags)1850Sstevel@tonic-gate smdb_cursor_get_flags_to_db2(flags)
1860Sstevel@tonic-gate SMDB_FLAG flags;
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate switch (flags)
1890Sstevel@tonic-gate {
1900Sstevel@tonic-gate case SMDB_CURSOR_GET_FIRST:
1910Sstevel@tonic-gate return DB_FIRST;
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate case SMDB_CURSOR_GET_LAST:
1940Sstevel@tonic-gate return DB_LAST;
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate case SMDB_CURSOR_GET_NEXT:
1970Sstevel@tonic-gate return DB_NEXT;
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate case SMDB_CURSOR_GET_RANGE:
2000Sstevel@tonic-gate return DB_SET_RANGE;
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate default:
2030Sstevel@tonic-gate return -1;
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate /*
2080Sstevel@tonic-gate ** Except for smdb_db_open, the rest of these functions correspond to the
2090Sstevel@tonic-gate ** interface laid out in smdb.h.
2100Sstevel@tonic-gate */
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate SMDB_DB2_DATABASE *
smdb2_malloc_database()2130Sstevel@tonic-gate smdb2_malloc_database()
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate SMDB_DB2_DATABASE *db2;
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate db2 = (SMDB_DB2_DATABASE *) malloc(sizeof(SMDB_DB2_DATABASE));
2180Sstevel@tonic-gate if (db2 != NULL)
2190Sstevel@tonic-gate db2->smdb2_lock_fd = -1;
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate return db2;
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate int
smdb2_close(database)2250Sstevel@tonic-gate smdb2_close(database)
2260Sstevel@tonic-gate SMDB_DATABASE *database;
2270Sstevel@tonic-gate {
2280Sstevel@tonic-gate int result;
2290Sstevel@tonic-gate SMDB_DB2_DATABASE *db2 = (SMDB_DB2_DATABASE *) database->smdb_impl;
2300Sstevel@tonic-gate DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate result = db2_error_to_smdb(db->close(db, 0));
2330Sstevel@tonic-gate if (db2->smdb2_lock_fd != -1)
2340Sstevel@tonic-gate close(db2->smdb2_lock_fd);
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate free(db2);
2370Sstevel@tonic-gate database->smdb_impl = NULL;
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate return result;
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate int
smdb2_del(database,key,flags)2430Sstevel@tonic-gate smdb2_del(database, key, flags)
2440Sstevel@tonic-gate SMDB_DATABASE *database;
2450Sstevel@tonic-gate SMDB_DBENT *key;
2460Sstevel@tonic-gate unsigned int flags;
2470Sstevel@tonic-gate {
2480Sstevel@tonic-gate DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
2490Sstevel@tonic-gate DBT dbkey;
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate (void) memset(&dbkey, '\0', sizeof dbkey);
2520Sstevel@tonic-gate dbkey.data = key->data;
2530Sstevel@tonic-gate dbkey.size = key->size;
2540Sstevel@tonic-gate return db2_error_to_smdb(db->del(db, NULL, &dbkey, flags));
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate int
smdb2_fd(database,fd)2580Sstevel@tonic-gate smdb2_fd(database, fd)
2590Sstevel@tonic-gate SMDB_DATABASE *database;
2600Sstevel@tonic-gate int *fd;
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate return db2_error_to_smdb(db->fd(db, fd));
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate int
smdb2_lockfd(database)2680Sstevel@tonic-gate smdb2_lockfd(database)
2690Sstevel@tonic-gate SMDB_DATABASE *database;
2700Sstevel@tonic-gate {
2710Sstevel@tonic-gate SMDB_DB2_DATABASE *db2 = (SMDB_DB2_DATABASE *) database->smdb_impl;
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate return db2->smdb2_lock_fd;
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate int
smdb2_get(database,key,data,flags)2770Sstevel@tonic-gate smdb2_get(database, key, data, flags)
2780Sstevel@tonic-gate SMDB_DATABASE *database;
2790Sstevel@tonic-gate SMDB_DBENT *key;
2800Sstevel@tonic-gate SMDB_DBENT *data;
2810Sstevel@tonic-gate unsigned int flags;
2820Sstevel@tonic-gate {
2830Sstevel@tonic-gate int result;
2840Sstevel@tonic-gate DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
2850Sstevel@tonic-gate DBT dbkey, dbdata;
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate (void) memset(&dbdata, '\0', sizeof dbdata);
2880Sstevel@tonic-gate (void) memset(&dbkey, '\0', sizeof dbkey);
2890Sstevel@tonic-gate dbkey.data = key->data;
2900Sstevel@tonic-gate dbkey.size = key->size;
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate result = db->get(db, NULL, &dbkey, &dbdata, flags);
2930Sstevel@tonic-gate data->data = dbdata.data;
2940Sstevel@tonic-gate data->size = dbdata.size;
2950Sstevel@tonic-gate return db2_error_to_smdb(result);
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate int
smdb2_put(database,key,data,flags)2990Sstevel@tonic-gate smdb2_put(database, key, data, flags)
3000Sstevel@tonic-gate SMDB_DATABASE *database;
3010Sstevel@tonic-gate SMDB_DBENT *key;
3020Sstevel@tonic-gate SMDB_DBENT *data;
3030Sstevel@tonic-gate unsigned int flags;
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
3060Sstevel@tonic-gate DBT dbkey, dbdata;
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate (void) memset(&dbdata, '\0', sizeof dbdata);
3090Sstevel@tonic-gate (void) memset(&dbkey, '\0', sizeof dbkey);
3100Sstevel@tonic-gate dbkey.data = key->data;
3110Sstevel@tonic-gate dbkey.size = key->size;
3120Sstevel@tonic-gate dbdata.data = data->data;
3130Sstevel@tonic-gate dbdata.size = data->size;
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate return db2_error_to_smdb(db->put(db, NULL, &dbkey, &dbdata,
3160Sstevel@tonic-gate smdb_put_flags_to_db2_flags(flags)));
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate int
smdb2_set_owner(database,uid,gid)3210Sstevel@tonic-gate smdb2_set_owner(database, uid, gid)
3220Sstevel@tonic-gate SMDB_DATABASE *database;
3230Sstevel@tonic-gate uid_t uid;
3240Sstevel@tonic-gate gid_t gid;
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate # if HASFCHOWN
3270Sstevel@tonic-gate int fd;
3280Sstevel@tonic-gate int result;
3290Sstevel@tonic-gate DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate result = db->fd(db, &fd);
3320Sstevel@tonic-gate if (result != 0)
3330Sstevel@tonic-gate return result;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate result = fchown(fd, uid, gid);
3360Sstevel@tonic-gate if (result < 0)
3370Sstevel@tonic-gate return errno;
3380Sstevel@tonic-gate # endif /* HASFCHOWN */
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate return SMDBE_OK;
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate int
smdb2_sync(database,flags)3440Sstevel@tonic-gate smdb2_sync(database, flags)
3450Sstevel@tonic-gate SMDB_DATABASE *database;
3460Sstevel@tonic-gate unsigned int flags;
3470Sstevel@tonic-gate {
3480Sstevel@tonic-gate DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate return db2_error_to_smdb(db->sync(db, flags));
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate int
smdb2_cursor_close(cursor)3540Sstevel@tonic-gate smdb2_cursor_close(cursor)
3550Sstevel@tonic-gate SMDB_CURSOR *cursor;
3560Sstevel@tonic-gate {
3570Sstevel@tonic-gate int ret;
3580Sstevel@tonic-gate DBC *dbc = (DBC *) cursor->smdbc_impl;
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate ret = db2_error_to_smdb(dbc->c_close(dbc));
3610Sstevel@tonic-gate free(cursor);
3620Sstevel@tonic-gate return ret;
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate int
smdb2_cursor_del(cursor,flags)3660Sstevel@tonic-gate smdb2_cursor_del(cursor, flags)
3670Sstevel@tonic-gate SMDB_CURSOR *cursor;
3680Sstevel@tonic-gate SMDB_FLAG flags;
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate DBC *dbc = (DBC *) cursor->smdbc_impl;
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate return db2_error_to_smdb(dbc->c_del(dbc, 0));
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate int
smdb2_cursor_get(cursor,key,value,flags)3760Sstevel@tonic-gate smdb2_cursor_get(cursor, key, value, flags)
3770Sstevel@tonic-gate SMDB_CURSOR *cursor;
3780Sstevel@tonic-gate SMDB_DBENT *key;
3790Sstevel@tonic-gate SMDB_DBENT *value;
3800Sstevel@tonic-gate SMDB_FLAG flags;
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate int db2_flags;
3830Sstevel@tonic-gate int result;
3840Sstevel@tonic-gate DBC *dbc = (DBC *) cursor->smdbc_impl;
3850Sstevel@tonic-gate DBT dbkey, dbdata;
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate (void) memset(&dbdata, '\0', sizeof dbdata);
3880Sstevel@tonic-gate (void) memset(&dbkey, '\0', sizeof dbkey);
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate db2_flags = smdb_cursor_get_flags_to_db2(flags);
3910Sstevel@tonic-gate result = dbc->c_get(dbc, &dbkey, &dbdata, db2_flags);
3920Sstevel@tonic-gate if (result == DB_NOTFOUND)
3930Sstevel@tonic-gate return SMDBE_LAST_ENTRY;
3940Sstevel@tonic-gate key->data = dbkey.data;
3950Sstevel@tonic-gate key->size = dbkey.size;
3960Sstevel@tonic-gate value->data = dbdata.data;
3970Sstevel@tonic-gate value->size = dbdata.size;
3980Sstevel@tonic-gate return db2_error_to_smdb(result);
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate int
smdb2_cursor_put(cursor,key,value,flags)4020Sstevel@tonic-gate smdb2_cursor_put(cursor, key, value, flags)
4030Sstevel@tonic-gate SMDB_CURSOR *cursor;
4040Sstevel@tonic-gate SMDB_DBENT *key;
4050Sstevel@tonic-gate SMDB_DBENT *value;
4060Sstevel@tonic-gate SMDB_FLAG flags;
4070Sstevel@tonic-gate {
4080Sstevel@tonic-gate DBC *dbc = (DBC *) cursor->smdbc_impl;
4090Sstevel@tonic-gate DBT dbkey, dbdata;
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate (void) memset(&dbdata, '\0', sizeof dbdata);
4120Sstevel@tonic-gate (void) memset(&dbkey, '\0', sizeof dbkey);
4130Sstevel@tonic-gate dbkey.data = key->data;
4140Sstevel@tonic-gate dbkey.size = key->size;
4150Sstevel@tonic-gate dbdata.data = value->data;
4160Sstevel@tonic-gate dbdata.size = value->size;
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate return db2_error_to_smdb(dbc->c_put(dbc, &dbkey, &dbdata, 0));
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate int
smdb2_cursor(database,cursor,flags)4220Sstevel@tonic-gate smdb2_cursor(database, cursor, flags)
4230Sstevel@tonic-gate SMDB_DATABASE *database;
4240Sstevel@tonic-gate SMDB_CURSOR **cursor;
4250Sstevel@tonic-gate SMDB_FLAG flags;
4260Sstevel@tonic-gate {
4270Sstevel@tonic-gate int result;
4280Sstevel@tonic-gate DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
4290Sstevel@tonic-gate DBC *db2_cursor;
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
4320Sstevel@tonic-gate result = db->cursor(db, NULL, &db2_cursor, 0);
4330Sstevel@tonic-gate # else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
4340Sstevel@tonic-gate result = db->cursor(db, NULL, &db2_cursor);
4350Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
4360Sstevel@tonic-gate if (result != 0)
4370Sstevel@tonic-gate return db2_error_to_smdb(result);
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate *cursor = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
4400Sstevel@tonic-gate if (*cursor == NULL)
4410Sstevel@tonic-gate return SMDBE_MALLOC;
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate (*cursor)->smdbc_close = smdb2_cursor_close;
4440Sstevel@tonic-gate (*cursor)->smdbc_del = smdb2_cursor_del;
4450Sstevel@tonic-gate (*cursor)->smdbc_get = smdb2_cursor_get;
4460Sstevel@tonic-gate (*cursor)->smdbc_put = smdb2_cursor_put;
4470Sstevel@tonic-gate (*cursor)->smdbc_impl = db2_cursor;
4480Sstevel@tonic-gate
4490Sstevel@tonic-gate return SMDBE_OK;
4500Sstevel@tonic-gate }
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2
4530Sstevel@tonic-gate static int
smdb_db_open_internal(db_name,db_type,db_flags,db_params,db)4540Sstevel@tonic-gate smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
4550Sstevel@tonic-gate char *db_name;
4560Sstevel@tonic-gate DBTYPE db_type;
4570Sstevel@tonic-gate int db_flags;
4580Sstevel@tonic-gate SMDB_DBPARAMS *db_params;
4590Sstevel@tonic-gate DB **db;
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate void *params;
4620Sstevel@tonic-gate DB_INFO db_info;
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate params = NULL;
4650Sstevel@tonic-gate (void) memset(&db_info, '\0', sizeof db_info);
4660Sstevel@tonic-gate if (db_params != NULL)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate db_info.db_cachesize = db_params->smdbp_cache_size;
4690Sstevel@tonic-gate if (db_type == DB_HASH)
4700Sstevel@tonic-gate db_info.h_nelem = db_params->smdbp_num_elements;
4710Sstevel@tonic-gate if (db_params->smdbp_allow_dup)
4720Sstevel@tonic-gate db_info.flags |= DB_DUP;
4730Sstevel@tonic-gate params = &db_info;
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate return db_open(db_name, db_type, db_flags, DBMMODE, NULL, params, db);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2
4800Sstevel@tonic-gate static int
smdb_db_open_internal(db_name,db_type,db_flags,db_params,db)4810Sstevel@tonic-gate smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
4820Sstevel@tonic-gate char *db_name;
4830Sstevel@tonic-gate DBTYPE db_type;
4840Sstevel@tonic-gate int db_flags;
4850Sstevel@tonic-gate SMDB_DBPARAMS *db_params;
4860Sstevel@tonic-gate DB **db;
4870Sstevel@tonic-gate {
4880Sstevel@tonic-gate int result;
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate result = db_create(db, NULL, 0);
4910Sstevel@tonic-gate if (result != 0 || *db == NULL)
4920Sstevel@tonic-gate return result;
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate if (db_params != NULL)
4950Sstevel@tonic-gate {
4960Sstevel@tonic-gate result = (*db)->set_cachesize(*db, 0,
4970Sstevel@tonic-gate db_params->smdbp_cache_size, 0);
4980Sstevel@tonic-gate if (result != 0)
4990Sstevel@tonic-gate {
5000Sstevel@tonic-gate (void) (*db)->close((*db), 0);
5010Sstevel@tonic-gate *db = NULL;
5020Sstevel@tonic-gate return db2_error_to_smdb(result);
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate if (db_type == DB_HASH)
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate result = (*db)->set_h_nelem(*db, db_params->smdbp_num_elements);
5070Sstevel@tonic-gate if (result != 0)
5080Sstevel@tonic-gate {
5090Sstevel@tonic-gate (void) (*db)->close(*db, 0);
5100Sstevel@tonic-gate *db = NULL;
5110Sstevel@tonic-gate return db2_error_to_smdb(result);
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate }
5140Sstevel@tonic-gate if (db_params->smdbp_allow_dup)
5150Sstevel@tonic-gate {
5160Sstevel@tonic-gate result = (*db)->set_flags(*db, DB_DUP);
5170Sstevel@tonic-gate if (result != 0)
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate (void) (*db)->close(*db, 0);
5200Sstevel@tonic-gate *db = NULL;
5210Sstevel@tonic-gate return db2_error_to_smdb(result);
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate }
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate result = (*db)->open(*db,
5270Sstevel@tonic-gate DBTXN /* transaction for DB 4.1 */
5280Sstevel@tonic-gate db_name, NULL, db_type, db_flags, DBMMODE);
5290Sstevel@tonic-gate if (result != 0)
5300Sstevel@tonic-gate {
5310Sstevel@tonic-gate (void) (*db)->close(*db, 0);
5320Sstevel@tonic-gate *db = NULL;
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate return db2_error_to_smdb(result);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */
5370Sstevel@tonic-gate /*
5380Sstevel@tonic-gate ** SMDB_DB_OPEN -- Opens a db database.
5390Sstevel@tonic-gate **
5400Sstevel@tonic-gate ** Parameters:
5410Sstevel@tonic-gate ** database -- An unallocated database pointer to a pointer.
5420Sstevel@tonic-gate ** db_name -- The name of the database without extension.
5430Sstevel@tonic-gate ** mode -- File permisions for a created database.
5440Sstevel@tonic-gate ** mode_mask -- Mode bits that must match on an opened database.
5450Sstevel@tonic-gate ** sff -- Flags for safefile.
5460Sstevel@tonic-gate ** type -- The type of database to open
5470Sstevel@tonic-gate ** See smdb_type_to_db2_type for valid types.
5480Sstevel@tonic-gate ** user_info -- User information for file permissions.
5490Sstevel@tonic-gate ** db_params --
5500Sstevel@tonic-gate ** An SMDB_DBPARAMS struct including params. These
5510Sstevel@tonic-gate ** are processed according to the type of the
5520Sstevel@tonic-gate ** database. Currently supported params (only for
5530Sstevel@tonic-gate ** HASH type) are:
5540Sstevel@tonic-gate ** num_elements
5550Sstevel@tonic-gate ** cache_size
5560Sstevel@tonic-gate **
5570Sstevel@tonic-gate ** Returns:
5580Sstevel@tonic-gate ** SMDBE_OK -- Success, other errno:
5590Sstevel@tonic-gate ** SMDBE_MALLOC -- Cannot allocate memory.
5600Sstevel@tonic-gate ** SMDBE_BAD_OPEN -- db_open didn't return an error, but
5610Sstevel@tonic-gate ** somehow the DB pointer is NULL.
5620Sstevel@tonic-gate ** Anything else: translated error from db2
5630Sstevel@tonic-gate */
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate int
smdb_db_open(database,db_name,mode,mode_mask,sff,type,user_info,db_params)5660Sstevel@tonic-gate smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info, db_params)
5670Sstevel@tonic-gate SMDB_DATABASE **database;
5680Sstevel@tonic-gate char *db_name;
5690Sstevel@tonic-gate int mode;
5700Sstevel@tonic-gate int mode_mask;
5710Sstevel@tonic-gate long sff;
5720Sstevel@tonic-gate SMDB_DBTYPE type;
5730Sstevel@tonic-gate SMDB_USER_INFO *user_info;
5740Sstevel@tonic-gate SMDB_DBPARAMS *db_params;
5750Sstevel@tonic-gate {
5760Sstevel@tonic-gate bool lockcreated = false;
5770Sstevel@tonic-gate int result;
5780Sstevel@tonic-gate int db_flags;
5790Sstevel@tonic-gate int lock_fd;
5800Sstevel@tonic-gate int db_fd;
5810Sstevel@tonic-gate int major_v, minor_v, patch_v;
5820Sstevel@tonic-gate SMDB_DATABASE *smdb_db;
5830Sstevel@tonic-gate SMDB_DB2_DATABASE *db2;
5840Sstevel@tonic-gate DB *db;
5850Sstevel@tonic-gate DBTYPE db_type;
5860Sstevel@tonic-gate struct stat stat_info;
5870Sstevel@tonic-gate char db_file_name[MAXPATHLEN];
5880Sstevel@tonic-gate
5890Sstevel@tonic-gate (void) db_version(&major_v, &minor_v, &patch_v);
5900Sstevel@tonic-gate if (major_v != DB_VERSION_MAJOR || minor_v != DB_VERSION_MINOR)
5910Sstevel@tonic-gate return SMDBE_VERSION_MISMATCH;
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate *database = NULL;
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate result = smdb_add_extension(db_file_name, sizeof db_file_name,
5960Sstevel@tonic-gate db_name, SMDB2_FILE_EXTENSION);
5970Sstevel@tonic-gate if (result != SMDBE_OK)
5980Sstevel@tonic-gate return result;
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate result = smdb_setup_file(db_name, SMDB2_FILE_EXTENSION,
6010Sstevel@tonic-gate mode_mask, sff, user_info, &stat_info);
6020Sstevel@tonic-gate if (result != SMDBE_OK)
6030Sstevel@tonic-gate return result;
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate lock_fd = -1;
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate if (stat_info.st_mode == ST_MODE_NOFILE &&
6080Sstevel@tonic-gate bitset(mode, O_CREAT))
6090Sstevel@tonic-gate lockcreated = true;
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate result = smdb_lock_file(&lock_fd, db_name, mode, sff,
6120Sstevel@tonic-gate SMDB2_FILE_EXTENSION);
6130Sstevel@tonic-gate if (result != SMDBE_OK)
6140Sstevel@tonic-gate return result;
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate if (lockcreated)
6170Sstevel@tonic-gate {
6180Sstevel@tonic-gate mode |= O_TRUNC;
6190Sstevel@tonic-gate mode &= ~(O_CREAT|O_EXCL);
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate smdb_db = smdb_malloc_database();
623*11440SJohn.Beck@Sun.COM db2 = smdb2_malloc_database();
624*11440SJohn.Beck@Sun.COM if (db2 == NULL || smdb_db == NULL)
625*11440SJohn.Beck@Sun.COM {
626*11440SJohn.Beck@Sun.COM smdb_unlock_file(lock_fd);
627*11440SJohn.Beck@Sun.COM smdb_free_database(smdb_db); /* ok to be NULL */
6280Sstevel@tonic-gate return SMDBE_MALLOC;
629*11440SJohn.Beck@Sun.COM }
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate db2->smdb2_lock_fd = lock_fd;
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate db_type = smdb_type_to_db2_type(type);
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate db = NULL;
6360Sstevel@tonic-gate
6370Sstevel@tonic-gate db_flags = 0;
6380Sstevel@tonic-gate if (bitset(O_CREAT, mode))
6390Sstevel@tonic-gate db_flags |= DB_CREATE;
6400Sstevel@tonic-gate if (bitset(O_TRUNC, mode))
6410Sstevel@tonic-gate db_flags |= DB_TRUNCATE;
6420Sstevel@tonic-gate if (mode == O_RDONLY)
6430Sstevel@tonic-gate db_flags |= DB_RDONLY;
6440Sstevel@tonic-gate SM_DB_FLAG_ADD(db_flags);
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate result = smdb_db_open_internal(db_file_name, db_type,
6470Sstevel@tonic-gate db_flags, db_params, &db);
6480Sstevel@tonic-gate
6490Sstevel@tonic-gate if (result == 0 && db != NULL)
6500Sstevel@tonic-gate {
6510Sstevel@tonic-gate result = db->fd(db, &db_fd);
6520Sstevel@tonic-gate if (result == 0)
6530Sstevel@tonic-gate result = SMDBE_OK;
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate else
6560Sstevel@tonic-gate {
6570Sstevel@tonic-gate /* Try and narrow down on the problem */
6580Sstevel@tonic-gate if (result != 0)
6590Sstevel@tonic-gate result = db2_error_to_smdb(result);
6600Sstevel@tonic-gate else
6610Sstevel@tonic-gate result = SMDBE_BAD_OPEN;
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate if (result == SMDBE_OK)
6650Sstevel@tonic-gate result = smdb_filechanged(db_name, SMDB2_FILE_EXTENSION, db_fd,
6660Sstevel@tonic-gate &stat_info);
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate if (result == SMDBE_OK)
6690Sstevel@tonic-gate {
6700Sstevel@tonic-gate /* Everything is ok. Setup driver */
6710Sstevel@tonic-gate db2->smdb2_db = db;
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate smdb_db->smdb_close = smdb2_close;
6740Sstevel@tonic-gate smdb_db->smdb_del = smdb2_del;
6750Sstevel@tonic-gate smdb_db->smdb_fd = smdb2_fd;
6760Sstevel@tonic-gate smdb_db->smdb_lockfd = smdb2_lockfd;
6770Sstevel@tonic-gate smdb_db->smdb_get = smdb2_get;
6780Sstevel@tonic-gate smdb_db->smdb_put = smdb2_put;
6790Sstevel@tonic-gate smdb_db->smdb_set_owner = smdb2_set_owner;
6800Sstevel@tonic-gate smdb_db->smdb_sync = smdb2_sync;
6810Sstevel@tonic-gate smdb_db->smdb_cursor = smdb2_cursor;
6820Sstevel@tonic-gate smdb_db->smdb_impl = db2;
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate *database = smdb_db;
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate return SMDBE_OK;
6870Sstevel@tonic-gate }
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate if (db != NULL)
6900Sstevel@tonic-gate db->close(db, 0);
6910Sstevel@tonic-gate
6920Sstevel@tonic-gate smdb_unlock_file(db2->smdb2_lock_fd);
6930Sstevel@tonic-gate free(db2);
6940Sstevel@tonic-gate smdb_free_database(smdb_db);
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate return result;
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate #endif /* (DB_VERSION_MAJOR >= 2) */
700