7 /* create or open database, DBM style
11 /* MKMAP *mkmap_dbm_open(path)
14 /* This module implements support for creating DBM databases.
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.
21 /* All errors are fatal.
23 /* dict_dbm(3), DBM dictionary interface.
27 /* The Secure Mailer license must be distributed with this software.
30 /* IBM T.J. Watson Research
32 /* Yorktown Heights, NY 10598, USA
40 /* Utility library. */
44 #include <stringops.h>
49 /* Application-specific. */
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 */
66 /* mkmap_dbm_after_close - clean up after closing database */
68 static void mkmap_dbm_after_close(MKMAP
*mp
)
70 MKMAP_DBM
*mkmap
= (MKMAP_DBM
*) mp
;
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
);
77 /* mkmap_dbm_open - create or open database */
79 MKMAP
*mkmap_dbm_open(const char *path
)
81 MKMAP_DBM
*mkmap
= (MKMAP_DBM
*) mymalloc(sizeof(*mkmap
));
86 * Fill in the generic members.
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
;
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
98 if ((mkmap
->lock_fd
= open(mkmap
->lock_file
, O_CREAT
| O_RDWR
, 0644)) < 0)
99 msg_fatal("open %s: %m", mkmap
->lock_file
);
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
);
105 msg_warn("close %s: %m", pag_file
);
109 * Get an exclusive lock - we're going to change the database so we can't
110 * have any spectators.
112 if (myflock(mkmap
->lock_fd
, INTERNAL_LOCK
, MYFLOCK_OP_EXCLUSIVE
) < 0)
113 msg_fatal("lock %s: %m", mkmap
->lock_file
);
115 return (&mkmap
->mkmap
);