1 /*	$NetBSD: mkmap_sdbm.c,v 1.1.1.1 2009/06/23 10:08:47 tron Exp $	*/
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 
57 typedef 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 
65 static 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 
76 MKMAP  *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