1/*++ 2/* NAME 3/* mkmap_sdbm 3 4/* SUMMARY 5/* create or open database, SDBM style 6/* SYNOPSIS 7/* #include <mkmap.h> 8/* 9/* MKMAP *mkmap_sdbm_open(path) 10/* const char *path; 11/* DESCRIPTION 12/* This module implements support for creating SDBM databases. 13/* 14/* mkmap_sdbm_open() takes a file name, appends the ".dir" and ".pag" 15/* suffixes, and creates or opens the named SDBM database. 16/* This routine is a SDBM-specific helper for the more general 17/* mkmap_open() routine. 18/* 19/* All errors are fatal. 20/* SEE ALSO 21/* dict_sdbm(3), SDBM 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_sdbm.h> 45#include <myflock.h> 46 47/* Application-specific. */ 48 49#include "mkmap.h" 50 51#ifdef HAS_SDBM 52 53#include <sdbm.h> 54 55typedef struct MKMAP_SDBM { 56 MKMAP mkmap; /* parent class */ 57 char *lock_file; /* path name */ 58 int lock_fd; /* -1 or open locked file */ 59} MKMAP_SDBM; 60 61/* mkmap_sdbm_after_close - clean up after closing database */ 62 63static void mkmap_sdbm_after_close(MKMAP *mp) 64{ 65 MKMAP_SDBM *mkmap = (MKMAP_SDBM *) mp; 66 67 if (mkmap->lock_fd >= 0 && close(mkmap->lock_fd) < 0) 68 msg_warn("close %s: %m", mkmap->lock_file); 69 myfree(mkmap->lock_file); 70} 71 72/* mkmap_sdbm_open - create or open database */ 73 74MKMAP *mkmap_sdbm_open(const char *path) 75{ 76 MKMAP_SDBM *mkmap = (MKMAP_SDBM *) mymalloc(sizeof(*mkmap)); 77 char *pag_file; 78 int pag_fd; 79 80 /* 81 * Fill in the generic members. 82 */ 83 mkmap->lock_file = concatenate(path, ".dir", (char *) 0); 84 mkmap->mkmap.open = dict_sdbm_open; 85 mkmap->mkmap.after_open = 0; 86 mkmap->mkmap.after_close = mkmap_sdbm_after_close; 87 88 /* 89 * Unfortunately, not all systems support locking on open(), so we open 90 * the .dir and .pag files before truncating them. Keep one file open for 91 * locking. 92 */ 93 if ((mkmap->lock_fd = open(mkmap->lock_file, O_CREAT | O_RDWR, 0644)) < 0) 94 msg_fatal("open %s: %m", mkmap->lock_file); 95 96 pag_file = concatenate(path, ".pag", (char *) 0); 97 if ((pag_fd = open(pag_file, O_CREAT | O_RDWR, 0644)) < 0) 98 msg_fatal("open %s: %m", pag_file); 99 if (close(pag_fd)) 100 msg_warn("close %s: %m", pag_file); 101 myfree(pag_file); 102 103 /* 104 * Get an exclusive lock - we're going to change the database so we can't 105 * have any spectators. 106 */ 107 if (myflock(mkmap->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0) 108 msg_fatal("lock %s: %m", mkmap->lock_file); 109 110 return (&mkmap->mkmap); 111} 112 113#endif 114