1 /* $NetBSD: mkmap_dbm.c,v 1.2 2023/12/23 20:30:46 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* mkmap_dbm 3 6 /* SUMMARY 7 /* create or open database, DBM style 8 /* SYNOPSIS 9 /* #include <dict_dbm.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 /* Wietse Venema 35 /* Google, Inc. 36 /* 111 8th Avenue 37 /* New York, NY 10011, USA 38 /*--*/ 39 40 /* System library. */ 41 42 #include <sys_defs.h> 43 #include <unistd.h> 44 45 /* Utility library. */ 46 47 #include <msg.h> 48 #include <mymalloc.h> 49 #include <stringops.h> 50 #include <dict_dbm.h> 51 #include <myflock.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 60 typedef 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 68 static 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 79 MKMAP *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