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