-
Notifications
You must be signed in to change notification settings - Fork 271
/
dict-cdb.c
128 lines (106 loc) · 2.69 KB
/
dict-cdb.c
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
#include "lib.h"
#ifdef BUILD_CDB
#include "dict-private.h"
#include <string.h>
#include <cdb.h>
#include <unistd.h>
#include <fcntl.h>
#define CDB_WITH_NULL 1
#define CDB_WITHOUT_NULL 2
struct cdb_dict {
struct dict dict;
struct cdb cdb;
char *path;
int fd, flag;
};
static void cdb_dict_deinit(struct dict *_dict);
static int
cdb_dict_init(struct dict *driver, const char *uri,
const struct dict_settings *set ATTR_UNUSED,
struct dict **dict_r, const char **error_r)
{
struct cdb_dict *dict;
dict = i_new(struct cdb_dict, 1);
dict->dict = *driver;
dict->path = i_strdup(uri);
dict->flag = CDB_WITH_NULL | CDB_WITHOUT_NULL;
/* initialize cdb to 0 (unallocated) */
memset(&dict->cdb, 0, sizeof(struct cdb));
dict->fd = open(dict->path, O_RDONLY);
if (dict->fd == -1) {
*error_r = t_strdup_printf("open(%s) failed: %m", dict->path);
cdb_dict_deinit(&dict->dict);
return -1;
}
#ifdef TINYCDB_VERSION
if (cdb_init(&dict->cdb, dict->fd) < 0) {
*error_r = t_strdup_printf("cdb_init(%s) failed: %m", dict->path);
cdb_dict_deinit(&dict->dict);
return -1;
}
#else
cdb_init(&dict->cdb, dict->fd);
#endif
*dict_r = &dict->dict;
return 0;
}
static void cdb_dict_deinit(struct dict *_dict)
{
struct cdb_dict *dict = (struct cdb_dict *)_dict;
/* we can safely deinit unallocated cdb */
cdb_free(&dict->cdb);
if (dict->fd != -1) {
if (close(dict->fd) < 0)
i_error("close(%s) failed: %m", dict->path);
}
i_free(dict->path);
i_free(dict);
}
static int cdb_dict_lookup(struct dict *_dict, pool_t pool,
const char *key, const char **value_r)
{
struct cdb_dict *dict = (struct cdb_dict *)_dict;
unsigned datalen;
int ret = 0;
char *data;
/* keys and values may be null terminated... */
if ((dict->flag & CDB_WITH_NULL) != 0) {
ret = cdb_find(&dict->cdb, key, (unsigned)strlen(key)+1);
if (ret > 0)
dict->flag &= ~CDB_WITHOUT_NULL;
}
/* ...or not */
if (ret == 0 && (dict->flag & CDB_WITHOUT_NULL) != 0) {
ret = cdb_find(&dict->cdb, key, (unsigned)strlen(key));
if (ret > 0)
dict->flag &= ~CDB_WITH_NULL;
}
if (ret <= 0) {
*value_r = NULL;
/* something bad with db */
if (ret < 0) {
i_error("cdb_find(%s) failed: %m", dict->path);
return -1;
}
/* found nothing */
return 0;
}
datalen = cdb_datalen(&dict->cdb);
data = p_malloc(pool, datalen + 1);
if (cdb_read(&dict->cdb, data, datalen, cdb_datapos(&dict->cdb)) < 0) {
i_error("cdb_read(%s) failed: %m", dict->path);
return -1;
}
*value_r = data;
return 1;
}
struct dict dict_driver_cdb = {
.name = "cdb",
{
.init = cdb_dict_init,
.deinit = cdb_dict_deinit,
.lookup = cdb_dict_lookup,
}
};
#endif