46 #error "Error: you are including the Berkeley DB version of ndbm.h"
47 #error "To build with Postfix NDBM support, delete the Berkeley DB ndbm.h file"
74 #define SCOPY(buf, data, size) \
75 vstring_str(vstring_strncpy(buf ? buf : (buf = vstring_alloc(10)), data, size))
79 static const char *dict_dbm_lookup(
DICT *dict,
const char *name)
81 DICT_DBM *dict_dbm = (DICT_DBM *) dict;
84 const char *result = 0;
92 msg_panic(
"dict_dbm_lookup: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag");
109 msg_fatal(
"%s: lock dictionary: %m", dict_dbm->dict.name);
116 dbm_key.dptr = (
void *) name;
117 dbm_key.dsize = strlen(name) + 1;
118 dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key);
119 if (dbm_value.dptr != 0) {
121 result = SCOPY(dict_dbm->val_buf, dbm_value.dptr, dbm_value.dsize);
130 dbm_key.dptr = (
void *) name;
131 dbm_key.dsize = strlen(name);
132 dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key);
133 if (dbm_value.dptr != 0) {
135 result = SCOPY(dict_dbm->val_buf, dbm_value.dptr, dbm_value.dsize);
144 msg_fatal(
"%s: unlock dictionary: %m", dict_dbm->dict.name);
151 static int dict_dbm_update(
DICT *dict,
const char *name,
const char *value)
153 DICT_DBM *dict_dbm = (DICT_DBM *) dict;
164 msg_panic(
"dict_dbm_update: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag");
175 dbm_key.dptr = (
void *) name;
176 dbm_value.dptr = (
void *) value;
177 dbm_key.dsize = strlen(name);
178 dbm_value.dsize = strlen(value);
186 #ifdef DBM_NO_TRAILING_NULL
206 msg_fatal(
"%s: lock dictionary: %m", dict_dbm->dict.name);
211 if ((status = dbm_store(dict_dbm->dbm, dbm_key, dbm_value,
213 msg_fatal(
"error writing DBM database %s: %m", dict_dbm->dict.name);
218 msg_warn(
"%s: duplicate entry: \"%s\"", dict_dbm->dict.name, name);
220 msg_fatal(
"%s: duplicate entry: \"%s\"", dict_dbm->dict.name, name);
228 msg_fatal(
"%s: unlock dictionary: %m", dict_dbm->dict.name);
235 static int dict_dbm_delete(
DICT *dict,
const char *name)
237 DICT_DBM *dict_dbm = (DICT_DBM *) dict;
247 msg_panic(
"dict_dbm_delete: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag");
264 msg_fatal(
"%s: lock dictionary: %m", dict_dbm->dict.name);
271 dbm_key.dptr = (
void *) name;
272 dbm_key.dsize = strlen(name) + 1;
273 dbm_clearerr(dict_dbm->dbm);
274 if ((status = dbm_delete(dict_dbm->dbm, dbm_key)) < 0) {
275 if (dbm_error(dict_dbm->dbm) != 0)
276 msg_fatal(
"error deleting from %s: %m", dict_dbm->dict.name);
288 dbm_key.dptr = (
void *) name;
289 dbm_key.dsize = strlen(name);
290 dbm_clearerr(dict_dbm->dbm);
291 if ((status = dbm_delete(dict_dbm->dbm, dbm_key)) < 0) {
292 if (dbm_error(dict_dbm->dbm) != 0)
293 msg_fatal(
"error deleting from %s: %m", dict_dbm->dict.name);
305 msg_fatal(
"%s: unlock dictionary: %m", dict_dbm->dict.name);
312 static int dict_dbm_sequence(
DICT *dict,
int function,
313 const char **key,
const char **value)
315 const char *myname =
"dict_dbm_sequence";
316 DICT_DBM *dict_dbm = (DICT_DBM *) dict;
328 msg_fatal(
"%s: lock dictionary: %m", dict_dbm->dict.name);
335 dbm_key = dbm_firstkey(dict_dbm->dbm);
338 dbm_key = dbm_nextkey(dict_dbm->dbm);
341 msg_panic(
"%s: invalid function: %d", myname,
function);
344 if (dbm_key.dptr != 0 && dbm_key.dsize > 0) {
349 *key = SCOPY(dict_dbm->key_buf, dbm_key.dptr, dbm_key.dsize);
354 dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key);
356 if (dbm_value.dptr != 0 && dbm_value.dsize > 0) {
361 *value = SCOPY(dict_dbm->val_buf, dbm_value.dptr, dbm_value.dsize);
369 if (dbm_error(dict_dbm->dbm))
370 msg_fatal(
"error seeking %s: %m", dict_dbm->dict.name);
379 if (dbm_error(dict_dbm->dbm))
380 msg_fatal(
"error seeking %s: %m", dict_dbm->dict.name);
389 msg_fatal(
"%s: unlock dictionary: %m", dict_dbm->dict.name);
396 static void dict_dbm_close(
DICT *dict)
398 DICT_DBM *dict_dbm = (DICT_DBM *) dict;
400 dbm_close(dict_dbm->dbm);
401 if (dict_dbm->key_buf)
403 if (dict_dbm->val_buf)
423 #define DICT_DBM_OPEN_RETURN(d) do { \
439 if ((lock_fd = open(dbm_path, open_flags, 0644)) < 0)
441 open_flags, dict_flags,
442 "open database %s: %m",
445 msg_fatal(
"shared-lock database %s for open: %m", dbm_path);
451 if ((dbm = dbm_open((
char *) path, open_flags, 0644)) == 0)
453 open_flags, dict_flags,
454 "open database %s.{dir,pag}: %m",
457 if (dict_flags & DICT_FLAG_LOCK) {
459 msg_fatal(
"unlock database %s for open: %m", dbm_path);
460 if (close(lock_fd) < 0)
461 msg_fatal(
"close database %s: %m", dbm_path);
464 dict_dbm->dict.
lookup = dict_dbm_lookup;
465 dict_dbm->dict.update = dict_dbm_update;
466 dict_dbm->dict.delete = dict_dbm_delete;
467 dict_dbm->dict.sequence = dict_dbm_sequence;
468 dict_dbm->dict.close = dict_dbm_close;
469 dict_dbm->dict.lock_fd = dbm_dirfno(dbm);
470 dict_dbm->dict.stat_fd = dbm_pagfno(dbm);
471 if (dict_dbm->dict.lock_fd == dict_dbm->dict.stat_fd)
472 msg_fatal(
"open database %s: cannot support GDBM", path);
473 if (
fstat(dict_dbm->dict.stat_fd, &st) < 0)
475 dict_dbm->dict.mtime = st.st_mtime;
476 dict_dbm->dict.owner.uid = st.st_uid;
477 dict_dbm->dict.owner.status = (st.st_uid != 0);
483 if ((dict_flags & DICT_FLAG_LOCK) != 0
484 &&
stat(path, &st) == 0
485 && st.st_mtime > dict_dbm->dict.mtime
486 && st.st_mtime < time((time_t *) 0) - 100)
487 msg_warn(
"database %s is older than source file %s", dbm_path, path);
497 dict_dbm->key_buf = 0;
498 dict_dbm->val_buf = 0;
500 DICT_DBM_OPEN_RETURN(
DICT_DEBUG (&dict_dbm->dict));
#define DICT_FLAG_DUP_IGNORE
#define MYFLOCK_OP_SHARED
#define DICT_SEQ_FUN_FIRST
NORETURN msg_panic(const char *fmt,...)
#define DICT_SEQ_FUN_NEXT
#define MYFLOCK_OP_EXCLUSIVE
#define DICT_FLAG_FOLD_FIX
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
#define DICT_FLAG_DUP_REPLACE
#define DICT_FLAG_TRY1NULL
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
int myflock(int fd, int lock_style, int operation)
char * lowercase(char *string)
const char *(* lookup)(struct DICT *, const char *)
#define DICT_FLAG_DUP_WARN
NORETURN msg_fatal(const char *fmt,...)
char * concatenate(const char *arg0,...)
VSTRING * vstring_free(VSTRING *vp)
DICT * dict_dbm_open(const char *, int, int)
DICT * dict_alloc(const char *, const char *, ssize_t)
#define DICT_FLAG_TRY0NULL
int close_on_exec(int fd, int on)
DICT * dict_surrogate(const char *dict_type, const char *dict_name, int open_flags, int dict_flags, const char *fmt,...)