]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/cdb.cc
Move cdb.{cc ,hh} to the pdns directory
[thirdparty/pdns.git] / pdns / cdb.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30
31 #include "cdb.hh"
32
33 CDB::CDB(const string &cdbfile)
34 {
35 d_fd = open(cdbfile.c_str(), O_RDONLY);
36 if (d_fd < 0)
37 {
38 throw std::runtime_error("Failed to open cdb database file '"+cdbfile+"'. Error: " + stringerror());
39 }
40
41 memset(&d_cdbf,0,sizeof(struct cdb_find));
42 int cdbinit = cdb_init(&d_cdb, d_fd);
43 if (cdbinit < 0)
44 {
45 close(d_fd);
46 d_fd = -1;
47 throw std::runtime_error("Failed to initialize cdb structure. ErrorNt: '" + std::to_string(cdbinit) + "'");
48 }
49 }
50
51 CDB::~CDB() {
52 cdb_free(&d_cdb);
53 close(d_fd);
54 }
55
56 int CDB::searchKey(const string &key) {
57 d_searchType = SearchKey;
58
59 // A 'bug' in tinycdb (the lib used for reading the CDB files) means we have to copy the key because the cdb_find struct
60 // keeps a pointer to it.
61 d_key = key;
62 return cdb_findinit(&d_cdbf, &d_cdb, d_key.c_str(), d_key.size());
63 }
64
65 bool CDB::searchSuffix(const string &key) {
66 d_searchType = SearchSuffix;
67
68 //See CDB::searchKey()
69 d_key = key;
70
71 // We are ok with a search on things, but we do want to know if a record with that key exists.........
72 bool hasDomain = (cdb_find(&d_cdb, d_key.c_str(), d_key.size()) == 1);
73 if (hasDomain) {
74 cdb_seqinit(&d_seqPtr, &d_cdb);
75 }
76
77 return hasDomain;
78 }
79
80 void CDB::searchAll() {
81 d_searchType = SearchAll;
82 cdb_seqinit(&d_seqPtr, &d_cdb);
83 }
84
85 bool CDB::moveToNext() {
86 int hasNext = 0;
87 if (d_searchType == SearchKey) {
88 hasNext = cdb_findnext(&d_cdbf);
89 } else {
90 hasNext = cdb_seqnext(&d_seqPtr, &d_cdb);
91 }
92 return (hasNext > 0);
93 }
94
95 bool CDB::readNext(pair<string, string> &value) {
96 while (moveToNext()) {
97 unsigned int pos;
98 unsigned int len;
99
100 pos = cdb_keypos(&d_cdb);
101 len = cdb_keylen(&d_cdb);
102
103 std::string key;
104 key.resize(len);
105 cdb_read(&d_cdb, &key[0], len, pos);
106
107 if (d_searchType == SearchSuffix) {
108 char *p = strstr(const_cast<char*>(key.c_str()), d_key.c_str());
109 if (p == nullptr) {
110 continue;
111 }
112 }
113
114 pos = cdb_datapos(&d_cdb);
115 len = cdb_datalen(&d_cdb);
116 std::string val;
117 val.resize(len);
118 cdb_read(&d_cdb, &val[0], len, pos);
119
120 value = make_pair(std::move(key), std::move(val));
121 return true;
122 }
123
124 // We're done searching, so we can clean up d_key
125 if (d_searchType != SearchAll) {
126 d_key.clear();
127 }
128
129 return false;
130 }
131
132 vector<string> CDB::findall(string &key)
133 {
134 vector<string> ret;
135 struct cdb_find cdbf;
136
137 cdb_findinit(&cdbf, &d_cdb, key.c_str(), key.size());
138 int x=0;
139 while(cdb_findnext(&cdbf) > 0) {
140 x++;
141 unsigned int vpos = cdb_datapos(&d_cdb);
142 unsigned int vlen = cdb_datalen(&d_cdb);
143 std::string val;
144 val.resize(vlen);
145 cdb_read(&d_cdb, &val[0], vlen, vpos);
146 ret.push_back(std::move(val));
147 }
148
149 return ret;
150 }