-
Notifications
You must be signed in to change notification settings - Fork 271
/
dict-cdb.c
130 lines (108 loc) · 2.77 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
129
130
/* Copyright (c) 2013-2016 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,
enum dict_data_type value_type ATTR_UNUSED,
const char *username ATTR_UNUSED,
const char *base_dir 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(dict->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