]> git.ipfire.org Git - thirdparty/pdns.git/blob - modules/tinydnsbackend/cdb.cc
e6d1e7b43e21968692138a623d2c8d09873caff6
[thirdparty/pdns.git] / modules / tinydnsbackend / cdb.cc
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include "cdb.hh"
5 #include <cdb.h>
6 #include "pdns/misc.hh"
7 #include "pdns/iputils.hh"
8 #include <utility>
9
10
11 CDB::CDB(const string &cdbfile)
12 {
13 d_fd = open(cdbfile.c_str(), O_RDONLY);
14 if (d_fd < 0)
15 {
16 L<<Logger::Error<<"Failed to open cdb database file '"<<cdbfile<<"'. Error: "<<stringerror()<<endl;
17 throw new PDNSException("Failed to open cdb database file '"+cdbfile+"'. Error: " + stringerror());
18 }
19
20 memset(&d_cdbf,0,sizeof(struct cdb_find));
21 int cdbinit = cdb_init(&d_cdb, d_fd);
22 if (cdbinit < 0)
23 {
24 L<<Logger::Error<<"Failed to initialize cdb structure. ErrorNr: '"<<cdbinit<<endl;
25 throw new PDNSException("Failed to initialize cdb structure.");
26 }
27
28 d_key = NULL;
29 d_seqPtr = 0;
30 d_searchType = SearchKey;
31 }
32
33 CDB::~CDB() {
34 cdb_free(&d_cdb);
35 close(d_fd);
36 }
37
38 int CDB::searchKey(const string &key) {
39 d_searchType = SearchKey;
40
41 // A 'bug' in tinycdb (the lib used for reading the CDB files) means we have to copy the key because the cdb_find struct
42 // keeps a pointer to it.
43 d_key = strdup(key.c_str());
44 return cdb_findinit(&d_cdbf, &d_cdb, d_key, key.size());
45 }
46
47 bool CDB::searchSuffix(const string &key) {
48 d_searchType = SearchSuffix;
49
50 //See CDB::searchKey()
51 d_key = strdup(key.c_str());
52
53 // We are ok with a search on things, but we do want to know if a record with that key exists.........
54 bool hasDomain = (cdb_find(&d_cdb, key.c_str(), key.size()) == 1);
55 if (hasDomain) {
56 cdb_seqinit(&d_seqPtr, &d_cdb);
57 }
58
59 return hasDomain;
60 }
61
62 void CDB::searchAll() {
63 d_searchType = SearchAll;
64 cdb_seqinit(&d_seqPtr, &d_cdb);
65 }
66
67 bool CDB::moveToNext() {
68 int hasNext = 0;
69 if (d_searchType == SearchKey) {
70 hasNext = cdb_findnext(&d_cdbf);
71 } else {
72 hasNext = cdb_seqnext(&d_seqPtr, &d_cdb);
73 }
74 return (hasNext > 0);
75 }
76
77 bool CDB::readNext(pair<string, string> &value) {
78 while (moveToNext()) {
79 unsigned int pos;
80 unsigned int len;
81
82 pos = cdb_keypos(&d_cdb);
83 len = cdb_keylen(&d_cdb);
84
85 char *key = (char *)malloc(len);
86 cdb_read(&d_cdb, key, len, pos);
87
88 if (d_searchType == SearchSuffix) {
89 char *p = strstr(key, d_key);
90 if (p == NULL) {
91 free(key);
92 continue;
93 }
94 }
95 string skey(key, len);
96 free(key);
97
98 pos = cdb_datapos(&d_cdb);
99 len = cdb_datalen(&d_cdb);
100 char *val = (char *)malloc(len);
101 cdb_read(&d_cdb, val, len, pos);
102 string sval(val, len);
103 free(val);
104
105 value = make_pair(skey, sval);
106 return true;
107 }
108 // We're done searching, so we can clean up d_key
109 if (d_searchType != SearchAll) {
110 free(d_key);
111 }
112 return false;
113 }
114
115 vector<string> CDB::findall(string &key)
116 {
117 vector<string> ret;
118 struct cdb_find cdbf;
119
120 cdb_findinit(&cdbf, &d_cdb, key.c_str(), key.size());
121 int x=0;
122 while(cdb_findnext(&cdbf) > 0) {
123 x++;
124 unsigned int vpos = cdb_datapos(&d_cdb);
125 unsigned int vlen = cdb_datalen(&d_cdb);
126 char *val = (char *)malloc(vlen);
127 cdb_read(&d_cdb, val, vlen, vpos);
128 string sval(val, vlen);
129 ret.push_back(sval);
130 free(val);
131 }
132 return ret;
133 }