2 ** Copyright (c) 1999-2003, 2009 Proofpoint, Inc. and its suppliers.
3 ** All rights reserved.
5 ** By using this file, you agree to the terms and conditions set
6 ** forth in the LICENSE file which can be found at the top level of
7 ** the sendmail distribution.
11 SM_RCSID("@(#)$Id: smdb2.c,v 8.83 2013-11-22 20:51:49 ca Exp $")
18 #include <sendmail/sendmail.h>
19 #include <libsmdb/smdb.h>
21 #if (DB_VERSION_MAJOR >= 2)
23 struct smdb_db2_database
28 typedef struct smdb_db2_database SMDB_DB2_DATABASE;
31 ** SMDB_TYPE_TO_DB2_TYPE -- Translates smdb database type to db2 type.
34 ** type -- The type to translate.
37 ** The DB2 type that corresponsds to the passed in SMDB type.
38 ** Returns -1 if there is no equivalent type.
43 smdb_type_to_db2_type(type)
46 if (type == SMDB_TYPE_DEFAULT)
49 if (SMDB_IS_TYPE_HASH(type))
52 if (SMDB_IS_TYPE_BTREE(type))
58 ** DB2_ERROR_TO_SMDB -- Translates db2 errors to smdbe errors
61 ** error -- The error to translate.
64 ** The SMDBE error corresponding to the db2 error.
65 ** If we don't have a corresponding error, it returns errno.
70 db2_error_to_smdb(error)
79 result = SMDBE_INCOMPLETE;
85 result = SMDBE_NOT_FOUND;
91 result = SMDBE_KEY_EMPTY;
97 result = SMDBE_KEY_EXIST;
101 # ifdef DB_LOCK_DEADLOCK
102 case DB_LOCK_DEADLOCK:
103 result = SMDBE_LOCK_DEADLOCK;
107 # ifdef DB_LOCK_NOTGRANTED
108 case DB_LOCK_NOTGRANTED:
109 result = SMDBE_LOCK_NOT_GRANTED;
113 # ifdef DB_LOCK_NOTHELD
114 case DB_LOCK_NOTHELD:
115 result = SMDBE_LOCK_NOT_HELD;
119 # ifdef DB_RUNRECOVERY
121 result = SMDBE_RUN_RECOVERY;
125 # ifdef DB_OLD_VERSION
127 result = SMDBE_OLD_VERSION;
141 ** SMDB_PUT_FLAGS_TO_DB2_FLAGS -- Translates smdb put flags to db2 put flags.
144 ** flags -- The flags to translate.
147 ** The db2 flags that are equivalent to the smdb flags.
150 ** Any invalid flags are ignored.
155 smdb_put_flags_to_db2_flags(flags)
162 if (bitset(SMDBF_NO_OVERWRITE, flags))
163 return_flags |= DB_NOOVERWRITE;
168 ** SMDB_CURSOR_GET_FLAGS_TO_DB2 -- Translates smdb cursor get flags to db2
172 ** flags -- The flags to translate.
175 ** The db2 flags that are equivalent to the smdb flags.
178 ** -1 is returned if flag is unknown.
183 smdb_cursor_get_flags_to_db2(flags)
188 case SMDB_CURSOR_GET_FIRST:
191 case SMDB_CURSOR_GET_LAST:
194 case SMDB_CURSOR_GET_NEXT:
197 case SMDB_CURSOR_GET_RANGE:
206 ** Except for smdb_db_open, the rest of these functions correspond to the
207 ** interface laid out in smdb.h.
210 static SMDB_DB2_DATABASE *
211 smdb2_malloc_database()
213 SMDB_DB2_DATABASE *db2;
215 db2 = (SMDB_DB2_DATABASE *) malloc(sizeof(SMDB_DB2_DATABASE));
217 db2->smdb2_lock_fd = -1;
223 smdb2_close(database)
224 SMDB_DATABASE *database;
227 SMDB_DB2_DATABASE *db2 = (SMDB_DB2_DATABASE *) database->smdb_impl;
228 DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
230 result = db2_error_to_smdb(db->close(db, 0));
231 if (db2->smdb2_lock_fd != -1)
232 close(db2->smdb2_lock_fd);
235 database->smdb_impl = NULL;
241 smdb2_del(database, key, flags)
242 SMDB_DATABASE *database;
246 DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
249 (void) memset(&dbkey, '\0', sizeof dbkey);
250 dbkey.data = key->data;
251 dbkey.size = key->size;
252 return db2_error_to_smdb(db->del(db, NULL, &dbkey, flags));
256 smdb2_fd(database, fd)
257 SMDB_DATABASE *database;
260 DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
262 return db2_error_to_smdb(db->fd(db, fd));
266 smdb2_lockfd(database)
267 SMDB_DATABASE *database;
269 SMDB_DB2_DATABASE *db2 = (SMDB_DB2_DATABASE *) database->smdb_impl;
271 return db2->smdb2_lock_fd;
275 smdb2_get(database, key, data, flags)
276 SMDB_DATABASE *database;
282 DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
285 (void) memset(&dbdata, '\0', sizeof dbdata);
286 (void) memset(&dbkey, '\0', sizeof dbkey);
287 dbkey.data = key->data;
288 dbkey.size = key->size;
290 result = db->get(db, NULL, &dbkey, &dbdata, flags);
291 data->data = dbdata.data;
292 data->size = dbdata.size;
293 return db2_error_to_smdb(result);
297 smdb2_put(database, key, data, flags)
298 SMDB_DATABASE *database;
303 DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
306 (void) memset(&dbdata, '\0', sizeof dbdata);
307 (void) memset(&dbkey, '\0', sizeof dbkey);
308 dbkey.data = key->data;
309 dbkey.size = key->size;
310 dbdata.data = data->data;
311 dbdata.size = data->size;
313 return db2_error_to_smdb(db->put(db, NULL, &dbkey, &dbdata,
314 smdb_put_flags_to_db2_flags(flags)));
319 smdb2_set_owner(database, uid, gid)
320 SMDB_DATABASE *database;
327 DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
329 result = db->fd(db, &fd);
333 result = fchown(fd, uid, gid);
336 # endif /* HASFCHOWN */
342 smdb2_sync(database, flags)
343 SMDB_DATABASE *database;
346 DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
348 return db2_error_to_smdb(db->sync(db, flags));
352 smdb2_cursor_close(cursor)
356 DBC *dbc = (DBC *) cursor->smdbc_impl;
358 ret = db2_error_to_smdb(dbc->c_close(dbc));
364 smdb2_cursor_del(cursor, flags)
368 DBC *dbc = (DBC *) cursor->smdbc_impl;
370 return db2_error_to_smdb(dbc->c_del(dbc, 0));
374 smdb2_cursor_get(cursor, key, value, flags)
382 DBC *dbc = (DBC *) cursor->smdbc_impl;
385 (void) memset(&dbdata, '\0', sizeof dbdata);
386 (void) memset(&dbkey, '\0', sizeof dbkey);
388 db2_flags = smdb_cursor_get_flags_to_db2(flags);
389 result = dbc->c_get(dbc, &dbkey, &dbdata, db2_flags);
390 if (result == DB_NOTFOUND)
391 return SMDBE_LAST_ENTRY;
392 key->data = dbkey.data;
393 key->size = dbkey.size;
394 value->data = dbdata.data;
395 value->size = dbdata.size;
396 return db2_error_to_smdb(result);
400 smdb2_cursor_put(cursor, key, value, flags)
406 DBC *dbc = (DBC *) cursor->smdbc_impl;
409 (void) memset(&dbdata, '\0', sizeof dbdata);
410 (void) memset(&dbkey, '\0', sizeof dbkey);
411 dbkey.data = key->data;
412 dbkey.size = key->size;
413 dbdata.data = value->data;
414 dbdata.size = value->size;
416 return db2_error_to_smdb(dbc->c_put(dbc, &dbkey, &dbdata, 0));
420 smdb2_cursor(database, cursor, flags)
421 SMDB_DATABASE *database;
422 SMDB_CURSOR **cursor;
426 DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
429 # if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
430 result = db->cursor(db, NULL, &db2_cursor, 0);
432 result = db->cursor(db, NULL, &db2_cursor);
435 return db2_error_to_smdb(result);
437 *cursor = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
441 (*cursor)->smdbc_close = smdb2_cursor_close;
442 (*cursor)->smdbc_del = smdb2_cursor_del;
443 (*cursor)->smdbc_get = smdb2_cursor_get;
444 (*cursor)->smdbc_put = smdb2_cursor_put;
445 (*cursor)->smdbc_impl = db2_cursor;
450 # if DB_VERSION_MAJOR == 2
452 smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
456 SMDB_DBPARAMS *db_params;
463 (void) memset(&db_info, '\0', sizeof db_info);
464 if (db_params != NULL)
466 db_info.db_cachesize = db_params->smdbp_cache_size;
467 if (db_type == DB_HASH)
468 db_info.h_nelem = db_params->smdbp_num_elements;
469 if (db_params->smdbp_allow_dup)
470 db_info.flags |= DB_DUP;
473 return db_open(db_name, db_type, db_flags, DBMMODE, NULL, params, db);
475 # endif /* DB_VERSION_MAJOR == 2 */
477 # if DB_VERSION_MAJOR > 2
481 #if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
485 #if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
494 /* do not print/log any errors... */
499 smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
503 SMDB_DBPARAMS *db_params;
508 result = db_create(db, NULL, 0);
509 if (result != 0 || *db == NULL)
512 (*db)->set_errcall(*db, db_err_cb);
513 if (db_params != NULL)
515 result = (*db)->set_cachesize(*db, 0,
516 db_params->smdbp_cache_size, 0);
519 if (db_type == DB_HASH)
521 result = (*db)->set_h_nelem(*db, db_params->smdbp_num_elements);
525 if (db_params->smdbp_allow_dup)
527 result = (*db)->set_flags(*db, DB_DUP);
533 result = (*db)->open(*db,
534 DBTXN /* transaction for DB 4.1 */
535 db_name, NULL, db_type, db_flags, DBMMODE);
539 (void) (*db)->close(*db, 0);
542 return db2_error_to_smdb(result);
544 # endif /* DB_VERSION_MAJOR > 2 */
547 ** SMDB_DB_OPEN -- Opens a db database.
550 ** database -- An unallocated database pointer to a pointer.
551 ** db_name -- The name of the database without extension.
552 ** mode -- File permisions for a created database.
553 ** mode_mask -- Mode bits that must match on an opened database.
554 ** sff -- Flags for safefile.
555 ** type -- The type of database to open
556 ** See smdb_type_to_db2_type for valid types.
557 ** user_info -- User information for file permissions.
559 ** An SMDB_DBPARAMS struct including params. These
560 ** are processed according to the type of the
561 ** database. Currently supported params (only for
567 ** SMDBE_OK -- Success, other errno:
568 ** SMDBE_MALLOC -- Cannot allocate memory.
569 ** SMDBE_BAD_OPEN -- db_open didn't return an error, but
570 ** somehow the DB pointer is NULL.
571 ** Anything else: translated error from db2
575 smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info, db_params)
576 SMDB_DATABASE **database;
582 SMDB_USER_INFO *user_info;
583 SMDB_DBPARAMS *db_params;
585 bool lockcreated = false;
590 int major_v, minor_v, patch_v;
591 SMDB_DATABASE *smdb_db;
592 SMDB_DB2_DATABASE *db2;
595 struct stat stat_info;
596 char db_file_name[MAXPATHLEN];
598 (void) db_version(&major_v, &minor_v, &patch_v);
599 if (major_v != DB_VERSION_MAJOR || minor_v != DB_VERSION_MINOR)
600 return SMDBE_VERSION_MISMATCH;
604 result = smdb_add_extension(db_file_name, sizeof db_file_name,
605 db_name, SMDB2_FILE_EXTENSION);
606 if (result != SMDBE_OK)
609 result = smdb_setup_file(db_name, SMDB2_FILE_EXTENSION,
610 mode_mask, sff, user_info, &stat_info);
611 if (result != SMDBE_OK)
616 if (stat_info.st_mode == ST_MODE_NOFILE &&
617 bitset(mode, O_CREAT))
620 result = smdb_lock_file(&lock_fd, db_name, mode, sff,
621 SMDB2_FILE_EXTENSION);
622 if (result != SMDBE_OK)
628 mode &= ~(O_CREAT|O_EXCL);
631 smdb_db = smdb_malloc_database();
632 db2 = smdb2_malloc_database();
633 if (db2 == NULL || smdb_db == NULL)
635 smdb_unlock_file(lock_fd);
636 smdb_free_database(smdb_db); /* ok to be NULL */
642 db2->smdb2_lock_fd = lock_fd;
644 db_type = smdb_type_to_db2_type(type);
649 if (bitset(O_CREAT, mode))
650 db_flags |= DB_CREATE;
651 if (bitset(O_TRUNC, mode))
652 db_flags |= DB_TRUNCATE;
653 if (mode == O_RDONLY)
654 db_flags |= DB_RDONLY;
655 SM_DB_FLAG_ADD(db_flags);
657 result = smdb_db_open_internal(db_file_name, db_type,
658 db_flags, db_params, &db);
660 if (result == 0 && db != NULL)
662 result = db->fd(db, &db_fd);
668 /* Try and narrow down on the problem */
670 result = db2_error_to_smdb(result);
672 result = SMDBE_BAD_OPEN;
675 if (result == SMDBE_OK)
676 result = smdb_filechanged(db_name, SMDB2_FILE_EXTENSION, db_fd,
679 if (result == SMDBE_OK)
681 /* Everything is ok. Setup driver */
684 smdb_db->smdb_close = smdb2_close;
685 smdb_db->smdb_del = smdb2_del;
686 smdb_db->smdb_fd = smdb2_fd;
687 smdb_db->smdb_lockfd = smdb2_lockfd;
688 smdb_db->smdb_get = smdb2_get;
689 smdb_db->smdb_put = smdb2_put;
690 smdb_db->smdb_set_owner = smdb2_set_owner;
691 smdb_db->smdb_sync = smdb2_sync;
692 smdb_db->smdb_cursor = smdb2_cursor;
693 smdb_db->smdb_impl = db2;
703 smdb_unlock_file(db2->smdb2_lock_fd);
705 smdb_free_database(smdb_db);
710 #endif /* (DB_VERSION_MAJOR >= 2) */