Import sendmail 8.13.4 into a new contrib directory as the first step
[dragonfly.git] / contrib / sendmail-8.13.4 / libsmdb / smdb1.c
blobe45de7c7f8f836c8912106e53c4271a84930fc27
1 /*
2 ** Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers.
3 ** All rights reserved.
4 **
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.
8 */
10 #include <sm/gen.h>
11 SM_RCSID("@(#)$Id: smdb1.c,v 8.59 2004/08/03 20:58:39 ca Exp $")
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <fcntl.h>
17 #include <sendmail/sendmail.h>
18 #include <libsmdb/smdb.h>
20 #if (DB_VERSION_MAJOR == 1)
22 # define SMDB1_FILE_EXTENSION "db"
24 struct smdb_db1_struct
26 DB *smdb1_db;
27 int smdb1_lock_fd;
28 bool smdb1_cursor_in_use;
30 typedef struct smdb_db1_struct SMDB_DB1_DATABASE;
32 struct smdb_db1_cursor
34 SMDB_DB1_DATABASE *db;
36 typedef struct smdb_db1_cursor SMDB_DB1_CURSOR;
38 static DBTYPE smdb_type_to_db1_type __P((SMDB_DBTYPE));
39 static unsigned int smdb_put_flags_to_db1_flags __P((SMDB_FLAG));
40 static int smdb_cursor_get_flags_to_smdb1 __P((SMDB_FLAG));
41 static SMDB_DB1_DATABASE *smdb1_malloc_database __P((void));
42 static int smdb1_close __P((SMDB_DATABASE *));
43 static int smdb1_del __P((SMDB_DATABASE *, SMDB_DBENT *, unsigned int));
44 static int smdb1_fd __P((SMDB_DATABASE *, int *));
45 static int smdb1_lockfd __P((SMDB_DATABASE *));
46 static int smdb1_get __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
47 static int smdb1_put __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
48 static int smdb1_set_owner __P((SMDB_DATABASE *, uid_t, gid_t));
49 static int smdb1_sync __P((SMDB_DATABASE *, unsigned int));
50 static int smdb1_cursor_close __P((SMDB_CURSOR *));
51 static int smdb1_cursor_del __P((SMDB_CURSOR *, unsigned int));
52 static int smdb1_cursor_get __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
53 static int smdb1_cursor_put __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
54 static int smdb1_cursor __P((SMDB_DATABASE *, SMDB_CURSOR **, unsigned int));
57 ** SMDB_TYPE_TO_DB1_TYPE -- Translates smdb database type to db1 type.
59 ** Parameters:
60 ** type -- The type to translate.
62 ** Returns:
63 ** The DB1 type that corresponsds to the passed in SMDB type.
64 ** Returns -1 if there is no equivalent type.
68 static DBTYPE
69 smdb_type_to_db1_type(type)
70 SMDB_DBTYPE type;
72 if (type == SMDB_TYPE_DEFAULT)
73 return DB_HASH;
75 if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
76 return DB_HASH;
78 if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
79 return DB_BTREE;
81 /* Should never get here thanks to test in smdb_db_open() */
82 return DB_HASH;
85 ** SMDB_PUT_FLAGS_TO_DB1_FLAGS -- Translates smdb put flags to db1 put flags.
87 ** Parameters:
88 ** flags -- The flags to translate.
90 ** Returns:
91 ** The db1 flags that are equivalent to the smdb flags.
93 ** Notes:
94 ** Any invalid flags are ignored.
98 static unsigned int
99 smdb_put_flags_to_db1_flags(flags)
100 SMDB_FLAG flags;
102 int return_flags;
104 return_flags = 0;
106 if (bitset(SMDBF_NO_OVERWRITE, flags))
107 return_flags |= R_NOOVERWRITE;
109 return return_flags;
112 ** SMDB_CURSOR_GET_FLAGS_TO_SMDB1
114 ** Parameters:
115 ** flags -- The flags to translate.
117 ** Returns:
118 ** The db1 flags that are equivalent to the smdb flags.
120 ** Notes:
121 ** Returns -1 if we don't support the flag.
125 static int
126 smdb_cursor_get_flags_to_smdb1(flags)
127 SMDB_FLAG flags;
129 switch(flags)
131 case SMDB_CURSOR_GET_FIRST:
132 return R_FIRST;
134 case SMDB_CURSOR_GET_LAST:
135 return R_LAST;
137 case SMDB_CURSOR_GET_NEXT:
138 return R_NEXT;
140 case SMDB_CURSOR_GET_RANGE:
141 return R_CURSOR;
143 default:
144 return -1;
149 ** The rest of these functions correspond to the interface laid out in smdb.h.
152 static SMDB_DB1_DATABASE *
153 smdb1_malloc_database()
155 SMDB_DB1_DATABASE *db1;
157 db1 = (SMDB_DB1_DATABASE *) malloc(sizeof(SMDB_DB1_DATABASE));
159 if (db1 != NULL)
161 db1->smdb1_lock_fd = -1;
162 db1->smdb1_cursor_in_use = false;
165 return db1;
168 static int
169 smdb1_close(database)
170 SMDB_DATABASE *database;
172 int result;
173 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
174 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
176 result = db->close(db);
177 if (db1->smdb1_lock_fd != -1)
178 (void) close(db1->smdb1_lock_fd);
180 free(db1);
181 database->smdb_impl = NULL;
183 return result;
186 static int
187 smdb1_del(database, key, flags)
188 SMDB_DATABASE *database;
189 SMDB_DBENT *key;
190 unsigned int flags;
192 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
193 DBT dbkey;
195 (void) memset(&dbkey, '\0', sizeof dbkey);
196 dbkey.data = key->data;
197 dbkey.size = key->size;
198 return db->del(db, &dbkey, flags);
201 static int
202 smdb1_fd(database, fd)
203 SMDB_DATABASE *database;
204 int *fd;
206 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
208 *fd = db->fd(db);
209 if (*fd == -1)
210 return errno;
212 return SMDBE_OK;
215 static int
216 smdb1_lockfd(database)
217 SMDB_DATABASE *database;
219 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
221 return db1->smdb1_lock_fd;
225 static int
226 smdb1_get(database, key, data, flags)
227 SMDB_DATABASE *database;
228 SMDB_DBENT *key;
229 SMDB_DBENT *data;
230 unsigned int flags;
232 int result;
233 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
234 DBT dbkey, dbdata;
236 (void) memset(&dbdata, '\0', sizeof dbdata);
237 (void) memset(&dbkey, '\0', sizeof dbkey);
238 dbkey.data = key->data;
239 dbkey.size = key->size;
241 result = db->get(db, &dbkey, &dbdata, flags);
242 if (result != 0)
244 if (result == 1)
245 return SMDBE_NOT_FOUND;
246 return errno;
248 data->data = dbdata.data;
249 data->size = dbdata.size;
250 return SMDBE_OK;
253 static int
254 smdb1_put(database, key, data, flags)
255 SMDB_DATABASE *database;
256 SMDB_DBENT *key;
257 SMDB_DBENT *data;
258 unsigned int flags;
260 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
261 DBT dbkey, dbdata;
263 (void) memset(&dbdata, '\0', sizeof dbdata);
264 (void) memset(&dbkey, '\0', sizeof dbkey);
265 dbkey.data = key->data;
266 dbkey.size = key->size;
267 dbdata.data = data->data;
268 dbdata.size = data->size;
270 return db->put(db, &dbkey, &dbdata,
271 smdb_put_flags_to_db1_flags(flags));
274 static int
275 smdb1_set_owner(database, uid, gid)
276 SMDB_DATABASE *database;
277 uid_t uid;
278 gid_t gid;
280 # if HASFCHOWN
281 int fd;
282 int result;
283 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
285 fd = db->fd(db);
286 if (fd == -1)
287 return errno;
289 result = fchown(fd, uid, gid);
290 if (result < 0)
291 return errno;
292 # endif /* HASFCHOWN */
294 return SMDBE_OK;
297 static int
298 smdb1_sync(database, flags)
299 SMDB_DATABASE *database;
300 unsigned int flags;
302 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
304 return db->sync(db, flags);
307 static int
308 smdb1_cursor_close(cursor)
309 SMDB_CURSOR *cursor;
311 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
312 SMDB_DB1_DATABASE *db1 = db1_cursor->db;
314 if (!db1->smdb1_cursor_in_use)
315 return SMDBE_NOT_A_VALID_CURSOR;
317 db1->smdb1_cursor_in_use = false;
318 free(cursor);
320 return SMDBE_OK;
323 static int
324 smdb1_cursor_del(cursor, flags)
325 SMDB_CURSOR *cursor;
326 unsigned int flags;
328 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
329 SMDB_DB1_DATABASE *db1 = db1_cursor->db;
330 DB *db = db1->smdb1_db;
332 return db->del(db, NULL, R_CURSOR);
335 static int
336 smdb1_cursor_get(cursor, key, value, flags)
337 SMDB_CURSOR *cursor;
338 SMDB_DBENT *key;
339 SMDB_DBENT *value;
340 SMDB_FLAG flags;
342 int db1_flags;
343 int result;
344 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
345 SMDB_DB1_DATABASE *db1 = db1_cursor->db;
346 DB *db = db1->smdb1_db;
347 DBT dbkey, dbdata;
349 (void) memset(&dbdata, '\0', sizeof dbdata);
350 (void) memset(&dbkey, '\0', sizeof dbkey);
352 db1_flags = smdb_cursor_get_flags_to_smdb1(flags);
353 result = db->seq(db, &dbkey, &dbdata, db1_flags);
354 if (result == -1)
355 return errno;
356 if (result == 1)
357 return SMDBE_LAST_ENTRY;
358 value->data = dbdata.data;
359 value->size = dbdata.size;
360 key->data = dbkey.data;
361 key->size = dbkey.size;
362 return SMDBE_OK;
365 static int
366 smdb1_cursor_put(cursor, key, value, flags)
367 SMDB_CURSOR *cursor;
368 SMDB_DBENT *key;
369 SMDB_DBENT *value;
370 SMDB_FLAG flags;
372 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
373 SMDB_DB1_DATABASE *db1 = db1_cursor->db;
374 DB *db = db1->smdb1_db;
375 DBT dbkey, dbdata;
377 (void) memset(&dbdata, '\0', sizeof dbdata);
378 (void) memset(&dbkey, '\0', sizeof dbkey);
379 dbkey.data = key->data;
380 dbkey.size = key->size;
381 dbdata.data = value->data;
382 dbdata.size = value->size;
384 return db->put(db, &dbkey, &dbdata, R_CURSOR);
387 static int
388 smdb1_cursor(database, cursor, flags)
389 SMDB_DATABASE *database;
390 SMDB_CURSOR **cursor;
391 unsigned int flags;
393 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
394 SMDB_CURSOR *cur;
395 SMDB_DB1_CURSOR *db1_cursor;
397 if (db1->smdb1_cursor_in_use)
398 return SMDBE_ONLY_SUPPORTS_ONE_CURSOR;
400 db1->smdb1_cursor_in_use = true;
401 db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR));
402 db1_cursor->db = db1;
404 cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
406 if (cur == NULL)
407 return SMDBE_MALLOC;
409 cur->smdbc_impl = db1_cursor;
410 cur->smdbc_close = smdb1_cursor_close;
411 cur->smdbc_del = smdb1_cursor_del;
412 cur->smdbc_get = smdb1_cursor_get;
413 cur->smdbc_put = smdb1_cursor_put;
414 *cursor = cur;
416 return SMDBE_OK;
419 ** SMDB_DB_OPEN -- Opens a db1 database.
421 ** Parameters:
422 ** database -- An unallocated database pointer to a pointer.
423 ** db_name -- The name of the database without extension.
424 ** mode -- File permisions on the database if created.
425 ** mode_mask -- Mode bits that must match on an existing database.
426 ** sff -- Flags for safefile.
427 ** type -- The type of database to open
428 ** See smdb_type_to_db1_type for valid types.
429 ** user_info -- Information on the user to use for file
430 ** permissions.
431 ** db_params --
432 ** An SMDB_DBPARAMS struct including params. These
433 ** are processed according to the type of the
434 ** database. Currently supported params (only for
435 ** HASH type) are:
436 ** num_elements
437 ** cache_size
439 ** Returns:
440 ** SMDBE_OK -- Success, otherwise errno.
444 smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
445 db_params)
446 SMDB_DATABASE **database;
447 char *db_name;
448 int mode;
449 int mode_mask;
450 long sff;
451 SMDB_DBTYPE type;
452 SMDB_USER_INFO *user_info;
453 SMDB_DBPARAMS *db_params;
455 bool lockcreated = false;
456 int db_fd;
457 int lock_fd;
458 int result;
459 void *params;
460 SMDB_DATABASE *smdb_db;
461 SMDB_DB1_DATABASE *db1;
462 DB *db;
463 HASHINFO hash_info;
464 BTREEINFO btree_info;
465 DBTYPE db_type;
466 struct stat stat_info;
467 char db_file_name[MAXPATHLEN];
469 if (type == NULL ||
470 (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) != 0 &&
471 strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) != 0))
472 return SMDBE_UNKNOWN_DB_TYPE;
474 result = smdb_add_extension(db_file_name, sizeof db_file_name,
475 db_name, SMDB1_FILE_EXTENSION);
476 if (result != SMDBE_OK)
477 return result;
479 result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask,
480 sff, user_info, &stat_info);
481 if (result != SMDBE_OK)
482 return result;
484 if (stat_info.st_mode == ST_MODE_NOFILE &&
485 bitset(mode, O_CREAT))
486 lockcreated = true;
488 lock_fd = -1;
489 result = smdb_lock_file(&lock_fd, db_name, mode, sff,
490 SMDB1_FILE_EXTENSION);
491 if (result != SMDBE_OK)
492 return result;
494 if (lockcreated)
496 mode |= O_TRUNC;
497 mode &= ~(O_CREAT|O_EXCL);
500 *database = NULL;
502 smdb_db = smdb_malloc_database();
503 db1 = smdb1_malloc_database();
504 if (smdb_db == NULL || db1 == NULL)
505 return SMDBE_MALLOC;
506 db1->smdb1_lock_fd = lock_fd;
508 params = NULL;
509 if (db_params != NULL &&
510 (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) == 0))
512 (void) memset(&hash_info, '\0', sizeof hash_info);
513 hash_info.nelem = db_params->smdbp_num_elements;
514 hash_info.cachesize = db_params->smdbp_cache_size;
515 params = &hash_info;
518 if (db_params != NULL &&
519 (strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) == 0))
521 (void) memset(&btree_info, '\0', sizeof btree_info);
522 btree_info.cachesize = db_params->smdbp_cache_size;
523 if (db_params->smdbp_allow_dup)
524 btree_info.flags |= R_DUP;
525 params = &btree_info;
528 db_type = smdb_type_to_db1_type(type);
529 db = dbopen(db_file_name, mode, DBMMODE, db_type, params);
530 if (db != NULL)
532 db_fd = db->fd(db);
533 result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd,
534 &stat_info);
536 else
538 if (errno == 0)
539 result = SMDBE_BAD_OPEN;
540 else
541 result = errno;
544 if (result == SMDBE_OK)
546 /* Everything is ok. Setup driver */
547 db1->smdb1_db = db;
549 smdb_db->smdb_close = smdb1_close;
550 smdb_db->smdb_del = smdb1_del;
551 smdb_db->smdb_fd = smdb1_fd;
552 smdb_db->smdb_lockfd = smdb1_lockfd;
553 smdb_db->smdb_get = smdb1_get;
554 smdb_db->smdb_put = smdb1_put;
555 smdb_db->smdb_set_owner = smdb1_set_owner;
556 smdb_db->smdb_sync = smdb1_sync;
557 smdb_db->smdb_cursor = smdb1_cursor;
558 smdb_db->smdb_impl = db1;
560 *database = smdb_db;
561 return SMDBE_OK;
564 if (db != NULL)
565 (void) db->close(db);
567 /* Error opening database */
568 (void) smdb_unlock_file(db1->smdb1_lock_fd);
569 free(db1);
570 smdb_free_database(smdb_db);
572 return result;
575 #endif /* (DB_VERSION_MAJOR == 1) */