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.
10 #pragma ident "%Z%%M% %I% %E% SMI"
13 SM_RCSID("@(#)$Id: smdb.c,v 8.58 2004/08/03 20:58:38 ca Exp $")
20 #include <sendmail/sendmail.h>
21 #include <libsmdb/smdb.h>
23 static bool smdb_lockfile
__P((int, int));
26 ** SMDB_MALLOC_DATABASE -- Allocates a database structure.
32 ** An pointer to an allocated SMDB_DATABASE structure or
33 ** NULL if it couldn't allocate the memory.
37 smdb_malloc_database()
41 db
= (SMDB_DATABASE
*) malloc(sizeof(SMDB_DATABASE
));
44 (void) memset(db
, '\0', sizeof(SMDB_DATABASE
));
51 ** SMDB_FREE_DATABASE -- Unallocates a database structure.
54 ** database -- a SMDB_DATABASE pointer to deallocate.
61 smdb_free_database(database
)
62 SMDB_DATABASE
*database
;
68 ** SMDB_LOCKFILE -- lock a file using flock or (shudder) fcntl locking
71 ** fd -- the file descriptor of the file.
72 ** type -- type of the lock. Bits can be:
73 ** LOCK_EX -- exclusive lock.
74 ** LOCK_NB -- non-blocking.
77 ** true if the lock was acquired.
82 smdb_lockfile(fd
, type
)
92 (void) memset(&lfd
, '\0', sizeof lfd
);
93 if (bitset(LOCK_UN
, type
))
95 else if (bitset(LOCK_EX
, type
))
100 if (bitset(LOCK_NB
, type
))
105 while ((i
= fcntl(fd
, action
, &lfd
)) < 0 && errno
== EINTR
)
112 ** On SunOS, if you are testing using -oQ/tmp/mqueue or
113 ** -oA/tmp/aliases or anything like that, and /tmp is mounted
114 ** as type "tmp" (that is, served from swap space), the
115 ** previous fcntl will fail with "Invalid argument" errors.
116 ** Since this is fairly common during testing, we will assume
117 ** that this indicates that the lock is successfully grabbed.
120 if (save_errno
== EINVAL
)
123 if (!bitset(LOCK_NB
, type
) ||
124 (save_errno
!= EACCES
&& save_errno
!= EAGAIN
))
127 int omode
= fcntl(fd
, F_GETFL
, NULL
);
128 int euid
= (int) geteuid();
130 syslog(LOG_ERR
, "cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
131 filename
, ext
, fd
, type
, omode
, euid
);
136 #else /* !HASFLOCK */
138 while ((i
= flock(fd
, type
)) < 0 && errno
== EINTR
)
144 if (!bitset(LOCK_NB
, type
) || save_errno
!= EWOULDBLOCK
)
147 int omode
= fcntl(fd
, F_GETFL
, NULL
);
148 int euid
= (int) geteuid();
150 syslog(LOG_ERR
, "cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
151 filename
, ext
, fd
, type
, omode
, euid
);
156 #endif /* !HASFLOCK */
161 ** SMDB_OPEN_DATABASE -- Opens a database.
163 ** This opens a database. If type is SMDB_DEFAULT it tries to
164 ** use a DB1 or DB2 hash. If that isn't available, it will try
165 ** to use NDBM. If a specific type is given it will try to open
166 ** a database of that type.
169 ** database -- An pointer to a SMDB_DATABASE pointer where the
170 ** opened database will be stored. This should
172 ** db_name -- The name of the database to open. Do not include
173 ** the file name extension.
174 ** mode -- The mode to set on the database file or files.
175 ** mode_mask -- Mode bits that must match on an opened database.
176 ** sff -- Flags to safefile.
177 ** type -- The type of database to open. Supported types
178 ** vary depending on what was compiled in.
179 ** user_info -- Information on the user to use for file
181 ** params -- Params specific to the database being opened.
182 ** Only supports some DB hash options right now
183 ** (see smdb_db_open() for details).
186 ** SMDBE_OK -- Success.
187 ** Anything else is an error. Look up more info about the
188 ** error in the comments for the specific open() used.
192 smdb_open_database(database
, db_name
, mode
, mode_mask
, sff
, type
, user_info
,
194 SMDB_DATABASE
**database
;
200 SMDB_USER_INFO
*user_info
;
201 SMDB_DBPARAMS
*params
;
203 bool type_was_default
= false;
205 if (type
== SMDB_TYPE_DEFAULT
)
207 type_was_default
= true;
209 type
= SMDB_TYPE_HASH
;
212 type
= SMDB_TYPE_NDBM
;
217 if (type
== SMDB_TYPE_DEFAULT
)
218 return SMDBE_UNKNOWN_DB_TYPE
;
220 if ((strncmp(type
, SMDB_TYPE_HASH
, SMDB_TYPE_HASH_LEN
) == 0) ||
221 (strncmp(type
, SMDB_TYPE_BTREE
, SMDB_TYPE_BTREE_LEN
) == 0))
226 result
= smdb_db_open(database
, db_name
, mode
, mode_mask
, sff
,
227 type
, user_info
, params
);
229 if (result
== ENOENT
&& type_was_default
)
230 type
= SMDB_TYPE_NDBM
;
235 return SMDBE_UNSUPPORTED_DB_TYPE
;
239 if (strncmp(type
, SMDB_TYPE_NDBM
, SMDB_TYPE_NDBM_LEN
) == 0)
244 result
= smdb_ndbm_open(database
, db_name
, mode
, mode_mask
,
245 sff
, type
, user_info
, params
);
248 return SMDBE_UNSUPPORTED_DB_TYPE
;
252 return SMDBE_UNKNOWN_DB_TYPE
;
255 ** SMDB_ADD_EXTENSION -- Adds an extension to a file name.
257 ** Just adds a . followed by a string to a db_name if there
258 ** is room and the db_name does not already have that extension.
261 ** full_name -- The final file name.
262 ** max_full_name_len -- The max length for full_name.
263 ** db_name -- The name of the db.
264 ** extension -- The extension to add.
267 ** SMDBE_OK -- Success.
268 ** Anything else is an error. Look up more info about the
269 ** error in the comments for the specific open() used.
273 smdb_add_extension(full_name
, max_full_name_len
, db_name
, extension
)
275 int max_full_name_len
;
282 if (full_name
== NULL
|| db_name
== NULL
|| extension
== NULL
)
283 return SMDBE_INVALID_PARAMETER
;
285 extension_len
= strlen(extension
);
286 db_name_len
= strlen(db_name
);
288 if (extension_len
+ db_name_len
+ 2 > max_full_name_len
)
289 return SMDBE_DB_NAME_TOO_LONG
;
291 if (db_name_len
< extension_len
+ 1 ||
292 db_name
[db_name_len
- extension_len
- 1] != '.' ||
293 strcmp(&db_name
[db_name_len
- extension_len
], extension
) != 0)
294 (void) sm_snprintf(full_name
, max_full_name_len
, "%s.%s",
297 (void) sm_strlcpy(full_name
, db_name
, max_full_name_len
);
302 ** SMDB_LOCK_FILE -- Locks the database file.
304 ** Locks the actual database file.
307 ** lock_fd -- The resulting descriptor for the locked file.
308 ** db_name -- The name of the database without extension.
309 ** mode -- The open mode.
310 ** sff -- Flags to safefile.
311 ** extension -- The extension for the file.
314 ** SMDBE_OK -- Success, otherwise errno.
318 smdb_lock_file(lock_fd
, db_name
, mode
, sff
, extension
)
326 char file_name
[MAXPATHLEN
];
328 result
= smdb_add_extension(file_name
, sizeof file_name
, db_name
,
330 if (result
!= SMDBE_OK
)
333 *lock_fd
= safeopen(file_name
, mode
& ~O_TRUNC
, DBMMODE
, sff
);
340 ** SMDB_UNLOCK_FILE -- Unlocks a file
345 ** lock_fd -- The descriptor for the locked file.
348 ** SMDBE_OK -- Success, otherwise errno.
352 smdb_unlock_file(lock_fd
)
357 result
= close(lock_fd
);
364 ** SMDB_LOCK_MAP -- Locks a database.
367 ** database -- database description.
368 ** type -- type of the lock. Bits can be:
369 ** LOCK_EX -- exclusive lock.
370 ** LOCK_NB -- non-blocking.
373 ** SMDBE_OK -- Success, otherwise errno.
377 smdb_lock_map(database
, type
)
378 SMDB_DATABASE
*database
;
383 fd
= database
->smdb_lockfd(database
);
385 return SMDBE_NOT_FOUND
;
386 if (!smdb_lockfile(fd
, type
))
387 return SMDBE_LOCK_NOT_GRANTED
;
391 ** SMDB_UNLOCK_MAP -- Unlocks a database
394 ** database -- database description.
397 ** SMDBE_OK -- Success, otherwise errno.
401 smdb_unlock_map(database
)
402 SMDB_DATABASE
*database
;
406 fd
= database
->smdb_lockfd(database
);
408 return SMDBE_NOT_FOUND
;
409 if (!smdb_lockfile(fd
, LOCK_UN
))
410 return SMDBE_LOCK_NOT_HELD
;
414 ** SMDB_SETUP_FILE -- Gets db file ready for use.
416 ** Makes sure permissions on file are safe and creates it if it
420 ** db_name -- The name of the database without extension.
421 ** extension -- The extension.
422 ** sff -- Flags to safefile.
423 ** mode_mask -- Mode bits that must match.
424 ** user_info -- Information on the user to use for file
426 ** stat_info -- A place to put the stat info for the file.
428 ** SMDBE_OK -- Success, otherwise errno.
432 smdb_setup_file(db_name
, extension
, mode_mask
, sff
, user_info
, stat_info
)
437 SMDB_USER_INFO
*user_info
;
438 struct stat
*stat_info
;
442 char db_file_name
[MAXPATHLEN
];
444 result
= smdb_add_extension(db_file_name
, sizeof db_file_name
, db_name
,
446 if (result
!= SMDBE_OK
)
449 st
= safefile(db_file_name
, user_info
->smdbu_id
,
450 user_info
->smdbu_group_id
, user_info
->smdbu_name
,
451 sff
, mode_mask
, stat_info
);
458 ** SMDB_FILECHANGED -- Checks to see if a file changed.
460 ** Compares the passed in stat_info with a current stat on
461 ** the passed in file descriptor. Check filechanged for
465 ** db_name -- The name of the database without extension.
466 ** extension -- The extension.
467 ** db_fd -- A file descriptor for the database file.
468 ** stat_info -- An old stat_info.
470 ** SMDBE_OK -- Success, otherwise errno.
474 smdb_filechanged(db_name
, extension
, db_fd
, stat_info
)
478 struct stat
*stat_info
;
481 char db_file_name
[MAXPATHLEN
];
483 result
= smdb_add_extension(db_file_name
, sizeof db_file_name
, db_name
,
485 if (result
!= SMDBE_OK
)
487 return filechanged(db_file_name
, db_fd
, stat_info
);
490 ** SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types.
500 smdb_print_available_types()
511 ** SMDB_DB_DEFINITION -- Given a database type, return database definition
513 ** Reads though a structure making an association with the database
514 ** type and the required cpp define from sendmail/README.
515 ** List size is dynamic and must be NULL terminated.
518 ** type -- The name of the database type.
521 ** definition for type, otherwise NULL.
530 static dbtype DatabaseDefs
[] =
532 { SMDB_TYPE_HASH
, "NEWDB" },
533 { SMDB_TYPE_BTREE
, "NEWDB" },
534 { SMDB_TYPE_NDBM
, "NDBM" },
539 smdb_db_definition(type
)
542 dbtype
*ptr
= DatabaseDefs
;
544 while (ptr
!= NULL
&& ptr
->type
!= NULL
)
546 if (strcmp(type
, ptr
->type
) == 0)