summaryrefslogtreecommitdiffstats
path: root/src/global/mkmap_sdbm.c
blob: 7e87e4e823e2a78584c274dc549c0162d9d364cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*++
/* NAME
/*	mkmap_sdbm 3
/* SUMMARY
/*	create or open database, SDBM style
/* SYNOPSIS
/*	#include <mkmap.h>
/*
/*	MKMAP	*mkmap_sdbm_open(path)
/*	const char *path;
/* DESCRIPTION
/*	This module implements support for creating SDBM databases.
/*
/*	mkmap_sdbm_open() takes a file name, appends the ".dir" and ".pag"
/*	suffixes, and creates or opens the named SDBM database.
/*	This routine is a SDBM-specific helper for the more general
/*	mkmap_open() routine.
/*
/*	All errors are fatal.
/* SEE ALSO
/*	dict_sdbm(3), SDBM dictionary interface.
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

/* System library. */

#include <sys_defs.h>
#include <unistd.h>

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>
#include <stringops.h>
#include <dict.h>
#include <dict_sdbm.h>
#include <myflock.h>

/* Application-specific. */

#include "mkmap.h"

#ifdef HAS_SDBM

#include <sdbm.h>

typedef struct MKMAP_SDBM {
    MKMAP   mkmap;			/* parent class */
    char   *lock_file;			/* path name */
    int     lock_fd;			/* -1 or open locked file */
} MKMAP_SDBM;

/* mkmap_sdbm_after_close - clean up after closing database */

static void mkmap_sdbm_after_close(MKMAP *mp)
{
    MKMAP_SDBM *mkmap = (MKMAP_SDBM *) mp;

    if (mkmap->lock_fd >= 0 && close(mkmap->lock_fd) < 0)
	msg_warn("close %s: %m", mkmap->lock_file);
    myfree(mkmap->lock_file);
}

/* mkmap_sdbm_open - create or open database */

MKMAP  *mkmap_sdbm_open(const char *path)
{
    MKMAP_SDBM *mkmap = (MKMAP_SDBM *) mymalloc(sizeof(*mkmap));
    char   *pag_file;
    int     pag_fd;

    /*
     * Fill in the generic members.
     */
    mkmap->lock_file = concatenate(path, ".dir", (char *) 0);
    mkmap->mkmap.open = dict_sdbm_open;
    mkmap->mkmap.after_open = 0;
    mkmap->mkmap.after_close = mkmap_sdbm_after_close;

    /*
     * Unfortunately, not all systems support locking on open(), so we open
     * the .dir and .pag files before truncating them. Keep one file open for
     * locking.
     */
    if ((mkmap->lock_fd = open(mkmap->lock_file, O_CREAT | O_RDWR, 0644)) < 0)
	msg_fatal("open %s: %m", mkmap->lock_file);

    pag_file = concatenate(path, ".pag", (char *) 0);
    if ((pag_fd = open(pag_file, O_CREAT | O_RDWR, 0644)) < 0)
	msg_fatal("open %s: %m", pag_file);
    if (close(pag_fd))
	msg_warn("close %s: %m", pag_file);
    myfree(pag_file);

    /*
     * Get an exclusive lock - we're going to change the database so we can't
     * have any spectators.
     */
    if (myflock(mkmap->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
	msg_fatal("lock %s: %m", mkmap->lock_file);

    return (&mkmap->mkmap);
}

#endif