2 ** Copyright (c) 1999-2002 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: smdb.c,v 8.58 2004/08/03 20:58:38 ca Exp $")
18 #include <sendmail/sendmail.h>
19 #include <libsmdb/smdb.h>
21 static bool smdb_lockfile
__P((int, int));
24 ** SMDB_MALLOC_DATABASE -- Allocates a database structure.
30 ** An pointer to an allocated SMDB_DATABASE structure or
31 ** NULL if it couldn't allocate the memory.
35 smdb_malloc_database()
39 db
= (SMDB_DATABASE
*) malloc(sizeof(SMDB_DATABASE
));
42 (void) memset(db
, '\0', sizeof(SMDB_DATABASE
));
49 ** SMDB_FREE_DATABASE -- Unallocates a database structure.
52 ** database -- a SMDB_DATABASE pointer to deallocate.
59 smdb_free_database(database
)
60 SMDB_DATABASE
*database
;
66 ** SMDB_LOCKFILE -- lock a file using flock or (shudder) fcntl locking
69 ** fd -- the file descriptor of the file.
70 ** type -- type of the lock. Bits can be:
71 ** LOCK_EX -- exclusive lock.
72 ** LOCK_NB -- non-blocking.
75 ** true if the lock was acquired.
80 smdb_lockfile(fd
, type
)
90 (void) memset(&lfd
, '\0', sizeof lfd
);
91 if (bitset(LOCK_UN
, type
))
93 else if (bitset(LOCK_EX
, type
))
98 if (bitset(LOCK_NB
, type
))
103 while ((i
= fcntl(fd
, action
, &lfd
)) < 0 && errno
== EINTR
)
110 ** On SunOS, if you are testing using -oQ/tmp/mqueue or
111 ** -oA/tmp/aliases or anything like that, and /tmp is mounted
112 ** as type "tmp" (that is, served from swap space), the
113 ** previous fcntl will fail with "Invalid argument" errors.
114 ** Since this is fairly common during testing, we will assume
115 ** that this indicates that the lock is successfully grabbed.
118 if (save_errno
== EINVAL
)
121 if (!bitset(LOCK_NB
, type
) ||
122 (save_errno
!= EACCES
&& save_errno
!= EAGAIN
))
125 int omode
= fcntl(fd
, F_GETFL
, NULL
);
126 int euid
= (int) geteuid();
128 syslog(LOG_ERR
, "cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
129 filename
, ext
, fd
, type
, omode
, euid
);
134 #else /* !HASFLOCK */
136 while ((i
= flock(fd
, type
)) < 0 && errno
== EINTR
)
142 if (!bitset(LOCK_NB
, type
) || save_errno
!= EWOULDBLOCK
)
145 int omode
= fcntl(fd
, F_GETFL
, NULL
);
146 int euid
= (int) geteuid();
148 syslog(LOG_ERR
, "cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
149 filename
, ext
, fd
, type
, omode
, euid
);
154 #endif /* !HASFLOCK */
159 ** SMDB_OPEN_DATABASE -- Opens a database.
161 ** This opens a database. If type is SMDB_DEFAULT it tries to
162 ** use a DB1 or DB2 hash. If that isn't available, it will try
163 ** to use NDBM. If a specific type is given it will try to open
164 ** a database of that type.
167 ** database -- An pointer to a SMDB_DATABASE pointer where the
168 ** opened database will be stored. This should
170 ** db_name -- The name of the database to open. Do not include
171 ** the file name extension.
172 ** mode -- The mode to set on the database file or files.
173 ** mode_mask -- Mode bits that must match on an opened database.
174 ** sff -- Flags to safefile.
175 ** type -- The type of database to open. Supported types
176 ** vary depending on what was compiled in.
177 ** user_info -- Information on the user to use for file
179 ** params -- Params specific to the database being opened.
180 ** Only supports some DB hash options right now
181 ** (see smdb_db_open() for details).
184 ** SMDBE_OK -- Success.
185 ** Anything else is an error. Look up more info about the
186 ** error in the comments for the specific open() used.
190 smdb_open_database(database
, db_name
, mode
, mode_mask
, sff
, type
, user_info
,
192 SMDB_DATABASE
**database
;
198 SMDB_USER_INFO
*user_info
;
199 SMDB_DBPARAMS
*params
;
201 bool type_was_default
= false;
203 if (type
== SMDB_TYPE_DEFAULT
)
205 type_was_default
= true;
207 type
= SMDB_TYPE_HASH
;
210 type
= SMDB_TYPE_NDBM
;
215 if (type
== SMDB_TYPE_DEFAULT
)
216 return SMDBE_UNKNOWN_DB_TYPE
;
218 if ((strncmp(type
, SMDB_TYPE_HASH
, SMDB_TYPE_HASH_LEN
) == 0) ||
219 (strncmp(type
, SMDB_TYPE_BTREE
, SMDB_TYPE_BTREE_LEN
) == 0))
224 result
= smdb_db_open(database
, db_name
, mode
, mode_mask
, sff
,
225 type
, user_info
, params
);
227 if (result
== ENOENT
&& type_was_default
)
228 type
= SMDB_TYPE_NDBM
;
233 return SMDBE_UNSUPPORTED_DB_TYPE
;
237 if (strncmp(type
, SMDB_TYPE_NDBM
, SMDB_TYPE_NDBM_LEN
) == 0)
242 result
= smdb_ndbm_open(database
, db_name
, mode
, mode_mask
,
243 sff
, type
, user_info
, params
);
246 return SMDBE_UNSUPPORTED_DB_TYPE
;
250 return SMDBE_UNKNOWN_DB_TYPE
;
253 ** SMDB_ADD_EXTENSION -- Adds an extension to a file name.
255 ** Just adds a . followed by a string to a db_name if there
256 ** is room and the db_name does not already have that extension.
259 ** full_name -- The final file name.
260 ** max_full_name_len -- The max length for full_name.
261 ** db_name -- The name of the db.
262 ** extension -- The extension to add.
265 ** SMDBE_OK -- Success.
266 ** Anything else is an error. Look up more info about the
267 ** error in the comments for the specific open() used.
271 smdb_add_extension(full_name
, max_full_name_len
, db_name
, extension
)
273 int max_full_name_len
;
280 if (full_name
== NULL
|| db_name
== NULL
|| extension
== NULL
)
281 return SMDBE_INVALID_PARAMETER
;
283 extension_len
= strlen(extension
);
284 db_name_len
= strlen(db_name
);
286 if (extension_len
+ db_name_len
+ 2 > max_full_name_len
)
287 return SMDBE_DB_NAME_TOO_LONG
;
289 if (db_name_len
< extension_len
+ 1 ||
290 db_name
[db_name_len
- extension_len
- 1] != '.' ||
291 strcmp(&db_name
[db_name_len
- extension_len
], extension
) != 0)
292 (void) sm_snprintf(full_name
, max_full_name_len
, "%s.%s",
295 (void) sm_strlcpy(full_name
, db_name
, max_full_name_len
);
300 ** SMDB_LOCK_FILE -- Locks the database file.
302 ** Locks the actual database file.
305 ** lock_fd -- The resulting descriptor for the locked file.
306 ** db_name -- The name of the database without extension.
307 ** mode -- The open mode.
308 ** sff -- Flags to safefile.
309 ** extension -- The extension for the file.
312 ** SMDBE_OK -- Success, otherwise errno.
316 smdb_lock_file(lock_fd
, db_name
, mode
, sff
, extension
)
324 char file_name
[MAXPATHLEN
];
326 result
= smdb_add_extension(file_name
, sizeof file_name
, db_name
,
328 if (result
!= SMDBE_OK
)
331 *lock_fd
= safeopen(file_name
, mode
& ~O_TRUNC
, DBMMODE
, sff
);
338 ** SMDB_UNLOCK_FILE -- Unlocks a file
343 ** lock_fd -- The descriptor for the locked file.
346 ** SMDBE_OK -- Success, otherwise errno.
350 smdb_unlock_file(lock_fd
)
355 result
= close(lock_fd
);
362 ** SMDB_LOCK_MAP -- Locks a database.
365 ** database -- database description.
366 ** type -- type of the lock. Bits can be:
367 ** LOCK_EX -- exclusive lock.
368 ** LOCK_NB -- non-blocking.
371 ** SMDBE_OK -- Success, otherwise errno.
375 smdb_lock_map(database
, type
)
376 SMDB_DATABASE
*database
;
381 fd
= database
->smdb_lockfd(database
);
383 return SMDBE_NOT_FOUND
;
384 if (!smdb_lockfile(fd
, type
))
385 return SMDBE_LOCK_NOT_GRANTED
;
389 ** SMDB_UNLOCK_MAP -- Unlocks a database
392 ** database -- database description.
395 ** SMDBE_OK -- Success, otherwise errno.
399 smdb_unlock_map(database
)
400 SMDB_DATABASE
*database
;
404 fd
= database
->smdb_lockfd(database
);
406 return SMDBE_NOT_FOUND
;
407 if (!smdb_lockfile(fd
, LOCK_UN
))
408 return SMDBE_LOCK_NOT_HELD
;
412 ** SMDB_SETUP_FILE -- Gets db file ready for use.
414 ** Makes sure permissions on file are safe and creates it if it
418 ** db_name -- The name of the database without extension.
419 ** extension -- The extension.
420 ** sff -- Flags to safefile.
421 ** mode_mask -- Mode bits that must match.
422 ** user_info -- Information on the user to use for file
424 ** stat_info -- A place to put the stat info for the file.
426 ** SMDBE_OK -- Success, otherwise errno.
430 smdb_setup_file(db_name
, extension
, mode_mask
, sff
, user_info
, stat_info
)
435 SMDB_USER_INFO
*user_info
;
436 struct stat
*stat_info
;
440 char db_file_name
[MAXPATHLEN
];
442 result
= smdb_add_extension(db_file_name
, sizeof db_file_name
, db_name
,
444 if (result
!= SMDBE_OK
)
447 st
= safefile(db_file_name
, user_info
->smdbu_id
,
448 user_info
->smdbu_group_id
, user_info
->smdbu_name
,
449 sff
, mode_mask
, stat_info
);
456 ** SMDB_FILECHANGED -- Checks to see if a file changed.
458 ** Compares the passed in stat_info with a current stat on
459 ** the passed in file descriptor. Check filechanged for
463 ** db_name -- The name of the database without extension.
464 ** extension -- The extension.
465 ** db_fd -- A file descriptor for the database file.
466 ** stat_info -- An old stat_info.
468 ** SMDBE_OK -- Success, otherwise errno.
472 smdb_filechanged(db_name
, extension
, db_fd
, stat_info
)
476 struct stat
*stat_info
;
479 char db_file_name
[MAXPATHLEN
];
481 result
= smdb_add_extension(db_file_name
, sizeof db_file_name
, db_name
,
483 if (result
!= SMDBE_OK
)
485 return filechanged(db_file_name
, db_fd
, stat_info
);
488 ** SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types.
498 smdb_print_available_types()
509 ** SMDB_DB_DEFINITION -- Given a database type, return database definition
511 ** Reads though a structure making an association with the database
512 ** type and the required cpp define from sendmail/README.
513 ** List size is dynamic and must be NULL terminated.
516 ** type -- The name of the database type.
519 ** definition for type, otherwise NULL.
528 static dbtype DatabaseDefs
[] =
530 { SMDB_TYPE_HASH
, "NEWDB" },
531 { SMDB_TYPE_BTREE
, "NEWDB" },
532 { SMDB_TYPE_NDBM
, "NDBM" },
537 smdb_db_definition(type
)
540 dbtype
*ptr
= DatabaseDefs
;
542 while (ptr
!= NULL
&& ptr
->type
!= NULL
)
544 if (strcmp(type
, ptr
->type
) == 0)