NetBSD/gnu/dist/postfix/global/mkmap_open.c

169 lines
3.9 KiB
C
Raw Normal View History

/*++
/* NAME
/* mkmap_open 3
/* SUMMARY
/* create or rewrite database, generic interface
/* SYNOPSIS
/* #include <mkmap.h>
/*
/* MKMAP *mkmap_open(type, path, open_flags, dict_flags)
/* char *type;
/* char *path;
/* int open_flags;
/* int dict_flags;
/*
/* void mkmap_append(mkmap, key, value, lineno)
/* MKMAP *mkmap;
/* char *key;
/* char *value;
/* int lineno;
/*
/* void mkmap_close(mkmap)
/* MKMAP *mkmap;
/* DESCRIPTION
/* This module implements support for creating Postfix databases.
/*
/* mkmap_open() creates or truncates the named database, after
/* appending the appropriate suffixes to the specified filename.
/* Before the database is updated, it is locked for exclusive
/* access, and signal delivery is suspended.
/* See dict(3) for a description of \fBopen_flags\fR and \fBdict_flags\fR.
/* All errors are fatal.
/*
/* mkmap_append() appends the named (key, value) pair to the
/* database. Update errors are fatal; duplicate keys are ignored
/* (but a warning is issued).
/* \fBlineno\fR is used for diagnostics.
/*
/* mkmap_close() closes the database, releases any locks,
/* and resumes signal delivery. All errors are fatal.
/* SEE ALSO
/* sigdelay(3) suspend/resume signal delivery
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <unistd.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
#include <dict.h>
#include <sigdelay.h>
#include <mymalloc.h>
#include <myflock.h>
/* Global library. */
#include "mkmap.h"
/*
* Information about available database types. Here, we list only those map
* types that exist as files. Network-based maps are not of interest.
*/
typedef struct {
char *type;
MKMAP *(*create_or_open) (const char *);
} MKMAP_OPEN_INFO;
MKMAP_OPEN_INFO mkmap_types[] = {
#ifdef HAS_DBM
"dbm", mkmap_dbm_open,
#endif
#ifdef HAS_DB
"hash", mkmap_hash_open,
"btree", mkmap_btree_open,
#endif
0,
};
/* mkmap_append - append entry to map */
void mkmap_append(MKMAP *mkmap, const char *key, const char *value)
{
dict_put(mkmap->dict, key, value);
}
/* mkmap_close - close database */
void mkmap_close(MKMAP *mkmap)
{
/*
* Close the database and the locking file descriptor.
*/
dict_close(mkmap->dict);
if (close(mkmap->lock_fd) < 0)
msg_warn("close %s: %m", mkmap->lock_file);
/*
* Resume signal delivery.
*/
sigresume();
/*
* Cleanup.
*/
myfree(mkmap->lock_file);
myfree((char *) mkmap);
}
/* mkmap_open - create or truncate database */
MKMAP *mkmap_open(const char *type, const char *path,
int open_flags, int dict_flags)
{
MKMAP *mkmap;
MKMAP_OPEN_INFO *mp;
/*
* Find out what map type to use.
*/
for (mp = mkmap_types; /* void */ ; mp++) {
if (mp->type == 0)
msg_fatal("unsupported map type: %s", type);
if (strcmp(type, mp->type) == 0)
break;
}
if (msg_verbose)
msg_info("open %s %s", type, path);
/*
* Create or open the desired map file(s).
*/
mkmap = mp->create_or_open(path);
/*
* Get an exclusive lock - we're going to change the database so we can't
* have any spectators.
*/
if (myflock(mkmap->lock_fd, MYFLOCK_EXCLUSIVE) < 0)
msg_fatal("lock %s: %m", mkmap->lock_file);
/*
* Delay signal delivery, so that we won't leave the database in an
* inconsistent state if we can avoid it.
*/
sigdelay();
/*
* Truncate the database upon open, and update it. Read-write mode is
* needed because the underlying routines read as well as write.
*/
mkmap->dict = mkmap->open(path, open_flags, dict_flags);
mkmap->dict->fd = -1; /* XXX just in case */
mkmap->dict->flags |= DICT_FLAG_DUP_WARN;
return (mkmap);
}