1/*++ 2/* NAME 3/* mkmap_dbm 3 4/* SUMMARY 5/* create or open database, DBM style 6/* SYNOPSIS 7/* #include <mkmap.h> 8/* 9/* MKMAP *mkmap_dbm_open(path) 10/* const char *path; 11/* DESCRIPTION 12/* This module implements support for creating DBM databases. 13/* 14/* mkmap_dbm_open() takes a file name, appends the ".dir" and ".pag" 15/* suffixes, and creates or opens the named DBM database. 16/* This routine is a DBM-specific helper for the more general 17/* mkmap_open() routine. 18/* 19/* All errors are fatal. 20/* SEE ALSO 21/* dict_dbm(3), DBM dictionary interface. 22/* LICENSE 23/* .ad 24/* .fi 25/* The Secure Mailer license must be distributed with this software. 26/* AUTHOR(S) 27/* Wietse Venema 28/* IBM T.J. Watson Research 29/* P.O. Box 704 30/* Yorktown Heights, NY 10598, USA 31/*--*/ 32 33/* System library. */ 34 35#include <sys_defs.h> 36#include <unistd.h> 37 38/* Utility library. */ 39 40#include <msg.h> 41#include <mymalloc.h> 42#include <stringops.h> 43#include <dict.h> 44#include <dict_dbm.h> 45#include <myflock.h> 46 47/* Application-specific. */ 48 49#include "mkmap.h" 50 51#ifdef HAS_DBM 52#ifdef PATH_NDBM_H 53#include PATH_NDBM_H 54#else 55#include <ndbm.h> 56#endif 57 58typedef struct MKMAP_DBM { 59 MKMAP mkmap; /* parent class */ 60 char *lock_file; /* path name */ 61 int lock_fd; /* -1 or open locked file */ 62} MKMAP_DBM; 63 64/* mkmap_dbm_after_close - clean up after closing database */ 65 66static void mkmap_dbm_after_close(MKMAP *mp) 67{ 68 MKMAP_DBM *mkmap = (MKMAP_DBM *) mp; 69 70 if (mkmap->lock_fd >= 0 && close(mkmap->lock_fd) < 0) 71 msg_warn("close %s: %m", mkmap->lock_file); 72 myfree(mkmap->lock_file); 73} 74 75/* mkmap_dbm_open - create or open database */ 76 77MKMAP *mkmap_dbm_open(const char *path) 78{ 79 MKMAP_DBM *mkmap = (MKMAP_DBM *) mymalloc(sizeof(*mkmap)); 80 char *pag_file; 81 int pag_fd; 82 83 /* 84 * Fill in the generic members. 85 */ 86 mkmap->lock_file = concatenate(path, ".dir", (char *) 0); 87 mkmap->mkmap.open = dict_dbm_open; 88 mkmap->mkmap.after_open = 0; 89 mkmap->mkmap.after_close = mkmap_dbm_after_close; 90 91 /* 92 * Unfortunately, not all systems support locking on open(), so we open 93 * the .dir and .pag files before truncating them. Keep one file open for 94 * locking. 95 */ 96 if ((mkmap->lock_fd = open(mkmap->lock_file, O_CREAT | O_RDWR, 0644)) < 0) 97 msg_fatal("open %s: %m", mkmap->lock_file); 98 99 pag_file = concatenate(path, ".pag", (char *) 0); 100 if ((pag_fd = open(pag_file, O_CREAT | O_RDWR, 0644)) < 0) 101 msg_fatal("open %s: %m", pag_file); 102 if (close(pag_fd)) 103 msg_warn("close %s: %m", pag_file); 104 myfree(pag_file); 105 106 /* 107 * Get an exclusive lock - we're going to change the database so we can't 108 * have any spectators. 109 */ 110 if (myflock(mkmap->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0) 111 msg_fatal("lock %s: %m", mkmap->lock_file); 112 113 return (&mkmap->mkmap); 114} 115 116#endif 117