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