xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/mkmap_dbm.c (revision c48c605c14fd8622b523d1d6a3f0c0bad133ea89)
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 
mkmap_dbm_after_close(MKMAP * mp)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 
mkmap_dbm_open(const char * path)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