2 ** Copyright (c) 1999-2002, 2004, 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: smdb1.c,v 8.63 2013-11-22 20:51:49 ca Exp $")
17 #include <sendmail/sendmail.h>
18 #include <libsmdb/smdb.h>
20 #if (DB_VERSION_MAJOR == 1)
22 struct smdb_db1_struct
26 bool smdb1_cursor_in_use;
28 typedef struct smdb_db1_struct SMDB_DB1_DATABASE;
30 struct smdb_db1_cursor
32 SMDB_DB1_DATABASE *db;
34 typedef struct smdb_db1_cursor SMDB_DB1_CURSOR;
36 static DBTYPE smdb_type_to_db1_type __P((SMDB_DBTYPE));
37 static unsigned int smdb_put_flags_to_db1_flags __P((SMDB_FLAG));
38 static int smdb_cursor_get_flags_to_smdb1 __P((SMDB_FLAG));
39 static SMDB_DB1_DATABASE *smdb1_malloc_database __P((void));
40 static int smdb1_close __P((SMDB_DATABASE *));
41 static int smdb1_del __P((SMDB_DATABASE *, SMDB_DBENT *, unsigned int));
42 static int smdb1_fd __P((SMDB_DATABASE *, int *));
43 static int smdb1_lockfd __P((SMDB_DATABASE *));
44 static int smdb1_get __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
45 static int smdb1_put __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
46 static int smdb1_set_owner __P((SMDB_DATABASE *, uid_t, gid_t));
47 static int smdb1_sync __P((SMDB_DATABASE *, unsigned int));
48 static int smdb1_cursor_close __P((SMDB_CURSOR *));
49 static int smdb1_cursor_del __P((SMDB_CURSOR *, unsigned int));
50 static int smdb1_cursor_get __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
51 static int smdb1_cursor_put __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
52 static int smdb1_cursor __P((SMDB_DATABASE *, SMDB_CURSOR **, unsigned int));
55 ** SMDB_TYPE_TO_DB1_TYPE -- Translates smdb database type to db1 type.
58 ** type -- The type to translate.
61 ** The DB1 type that corresponsds to the passed in SMDB type.
62 ** Returns -1 if there is no equivalent type.
67 smdb_type_to_db1_type(type)
70 if (type == SMDB_TYPE_DEFAULT)
73 if (SMDB_IS_TYPE_HASH(type))
76 if (SMDB_IS_TYPE_BTREE(type))
79 /* Should never get here thanks to test in smdb_db_open() */
83 ** SMDB_PUT_FLAGS_TO_DB1_FLAGS -- Translates smdb put flags to db1 put flags.
86 ** flags -- The flags to translate.
89 ** The db1 flags that are equivalent to the smdb flags.
92 ** Any invalid flags are ignored.
97 smdb_put_flags_to_db1_flags(flags)
104 if (bitset(SMDBF_NO_OVERWRITE, flags))
105 return_flags |= R_NOOVERWRITE;
110 ** SMDB_CURSOR_GET_FLAGS_TO_SMDB1
113 ** flags -- The flags to translate.
116 ** The db1 flags that are equivalent to the smdb flags.
119 ** Returns -1 if we don't support the flag.
124 smdb_cursor_get_flags_to_smdb1(flags)
129 case SMDB_CURSOR_GET_FIRST:
132 case SMDB_CURSOR_GET_LAST:
135 case SMDB_CURSOR_GET_NEXT:
138 case SMDB_CURSOR_GET_RANGE:
147 ** The rest of these functions correspond to the interface laid out in smdb.h.
150 static SMDB_DB1_DATABASE *
151 smdb1_malloc_database()
153 SMDB_DB1_DATABASE *db1;
155 db1 = (SMDB_DB1_DATABASE *) malloc(sizeof(SMDB_DB1_DATABASE));
159 db1->smdb1_lock_fd = -1;
160 db1->smdb1_cursor_in_use = false;
167 smdb1_close(database)
168 SMDB_DATABASE *database;
171 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
172 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
174 result = db->close(db);
175 if (db1->smdb1_lock_fd != -1)
176 (void) close(db1->smdb1_lock_fd);
179 database->smdb_impl = NULL;
185 smdb1_del(database, key, flags)
186 SMDB_DATABASE *database;
190 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
193 (void) memset(&dbkey, '\0', sizeof dbkey);
194 dbkey.data = key->data;
195 dbkey.size = key->size;
196 return db->del(db, &dbkey, flags);
200 smdb1_fd(database, fd)
201 SMDB_DATABASE *database;
204 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
214 smdb1_lockfd(database)
215 SMDB_DATABASE *database;
217 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
219 return db1->smdb1_lock_fd;
224 smdb1_get(database, key, data, flags)
225 SMDB_DATABASE *database;
231 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
234 (void) memset(&dbdata, '\0', sizeof dbdata);
235 (void) memset(&dbkey, '\0', sizeof dbkey);
236 dbkey.data = key->data;
237 dbkey.size = key->size;
239 result = db->get(db, &dbkey, &dbdata, flags);
243 return SMDBE_NOT_FOUND;
246 data->data = dbdata.data;
247 data->size = dbdata.size;
252 smdb1_put(database, key, data, flags)
253 SMDB_DATABASE *database;
258 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
261 (void) memset(&dbdata, '\0', sizeof dbdata);
262 (void) memset(&dbkey, '\0', sizeof dbkey);
263 dbkey.data = key->data;
264 dbkey.size = key->size;
265 dbdata.data = data->data;
266 dbdata.size = data->size;
268 return db->put(db, &dbkey, &dbdata,
269 smdb_put_flags_to_db1_flags(flags));
273 smdb1_set_owner(database, uid, gid)
274 SMDB_DATABASE *database;
281 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
287 result = fchown(fd, uid, gid);
290 # endif /* HASFCHOWN */
296 smdb1_sync(database, flags)
297 SMDB_DATABASE *database;
300 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
302 return db->sync(db, flags);
306 smdb1_cursor_close(cursor)
309 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
310 SMDB_DB1_DATABASE *db1 = db1_cursor->db;
312 if (!db1->smdb1_cursor_in_use)
313 return SMDBE_NOT_A_VALID_CURSOR;
315 db1->smdb1_cursor_in_use = false;
322 smdb1_cursor_del(cursor, flags)
326 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
327 SMDB_DB1_DATABASE *db1 = db1_cursor->db;
328 DB *db = db1->smdb1_db;
330 return db->del(db, NULL, R_CURSOR);
334 smdb1_cursor_get(cursor, key, value, flags)
342 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
343 SMDB_DB1_DATABASE *db1 = db1_cursor->db;
344 DB *db = db1->smdb1_db;
347 (void) memset(&dbdata, '\0', sizeof dbdata);
348 (void) memset(&dbkey, '\0', sizeof dbkey);
350 db1_flags = smdb_cursor_get_flags_to_smdb1(flags);
351 result = db->seq(db, &dbkey, &dbdata, db1_flags);
355 return SMDBE_LAST_ENTRY;
356 value->data = dbdata.data;
357 value->size = dbdata.size;
358 key->data = dbkey.data;
359 key->size = dbkey.size;
364 smdb1_cursor_put(cursor, key, value, flags)
370 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
371 SMDB_DB1_DATABASE *db1 = db1_cursor->db;
372 DB *db = db1->smdb1_db;
375 (void) memset(&dbdata, '\0', sizeof dbdata);
376 (void) memset(&dbkey, '\0', sizeof dbkey);
377 dbkey.data = key->data;
378 dbkey.size = key->size;
379 dbdata.data = value->data;
380 dbdata.size = value->size;
382 return db->put(db, &dbkey, &dbdata, R_CURSOR);
386 smdb1_cursor(database, cursor, flags)
387 SMDB_DATABASE *database;
388 SMDB_CURSOR **cursor;
391 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
393 SMDB_DB1_CURSOR *db1_cursor;
395 if (db1->smdb1_cursor_in_use)
396 return SMDBE_ONLY_SUPPORTS_ONE_CURSOR;
398 db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR));
399 if (db1_cursor == NULL)
402 cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
409 db1->smdb1_cursor_in_use = true;
410 db1_cursor->db = db1;
411 cur->smdbc_impl = db1_cursor;
412 cur->smdbc_close = smdb1_cursor_close;
413 cur->smdbc_del = smdb1_cursor_del;
414 cur->smdbc_get = smdb1_cursor_get;
415 cur->smdbc_put = smdb1_cursor_put;
421 ** SMDB_DB_OPEN -- Opens a db1 database.
424 ** database -- An unallocated database pointer to a pointer.
425 ** db_name -- The name of the database without extension.
426 ** mode -- File permisions on the database if created.
427 ** mode_mask -- Mode bits that must match on an existing database.
428 ** sff -- Flags for safefile.
429 ** type -- The type of database to open
430 ** See smdb_type_to_db1_type for valid types.
431 ** user_info -- Information on the user to use for file
434 ** An SMDB_DBPARAMS struct including params. These
435 ** are processed according to the type of the
436 ** database. Currently supported params (only for
442 ** SMDBE_OK -- Success, otherwise errno.
446 smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
448 SMDB_DATABASE **database;
454 SMDB_USER_INFO *user_info;
455 SMDB_DBPARAMS *db_params;
457 bool lockcreated = false;
462 SMDB_DATABASE *smdb_db;
463 SMDB_DB1_DATABASE *db1;
466 BTREEINFO btree_info;
468 struct stat stat_info;
469 char db_file_name[MAXPATHLEN];
472 (!SMDB_IS_TYPE_HASH(type) && !SMDB_IS_TYPE_BTREE(type)
474 return SMDBE_UNKNOWN_DB_TYPE;
476 result = smdb_add_extension(db_file_name, sizeof db_file_name,
477 db_name, SMDB1_FILE_EXTENSION);
478 if (result != SMDBE_OK)
481 result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask,
482 sff, user_info, &stat_info);
483 if (result != SMDBE_OK)
486 if (stat_info.st_mode == ST_MODE_NOFILE &&
487 bitset(mode, O_CREAT))
491 result = smdb_lock_file(&lock_fd, db_name, mode, sff,
492 SMDB1_FILE_EXTENSION);
493 if (result != SMDBE_OK)
499 mode &= ~(O_CREAT|O_EXCL);
504 smdb_db = smdb_malloc_database();
505 db1 = smdb1_malloc_database();
506 if (smdb_db == NULL || db1 == NULL)
508 (void) smdb_unlock_file(lock_fd);
509 smdb_free_database(smdb_db);
513 db1->smdb1_lock_fd = lock_fd;
516 if (db_params != NULL && SMDB_IS_TYPE_HASH(type))
518 (void) memset(&hash_info, '\0', sizeof hash_info);
519 hash_info.nelem = db_params->smdbp_num_elements;
520 hash_info.cachesize = db_params->smdbp_cache_size;
524 if (db_params != NULL && SMDB_IS_TYPE_BTREE(type))
526 (void) memset(&btree_info, '\0', sizeof btree_info);
527 btree_info.cachesize = db_params->smdbp_cache_size;
528 if (db_params->smdbp_allow_dup)
529 btree_info.flags |= R_DUP;
530 params = &btree_info;
533 db_type = smdb_type_to_db1_type(type);
534 db = dbopen(db_file_name, mode, DBMMODE, db_type, params);
538 result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd,
544 result = SMDBE_BAD_OPEN;
549 if (result == SMDBE_OK)
551 /* Everything is ok. Setup driver */
554 smdb_db->smdb_close = smdb1_close;
555 smdb_db->smdb_del = smdb1_del;
556 smdb_db->smdb_fd = smdb1_fd;
557 smdb_db->smdb_lockfd = smdb1_lockfd;
558 smdb_db->smdb_get = smdb1_get;
559 smdb_db->smdb_put = smdb1_put;
560 smdb_db->smdb_set_owner = smdb1_set_owner;
561 smdb_db->smdb_sync = smdb1_sync;
562 smdb_db->smdb_cursor = smdb1_cursor;
563 smdb_db->smdb_impl = db1;
570 (void) db->close(db);
572 /* Error opening database */
573 (void) smdb_unlock_file(db1->smdb1_lock_fd);
575 smdb_free_database(smdb_db);
580 #endif /* (DB_VERSION_MAJOR == 1) */