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