2 ** Copyright (c) 1999-2003 Sendmail, 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.79 2003/06/13 21:33:11 ca Exp $")
18 #include <sendmail/sendmail.h>
19 #include <libsmdb/smdb.h>
21 #if (DB_VERSION_MAJOR >= 2)
23 # define SMDB2_FILE_EXTENSION "db"
25 struct smdb_db2_database
30 typedef struct smdb_db2_database SMDB_DB2_DATABASE
;
33 ** SMDB_TYPE_TO_DB2_TYPE -- Translates smdb database type to db2 type.
36 ** type -- The type to translate.
39 ** The DB2 type that corresponsds to the passed in SMDB type.
40 ** Returns -1 if there is no equivalent type.
45 smdb_type_to_db2_type(type
)
48 if (type
== SMDB_TYPE_DEFAULT
)
51 if (strncmp(type
, SMDB_TYPE_HASH
, SMDB_TYPE_HASH_LEN
) == 0)
54 if (strncmp(type
, SMDB_TYPE_BTREE
, SMDB_TYPE_BTREE_LEN
) == 0)
60 ** DB2_ERROR_TO_SMDB -- Translates db2 errors to smdbe errors
63 ** error -- The error to translate.
66 ** The SMDBE error corresponding to the db2 error.
67 ** If we don't have a corresponding error, it returs errno.
72 db2_error_to_smdb(error
)
81 result
= SMDBE_INCOMPLETE
;
83 # endif /* DB_INCOMPLETE */
87 result
= SMDBE_NOT_FOUND
;
89 # endif /* DB_NOTFOUND */
93 result
= SMDBE_KEY_EMPTY
;
95 # endif /* DB_KEYEMPTY */
99 result
= SMDBE_KEY_EXIST
;
101 # endif /* DB_KEYEXIST */
103 # ifdef DB_LOCK_DEADLOCK
104 case DB_LOCK_DEADLOCK
:
105 result
= SMDBE_LOCK_DEADLOCK
;
107 # endif /* DB_LOCK_DEADLOCK */
109 # ifdef DB_LOCK_NOTGRANTED
110 case DB_LOCK_NOTGRANTED
:
111 result
= SMDBE_LOCK_NOT_GRANTED
;
113 # endif /* DB_LOCK_NOTGRANTED */
115 # ifdef DB_LOCK_NOTHELD
116 case DB_LOCK_NOTHELD
:
117 result
= SMDBE_LOCK_NOT_HELD
;
119 # endif /* DB_LOCK_NOTHELD */
121 # ifdef DB_RUNRECOVERY
123 result
= SMDBE_RUN_RECOVERY
;
125 # endif /* DB_RUNRECOVERY */
127 # ifdef DB_OLD_VERSION
129 result
= SMDBE_OLD_VERSION
;
131 # endif /* DB_OLD_VERSION */
143 ** SMDB_PUT_FLAGS_TO_DB2_FLAGS -- Translates smdb put flags to db2 put flags.
146 ** flags -- The flags to translate.
149 ** The db2 flags that are equivalent to the smdb flags.
152 ** Any invalid flags are ignored.
157 smdb_put_flags_to_db2_flags(flags
)
164 if (bitset(SMDBF_NO_OVERWRITE
, flags
))
165 return_flags
|= DB_NOOVERWRITE
;
170 ** SMDB_CURSOR_GET_FLAGS_TO_DB2 -- Translates smdb cursor get flags to db2
174 ** flags -- The flags to translate.
177 ** The db2 flags that are equivalent to the smdb flags.
180 ** -1 is returned if flag is unknown.
185 smdb_cursor_get_flags_to_db2(flags
)
190 case SMDB_CURSOR_GET_FIRST
:
193 case SMDB_CURSOR_GET_LAST
:
196 case SMDB_CURSOR_GET_NEXT
:
199 case SMDB_CURSOR_GET_RANGE
:
208 ** Except for smdb_db_open, the rest of these functions correspond to the
209 ** interface laid out in smdb.h.
213 smdb2_malloc_database()
215 SMDB_DB2_DATABASE
*db2
;
217 db2
= (SMDB_DB2_DATABASE
*) malloc(sizeof(SMDB_DB2_DATABASE
));
219 db2
->smdb2_lock_fd
= -1;
225 smdb2_close(database
)
226 SMDB_DATABASE
*database
;
229 SMDB_DB2_DATABASE
*db2
= (SMDB_DB2_DATABASE
*) database
->smdb_impl
;
230 DB
*db
= ((SMDB_DB2_DATABASE
*) database
->smdb_impl
)->smdb2_db
;
232 result
= db2_error_to_smdb(db
->close(db
, 0));
233 if (db2
->smdb2_lock_fd
!= -1)
234 close(db2
->smdb2_lock_fd
);
237 database
->smdb_impl
= NULL
;
243 smdb2_del(database
, key
, flags
)
244 SMDB_DATABASE
*database
;
248 DB
*db
= ((SMDB_DB2_DATABASE
*) database
->smdb_impl
)->smdb2_db
;
251 (void) memset(&dbkey
, '\0', sizeof dbkey
);
252 dbkey
.data
= key
->data
;
253 dbkey
.size
= key
->size
;
254 return db2_error_to_smdb(db
->del(db
, NULL
, &dbkey
, flags
));
258 smdb2_fd(database
, fd
)
259 SMDB_DATABASE
*database
;
262 DB
*db
= ((SMDB_DB2_DATABASE
*) database
->smdb_impl
)->smdb2_db
;
264 return db2_error_to_smdb(db
->fd(db
, fd
));
268 smdb2_lockfd(database
)
269 SMDB_DATABASE
*database
;
271 SMDB_DB2_DATABASE
*db2
= (SMDB_DB2_DATABASE
*) database
->smdb_impl
;
273 return db2
->smdb2_lock_fd
;
277 smdb2_get(database
, key
, data
, flags
)
278 SMDB_DATABASE
*database
;
284 DB
*db
= ((SMDB_DB2_DATABASE
*) database
->smdb_impl
)->smdb2_db
;
287 (void) memset(&dbdata
, '\0', sizeof dbdata
);
288 (void) memset(&dbkey
, '\0', sizeof dbkey
);
289 dbkey
.data
= key
->data
;
290 dbkey
.size
= key
->size
;
292 result
= db
->get(db
, NULL
, &dbkey
, &dbdata
, flags
);
293 data
->data
= dbdata
.data
;
294 data
->size
= dbdata
.size
;
295 return db2_error_to_smdb(result
);
299 smdb2_put(database
, key
, data
, flags
)
300 SMDB_DATABASE
*database
;
305 DB
*db
= ((SMDB_DB2_DATABASE
*) database
->smdb_impl
)->smdb2_db
;
308 (void) memset(&dbdata
, '\0', sizeof dbdata
);
309 (void) memset(&dbkey
, '\0', sizeof dbkey
);
310 dbkey
.data
= key
->data
;
311 dbkey
.size
= key
->size
;
312 dbdata
.data
= data
->data
;
313 dbdata
.size
= data
->size
;
315 return db2_error_to_smdb(db
->put(db
, NULL
, &dbkey
, &dbdata
,
316 smdb_put_flags_to_db2_flags(flags
)));
321 smdb2_set_owner(database
, uid
, gid
)
322 SMDB_DATABASE
*database
;
329 DB
*db
= ((SMDB_DB2_DATABASE
*) database
->smdb_impl
)->smdb2_db
;
331 result
= db
->fd(db
, &fd
);
335 result
= fchown(fd
, uid
, gid
);
338 # endif /* HASFCHOWN */
344 smdb2_sync(database
, flags
)
345 SMDB_DATABASE
*database
;
348 DB
*db
= ((SMDB_DB2_DATABASE
*) database
->smdb_impl
)->smdb2_db
;
350 return db2_error_to_smdb(db
->sync(db
, flags
));
354 smdb2_cursor_close(cursor
)
358 DBC
*dbc
= (DBC
*) cursor
->smdbc_impl
;
360 ret
= db2_error_to_smdb(dbc
->c_close(dbc
));
366 smdb2_cursor_del(cursor
, flags
)
370 DBC
*dbc
= (DBC
*) cursor
->smdbc_impl
;
372 return db2_error_to_smdb(dbc
->c_del(dbc
, 0));
376 smdb2_cursor_get(cursor
, key
, value
, flags
)
384 DBC
*dbc
= (DBC
*) cursor
->smdbc_impl
;
387 (void) memset(&dbdata
, '\0', sizeof dbdata
);
388 (void) memset(&dbkey
, '\0', sizeof dbkey
);
390 db2_flags
= smdb_cursor_get_flags_to_db2(flags
);
391 result
= dbc
->c_get(dbc
, &dbkey
, &dbdata
, db2_flags
);
392 if (result
== DB_NOTFOUND
)
393 return SMDBE_LAST_ENTRY
;
394 key
->data
= dbkey
.data
;
395 key
->size
= dbkey
.size
;
396 value
->data
= dbdata
.data
;
397 value
->size
= dbdata
.size
;
398 return db2_error_to_smdb(result
);
402 smdb2_cursor_put(cursor
, key
, value
, flags
)
408 DBC
*dbc
= (DBC
*) cursor
->smdbc_impl
;
411 (void) memset(&dbdata
, '\0', sizeof dbdata
);
412 (void) memset(&dbkey
, '\0', sizeof dbkey
);
413 dbkey
.data
= key
->data
;
414 dbkey
.size
= key
->size
;
415 dbdata
.data
= value
->data
;
416 dbdata
.size
= value
->size
;
418 return db2_error_to_smdb(dbc
->c_put(dbc
, &dbkey
, &dbdata
, 0));
422 smdb2_cursor(database
, cursor
, flags
)
423 SMDB_DATABASE
*database
;
424 SMDB_CURSOR
**cursor
;
428 DB
*db
= ((SMDB_DB2_DATABASE
*) database
->smdb_impl
)->smdb2_db
;
431 # if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
432 result
= db
->cursor(db
, NULL
, &db2_cursor
, 0);
433 # else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
434 result
= db
->cursor(db
, NULL
, &db2_cursor
);
435 # endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
437 return db2_error_to_smdb(result
);
439 *cursor
= (SMDB_CURSOR
*) malloc(sizeof(SMDB_CURSOR
));
443 (*cursor
)->smdbc_close
= smdb2_cursor_close
;
444 (*cursor
)->smdbc_del
= smdb2_cursor_del
;
445 (*cursor
)->smdbc_get
= smdb2_cursor_get
;
446 (*cursor
)->smdbc_put
= smdb2_cursor_put
;
447 (*cursor
)->smdbc_impl
= db2_cursor
;
452 # if DB_VERSION_MAJOR == 2
454 smdb_db_open_internal(db_name
, db_type
, db_flags
, db_params
, db
)
458 SMDB_DBPARAMS
*db_params
;
465 (void) memset(&db_info
, '\0', sizeof db_info
);
466 if (db_params
!= NULL
)
468 db_info
.db_cachesize
= db_params
->smdbp_cache_size
;
469 if (db_type
== DB_HASH
)
470 db_info
.h_nelem
= db_params
->smdbp_num_elements
;
471 if (db_params
->smdbp_allow_dup
)
472 db_info
.flags
|= DB_DUP
;
475 return db_open(db_name
, db_type
, db_flags
, DBMMODE
, NULL
, params
, db
);
477 # endif /* DB_VERSION_MAJOR == 2 */
479 # if DB_VERSION_MAJOR > 2
481 smdb_db_open_internal(db_name
, db_type
, db_flags
, db_params
, db
)
485 SMDB_DBPARAMS
*db_params
;
490 result
= db_create(db
, NULL
, 0);
491 if (result
!= 0 || *db
== NULL
)
494 if (db_params
!= NULL
)
496 result
= (*db
)->set_cachesize(*db
, 0,
497 db_params
->smdbp_cache_size
, 0);
500 (void) (*db
)->close((*db
), 0);
502 return db2_error_to_smdb(result
);
504 if (db_type
== DB_HASH
)
506 result
= (*db
)->set_h_nelem(*db
, db_params
->smdbp_num_elements
);
509 (void) (*db
)->close(*db
, 0);
511 return db2_error_to_smdb(result
);
514 if (db_params
->smdbp_allow_dup
)
516 result
= (*db
)->set_flags(*db
, DB_DUP
);
519 (void) (*db
)->close(*db
, 0);
521 return db2_error_to_smdb(result
);
526 result
= (*db
)->open(*db
,
527 DBTXN
/* transaction for DB 4.1 */
528 db_name
, NULL
, db_type
, db_flags
, DBMMODE
);
531 (void) (*db
)->close(*db
, 0);
534 return db2_error_to_smdb(result
);
536 # endif /* DB_VERSION_MAJOR > 2 */
538 ** SMDB_DB_OPEN -- Opens a db database.
541 ** database -- An unallocated database pointer to a pointer.
542 ** db_name -- The name of the database without extension.
543 ** mode -- File permisions for a created database.
544 ** mode_mask -- Mode bits that must match on an opened database.
545 ** sff -- Flags for safefile.
546 ** type -- The type of database to open
547 ** See smdb_type_to_db2_type for valid types.
548 ** user_info -- User information for file permissions.
550 ** An SMDB_DBPARAMS struct including params. These
551 ** are processed according to the type of the
552 ** database. Currently supported params (only for
558 ** SMDBE_OK -- Success, other errno:
559 ** SMDBE_MALLOC -- Cannot allocate memory.
560 ** SMDBE_BAD_OPEN -- db_open didn't return an error, but
561 ** somehow the DB pointer is NULL.
562 ** Anything else: translated error from db2
566 smdb_db_open(database
, db_name
, mode
, mode_mask
, sff
, type
, user_info
, db_params
)
567 SMDB_DATABASE
**database
;
573 SMDB_USER_INFO
*user_info
;
574 SMDB_DBPARAMS
*db_params
;
576 bool lockcreated
= false;
581 int major_v
, minor_v
, patch_v
;
582 SMDB_DATABASE
*smdb_db
;
583 SMDB_DB2_DATABASE
*db2
;
586 struct stat stat_info
;
587 char db_file_name
[MAXPATHLEN
];
589 (void) db_version(&major_v
, &minor_v
, &patch_v
);
590 if (major_v
!= DB_VERSION_MAJOR
|| minor_v
!= DB_VERSION_MINOR
)
591 return SMDBE_VERSION_MISMATCH
;
595 result
= smdb_add_extension(db_file_name
, sizeof db_file_name
,
596 db_name
, SMDB2_FILE_EXTENSION
);
597 if (result
!= SMDBE_OK
)
600 result
= smdb_setup_file(db_name
, SMDB2_FILE_EXTENSION
,
601 mode_mask
, sff
, user_info
, &stat_info
);
602 if (result
!= SMDBE_OK
)
607 if (stat_info
.st_mode
== ST_MODE_NOFILE
&&
608 bitset(mode
, O_CREAT
))
611 result
= smdb_lock_file(&lock_fd
, db_name
, mode
, sff
,
612 SMDB2_FILE_EXTENSION
);
613 if (result
!= SMDBE_OK
)
619 mode
&= ~(O_CREAT
|O_EXCL
);
622 smdb_db
= smdb_malloc_database();
626 db2
= smdb2_malloc_database();
630 db2
->smdb2_lock_fd
= lock_fd
;
632 db_type
= smdb_type_to_db2_type(type
);
637 if (bitset(O_CREAT
, mode
))
638 db_flags
|= DB_CREATE
;
639 if (bitset(O_TRUNC
, mode
))
640 db_flags
|= DB_TRUNCATE
;
641 if (mode
== O_RDONLY
)
642 db_flags
|= DB_RDONLY
;
643 SM_DB_FLAG_ADD(db_flags
);
645 result
= smdb_db_open_internal(db_file_name
, db_type
,
646 db_flags
, db_params
, &db
);
648 if (result
== 0 && db
!= NULL
)
650 result
= db
->fd(db
, &db_fd
);
656 /* Try and narrow down on the problem */
658 result
= db2_error_to_smdb(result
);
660 result
= SMDBE_BAD_OPEN
;
663 if (result
== SMDBE_OK
)
664 result
= smdb_filechanged(db_name
, SMDB2_FILE_EXTENSION
, db_fd
,
667 if (result
== SMDBE_OK
)
669 /* Everything is ok. Setup driver */
672 smdb_db
->smdb_close
= smdb2_close
;
673 smdb_db
->smdb_del
= smdb2_del
;
674 smdb_db
->smdb_fd
= smdb2_fd
;
675 smdb_db
->smdb_lockfd
= smdb2_lockfd
;
676 smdb_db
->smdb_get
= smdb2_get
;
677 smdb_db
->smdb_put
= smdb2_put
;
678 smdb_db
->smdb_set_owner
= smdb2_set_owner
;
679 smdb_db
->smdb_sync
= smdb2_sync
;
680 smdb_db
->smdb_cursor
= smdb2_cursor
;
681 smdb_db
->smdb_impl
= db2
;
691 smdb_unlock_file(db2
->smdb2_lock_fd
);
693 smdb_free_database(smdb_db
);
698 #endif /* (DB_VERSION_MAJOR >= 2) */