]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/libsmdb/smdb1.c
Merge sendmail 8.16.1 to HEAD: See contrib/sendmail/RELEASE_NOTES for details
[FreeBSD/FreeBSD.git] / contrib / sendmail / libsmdb / smdb1.c
1 /*
2 ** Copyright (c) 1999-2002, 2004, 2009 Proofpoint, 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 */
9
10 #include <sm/gen.h>
11 SM_RCSID("@(#)$Id: smdb1.c,v 8.63 2013-11-22 20:51:49 ca Exp $")
12
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <fcntl.h>
16
17 #include <sendmail/sendmail.h>
18 #include <libsmdb/smdb.h>
19
20 #if (DB_VERSION_MAJOR == 1)
21
22 struct smdb_db1_struct
23 {
24         DB      *smdb1_db;
25         int     smdb1_lock_fd;
26         bool    smdb1_cursor_in_use;
27 };
28 typedef struct smdb_db1_struct SMDB_DB1_DATABASE;
29
30 struct smdb_db1_cursor
31 {
32         SMDB_DB1_DATABASE       *db;
33 };
34 typedef struct smdb_db1_cursor SMDB_DB1_CURSOR;
35
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));
53
54 /*
55 **  SMDB_TYPE_TO_DB1_TYPE -- Translates smdb database type to db1 type.
56 **
57 **      Parameters:
58 **              type -- The type to translate.
59 **
60 **      Returns:
61 **              The DB1 type that corresponsds to the passed in SMDB type.
62 **              Returns -1 if there is no equivalent type.
63 **
64 */
65
66 static DBTYPE
67 smdb_type_to_db1_type(type)
68         SMDB_DBTYPE type;
69 {
70         if (type == SMDB_TYPE_DEFAULT)
71                 return DB_HASH;
72
73         if (SMDB_IS_TYPE_HASH(type))
74                 return DB_HASH;
75
76         if (SMDB_IS_TYPE_BTREE(type))
77                 return DB_BTREE;
78
79         /* Should never get here thanks to test in smdb_db_open() */
80         return DB_HASH;
81 }
82 /*
83 **  SMDB_PUT_FLAGS_TO_DB1_FLAGS -- Translates smdb put flags to db1 put flags.
84 **
85 **      Parameters:
86 **              flags -- The flags to translate.
87 **
88 **      Returns:
89 **              The db1 flags that are equivalent to the smdb flags.
90 **
91 **      Notes:
92 **              Any invalid flags are ignored.
93 **
94 */
95
96 static unsigned int
97 smdb_put_flags_to_db1_flags(flags)
98         SMDB_FLAG flags;
99 {
100         int return_flags;
101
102         return_flags = 0;
103
104         if (bitset(SMDBF_NO_OVERWRITE, flags))
105                 return_flags |= R_NOOVERWRITE;
106
107         return return_flags;
108 }
109 /*
110 **  SMDB_CURSOR_GET_FLAGS_TO_SMDB1
111 **
112 **      Parameters:
113 **              flags -- The flags to translate.
114 **
115 **      Returns:
116 **              The db1 flags that are equivalent to the smdb flags.
117 **
118 **      Notes:
119 **              Returns -1 if we don't support the flag.
120 **
121 */
122
123 static int
124 smdb_cursor_get_flags_to_smdb1(flags)
125         SMDB_FLAG flags;
126 {
127         switch(flags)
128         {
129                 case SMDB_CURSOR_GET_FIRST:
130                         return R_FIRST;
131
132                 case SMDB_CURSOR_GET_LAST:
133                         return R_LAST;
134
135                 case SMDB_CURSOR_GET_NEXT:
136                         return R_NEXT;
137
138                 case SMDB_CURSOR_GET_RANGE:
139                         return R_CURSOR;
140
141                 default:
142                         return -1;
143         }
144 }
145
146 /*
147 **  The rest of these functions correspond to the interface laid out in smdb.h.
148 */
149
150 static SMDB_DB1_DATABASE *
151 smdb1_malloc_database()
152 {
153         SMDB_DB1_DATABASE *db1;
154
155         db1 = (SMDB_DB1_DATABASE *) malloc(sizeof(SMDB_DB1_DATABASE));
156
157         if (db1 != NULL)
158         {
159                 db1->smdb1_lock_fd = -1;
160                 db1->smdb1_cursor_in_use = false;
161         }
162
163         return db1;
164 }
165
166 static int
167 smdb1_close(database)
168         SMDB_DATABASE *database;
169 {
170         int result;
171         SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
172         DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
173
174         result = db->close(db);
175         if (db1->smdb1_lock_fd != -1)
176                 (void) close(db1->smdb1_lock_fd);
177
178         free(db1);
179         database->smdb_impl = NULL;
180
181         return result;
182 }
183
184 static int
185 smdb1_del(database, key, flags)
186         SMDB_DATABASE *database;
187         SMDB_DBENT *key;
188         unsigned int flags;
189 {
190         DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
191         DBT dbkey;
192
193         (void) memset(&dbkey, '\0', sizeof dbkey);
194         dbkey.data = key->data;
195         dbkey.size = key->size;
196         return db->del(db, &dbkey, flags);
197 }
198
199 static int
200 smdb1_fd(database, fd)
201         SMDB_DATABASE *database;
202         int *fd;
203 {
204         DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
205
206         *fd = db->fd(db);
207         if (*fd == -1)
208                 return errno;
209
210         return SMDBE_OK;
211 }
212
213 static int
214 smdb1_lockfd(database)
215         SMDB_DATABASE *database;
216 {
217         SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
218
219         return db1->smdb1_lock_fd;
220 }
221
222
223 static int
224 smdb1_get(database, key, data, flags)
225         SMDB_DATABASE *database;
226         SMDB_DBENT *key;
227         SMDB_DBENT *data;
228         unsigned int flags;
229 {
230         int result;
231         DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
232         DBT dbkey, dbdata;
233
234         (void) memset(&dbdata, '\0', sizeof dbdata);
235         (void) memset(&dbkey, '\0', sizeof dbkey);
236         dbkey.data = key->data;
237         dbkey.size = key->size;
238
239         result = db->get(db, &dbkey, &dbdata, flags);
240         if (result != 0)
241         {
242                 if (result == 1)
243                         return SMDBE_NOT_FOUND;
244                 return errno;
245         }
246         data->data = dbdata.data;
247         data->size = dbdata.size;
248         return SMDBE_OK;
249 }
250
251 static int
252 smdb1_put(database, key, data, flags)
253         SMDB_DATABASE *database;
254         SMDB_DBENT *key;
255         SMDB_DBENT *data;
256         unsigned int flags;
257 {
258         DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
259         DBT dbkey, dbdata;
260
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;
267
268         return db->put(db, &dbkey, &dbdata,
269                        smdb_put_flags_to_db1_flags(flags));
270 }
271
272 static int
273 smdb1_set_owner(database, uid, gid)
274         SMDB_DATABASE *database;
275         uid_t uid;
276         gid_t gid;
277 {
278 # if HASFCHOWN
279         int fd;
280         int result;
281         DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
282
283         fd = db->fd(db);
284         if (fd == -1)
285                 return errno;
286
287         result = fchown(fd, uid, gid);
288         if (result < 0)
289                 return errno;
290 # endif /* HASFCHOWN */
291
292         return SMDBE_OK;
293 }
294
295 static int
296 smdb1_sync(database, flags)
297         SMDB_DATABASE *database;
298         unsigned int flags;
299 {
300         DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
301
302         return db->sync(db, flags);
303 }
304
305 static int
306 smdb1_cursor_close(cursor)
307         SMDB_CURSOR *cursor;
308 {
309         SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
310         SMDB_DB1_DATABASE *db1 = db1_cursor->db;
311
312         if (!db1->smdb1_cursor_in_use)
313                 return SMDBE_NOT_A_VALID_CURSOR;
314
315         db1->smdb1_cursor_in_use = false;
316         free(cursor);
317
318         return SMDBE_OK;
319 }
320
321 static int
322 smdb1_cursor_del(cursor, flags)
323         SMDB_CURSOR *cursor;
324         unsigned int flags;
325 {
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;
329
330         return db->del(db, NULL, R_CURSOR);
331 }
332
333 static int
334 smdb1_cursor_get(cursor, key, value, flags)
335         SMDB_CURSOR *cursor;
336         SMDB_DBENT *key;
337         SMDB_DBENT *value;
338         SMDB_FLAG flags;
339 {
340         int db1_flags;
341         int result;
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;
345         DBT dbkey, dbdata;
346
347         (void) memset(&dbdata, '\0', sizeof dbdata);
348         (void) memset(&dbkey, '\0', sizeof dbkey);
349
350         db1_flags = smdb_cursor_get_flags_to_smdb1(flags);
351         result = db->seq(db, &dbkey, &dbdata, db1_flags);
352         if (result == -1)
353                 return errno;
354         if (result == 1)
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;
360         return SMDBE_OK;
361 }
362
363 static int
364 smdb1_cursor_put(cursor, key, value, flags)
365         SMDB_CURSOR *cursor;
366         SMDB_DBENT *key;
367         SMDB_DBENT *value;
368         SMDB_FLAG flags;
369 {
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;
373         DBT dbkey, dbdata;
374
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;
381
382         return db->put(db, &dbkey, &dbdata, R_CURSOR);
383 }
384
385 static int
386 smdb1_cursor(database, cursor, flags)
387         SMDB_DATABASE *database;
388         SMDB_CURSOR **cursor;
389         unsigned int flags;
390 {
391         SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
392         SMDB_CURSOR *cur;
393         SMDB_DB1_CURSOR *db1_cursor;
394
395         if (db1->smdb1_cursor_in_use)
396                 return SMDBE_ONLY_SUPPORTS_ONE_CURSOR;
397
398         db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR));
399         if (db1_cursor == NULL)
400                 return SMDBE_MALLOC;
401
402         cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
403         if (cur == NULL)
404         {
405                 free(db1_cursor);
406                 return SMDBE_MALLOC;
407         }
408
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;
416         *cursor = cur;
417
418         return SMDBE_OK;
419 }
420 /*
421 **  SMDB_DB_OPEN -- Opens a db1 database.
422 **
423 **      Parameters:
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
432 **                          permissions.
433 **              db_params --
434 **                      An SMDB_DBPARAMS struct including params. These
435 **                      are processed according to the type of the
436 **                      database. Currently supported params (only for
437 **                      HASH type) are:
438 **                         num_elements
439 **                         cache_size
440 **
441 **      Returns:
442 **              SMDBE_OK -- Success, otherwise errno.
443 */
444
445 int
446 smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
447              db_params)
448         SMDB_DATABASE **database;
449         char *db_name;
450         int mode;
451         int mode_mask;
452         long sff;
453         SMDB_DBTYPE type;
454         SMDB_USER_INFO *user_info;
455         SMDB_DBPARAMS *db_params;
456 {
457         bool lockcreated = false;
458         int db_fd;
459         int lock_fd;
460         int result;
461         void *params;
462         SMDB_DATABASE *smdb_db;
463         SMDB_DB1_DATABASE *db1;
464         DB *db;
465         HASHINFO hash_info;
466         BTREEINFO btree_info;
467         DBTYPE db_type;
468         struct stat stat_info;
469         char db_file_name[MAXPATHLEN];
470
471         if (type == NULL ||
472             (!SMDB_IS_TYPE_HASH(type) && !SMDB_IS_TYPE_BTREE(type)
473              ))
474                 return SMDBE_UNKNOWN_DB_TYPE;
475
476         result = smdb_add_extension(db_file_name, sizeof db_file_name,
477                                     db_name, SMDB1_FILE_EXTENSION);
478         if (result != SMDBE_OK)
479                 return result;
480
481         result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask,
482                                  sff, user_info, &stat_info);
483         if (result != SMDBE_OK)
484                 return result;
485
486         if (stat_info.st_mode == ST_MODE_NOFILE &&
487             bitset(mode, O_CREAT))
488                 lockcreated = true;
489
490         lock_fd = -1;
491         result = smdb_lock_file(&lock_fd, db_name, mode, sff,
492                                 SMDB1_FILE_EXTENSION);
493         if (result != SMDBE_OK)
494                 return result;
495
496         if (lockcreated)
497         {
498                 mode |= O_TRUNC;
499                 mode &= ~(O_CREAT|O_EXCL);
500         }
501
502         *database = NULL;
503
504         smdb_db = smdb_malloc_database();
505         db1 = smdb1_malloc_database();
506         if (smdb_db == NULL || db1 == NULL)
507         {
508                 (void) smdb_unlock_file(lock_fd);
509                 smdb_free_database(smdb_db);
510                 free(db1);
511                 return SMDBE_MALLOC;
512         }
513         db1->smdb1_lock_fd = lock_fd;
514
515         params = NULL;
516         if (db_params != NULL && SMDB_IS_TYPE_HASH(type))
517         {
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;
521                 params = &hash_info;
522         }
523
524         if (db_params != NULL && SMDB_IS_TYPE_BTREE(type))
525         {
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;
531         }
532
533         db_type = smdb_type_to_db1_type(type);
534         db = dbopen(db_file_name, mode, DBMMODE, db_type, params);
535         if (db != NULL)
536         {
537                 db_fd = db->fd(db);
538                 result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd,
539                                           &stat_info);
540         }
541         else
542         {
543                 if (errno == 0)
544                         result = SMDBE_BAD_OPEN;
545                 else
546                         result = errno;
547         }
548
549         if (result == SMDBE_OK)
550         {
551                 /* Everything is ok. Setup driver */
552                 db1->smdb1_db = db;
553
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;
564
565                 *database = smdb_db;
566                 return SMDBE_OK;
567         }
568
569         if (db != NULL)
570                 (void) db->close(db);
571
572         /* Error opening database */
573         (void) smdb_unlock_file(db1->smdb1_lock_fd);
574         free(db1);
575         smdb_free_database(smdb_db);
576
577         return result;
578 }
579
580 #endif /* (DB_VERSION_MAJOR == 1) */