]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/cdb.cc
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
26 #include <sys/types.h>
33 CDB::CDB(const string
&cdbfile
)
35 d_fd
= open(cdbfile
.c_str(), O_RDONLY
);
38 throw std::runtime_error("Failed to open cdb database file '"+cdbfile
+"': " + stringerror());
41 memset(&d_cdbf
,0,sizeof(struct cdb_find
));
42 int cdbinit
= cdb_init(&d_cdb
, d_fd
);
47 throw std::runtime_error("Failed to initialize cdb structure for database '+cdbfile+': '" + std::to_string(cdbinit
) + "'");
56 int CDB::searchKey(const string
&key
) {
57 d_searchType
= SearchKey
;
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.
62 return cdb_findinit(&d_cdbf
, &d_cdb
, d_key
.c_str(), d_key
.size());
65 bool CDB::searchSuffix(const string
&key
) {
66 d_searchType
= SearchSuffix
;
68 //See CDB::searchKey()
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);
74 cdb_seqinit(&d_seqPtr
, &d_cdb
);
80 void CDB::searchAll() {
81 d_searchType
= SearchAll
;
82 cdb_seqinit(&d_seqPtr
, &d_cdb
);
85 bool CDB::moveToNext() {
87 if (d_searchType
== SearchKey
) {
88 hasNext
= cdb_findnext(&d_cdbf
);
90 hasNext
= cdb_seqnext(&d_seqPtr
, &d_cdb
);
95 bool CDB::readNext(pair
<string
, string
> &value
) {
96 while (moveToNext()) {
100 pos
= cdb_keypos(&d_cdb
);
101 len
= cdb_keylen(&d_cdb
);
105 int ret
= cdb_read(&d_cdb
, &key
[0], len
, pos
);
107 throw std::runtime_error("Error while reading key for key '" + key
+ "' from CDB database: " + std::to_string(ret
));
110 if (d_searchType
== SearchSuffix
) {
111 char *p
= strstr(const_cast<char*>(key
.c_str()), d_key
.c_str());
117 pos
= cdb_datapos(&d_cdb
);
118 len
= cdb_datalen(&d_cdb
);
121 ret
= cdb_read(&d_cdb
, &val
[0], len
, pos
);
123 throw std::runtime_error("Error while reading value for key '" + key
+ "' from CDB database: " + std::to_string(ret
));
126 value
= {std::move(key
), std::move(val
)};
130 // We're done searching, so we can clean up d_key
131 if (d_searchType
!= SearchAll
) {
138 vector
<string
> CDB::findall(string
&key
)
141 struct cdb_find cdbf
;
143 int res
= cdb_findinit(&cdbf
, &d_cdb
, key
.c_str(), key
.size());
145 throw std::runtime_error("Error looking up key '" + key
+ "' from CDB database: " + std::to_string(res
));
148 while(cdb_findnext(&cdbf
) > 0) {
149 unsigned int vpos
= cdb_datapos(&d_cdb
);
150 unsigned int vlen
= cdb_datalen(&d_cdb
);
153 res
= cdb_read(&d_cdb
, &val
[0], vlen
, vpos
);
155 throw std::runtime_error("Error while reading value for key '" + key
+ "' from CDB database: " + std::to_string(res
));
157 ret
.push_back(std::move(val
));
163 bool CDB::keyExists(const string
& key
)
165 int ret
= cdb_find(&d_cdb
, key
.c_str(), key
.size());
167 throw std::runtime_error("Error while looking up key '" + key
+ "' from CDB database: " + std::to_string(ret
));
177 bool CDB::findOne(const string
& key
, string
& value
)
179 if (!keyExists(key
)) {
183 unsigned int vpos
= cdb_datapos(&d_cdb
);
184 unsigned int vlen
= cdb_datalen(&d_cdb
);
186 int ret
= cdb_read(&d_cdb
, &value
[0], vlen
, vpos
);
188 throw std::runtime_error("Error while reading value for key '" + key
+ "' from CDB database: " + std::to_string(ret
));
194 CDBWriter::CDBWriter(int fd
): d_fd(fd
)
196 cdb_make_start(&d_cdbm
, d_fd
);
199 CDBWriter::~CDBWriter()
204 void CDBWriter::close()
207 cdb_make_finish(&d_cdbm
);
213 bool CDBWriter::addEntry(const std::string
& key
, const std::string
& value
)
216 throw std::runtime_error("Can't add an entry to a closed CDB database");
219 int ret
= cdb_make_add(&d_cdbm
, key
.c_str(), key
.size(), value
.c_str(), value
.size());
221 throw std::runtime_error("Error adding key '" + key
+ "' to CDB database: " + std::to_string(ret
));