]> git.lizzy.rs Git - minetest.git/blob - src/database/database-leveldb.cpp
Add LevelDB auth database. (#9476)
[minetest.git] / src / database / database-leveldb.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "config.h"
21
22 #if USE_LEVELDB
23
24 #include "database-leveldb.h"
25
26 #include "log.h"
27 #include "filesys.h"
28 #include "exceptions.h"
29 #include "util/serialize.h"
30 #include "util/string.h"
31
32 #include "leveldb/db.h"
33
34
35 #define ENSURE_STATUS_OK(s) \
36         if (!(s).ok()) { \
37                 throw DatabaseException(std::string("LevelDB error: ") + \
38                                 (s).ToString()); \
39         }
40
41
42 Database_LevelDB::Database_LevelDB(const std::string &savedir)
43 {
44         leveldb::Options options;
45         options.create_if_missing = true;
46         leveldb::Status status = leveldb::DB::Open(options,
47                 savedir + DIR_DELIM + "map.db", &m_database);
48         ENSURE_STATUS_OK(status);
49 }
50
51 Database_LevelDB::~Database_LevelDB()
52 {
53         delete m_database;
54 }
55
56 bool Database_LevelDB::saveBlock(const v3s16 &pos, const std::string &data)
57 {
58         leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
59                         i64tos(getBlockAsInteger(pos)), data);
60         if (!status.ok()) {
61                 warningstream << "saveBlock: LevelDB error saving block "
62                         << PP(pos) << ": " << status.ToString() << std::endl;
63                 return false;
64         }
65
66         return true;
67 }
68
69 void Database_LevelDB::loadBlock(const v3s16 &pos, std::string *block)
70 {
71         std::string datastr;
72         leveldb::Status status = m_database->Get(leveldb::ReadOptions(),
73                 i64tos(getBlockAsInteger(pos)), &datastr);
74
75         *block = (status.ok()) ? datastr : "";
76 }
77
78 bool Database_LevelDB::deleteBlock(const v3s16 &pos)
79 {
80         leveldb::Status status = m_database->Delete(leveldb::WriteOptions(),
81                         i64tos(getBlockAsInteger(pos)));
82         if (!status.ok()) {
83                 warningstream << "deleteBlock: LevelDB error deleting block "
84                         << PP(pos) << ": " << status.ToString() << std::endl;
85                 return false;
86         }
87
88         return true;
89 }
90
91 void Database_LevelDB::listAllLoadableBlocks(std::vector<v3s16> &dst)
92 {
93         leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions());
94         for (it->SeekToFirst(); it->Valid(); it->Next()) {
95                 dst.push_back(getIntegerAsBlock(stoi64(it->key().ToString())));
96         }
97         ENSURE_STATUS_OK(it->status());  // Check for any errors found during the scan
98         delete it;
99 }
100
101 AuthDatabaseLevelDB::AuthDatabaseLevelDB(const std::string &savedir)
102 {
103         leveldb::Options options;
104         options.create_if_missing = true;
105         leveldb::Status status = leveldb::DB::Open(options,
106                 savedir + DIR_DELIM + "auth.db", &m_database);
107         ENSURE_STATUS_OK(status);
108 }
109
110 AuthDatabaseLevelDB::~AuthDatabaseLevelDB()
111 {
112         delete m_database;
113 }
114
115 bool AuthDatabaseLevelDB::getAuth(const std::string &name, AuthEntry &res)
116 {
117         std::string raw;
118         leveldb::Status s = m_database->Get(leveldb::ReadOptions(), name, &raw);
119         if (!s.ok())
120                 return false;
121         std::istringstream is(raw);
122
123         /*
124         u8 version = 1
125         std::string password
126         u16 number of privileges
127         for each privilege {
128                 std::string privilege
129         }
130         s64 last_login
131         */
132
133         if (readU8(is) > 1)
134                 return false;
135
136         res.id = 1;
137         res.name = name;
138         res.password = deSerializeString(is);
139
140         u16 privilege_count = readU16(is);
141         res.privileges.clear();
142         res.privileges.reserve(privilege_count);
143         for (u16 i = 0; i < privilege_count; i++) {
144                 res.privileges.push_back(deSerializeString(is));
145         }
146
147         res.last_login = readS64(is);
148         return true;
149 }
150
151 bool AuthDatabaseLevelDB::saveAuth(const AuthEntry &authEntry)
152 {
153         std::ostringstream os;
154         writeU8(os, 1);
155         os << serializeString(authEntry.password);
156
157         size_t privilege_count = authEntry.privileges.size();
158         FATAL_ERROR_IF(privilege_count > U16_MAX,
159                 "Unsupported number of privileges");
160         writeU16(os, privilege_count);
161         for (const std::string &privilege : authEntry.privileges) {
162                 os << serializeString(privilege);
163         }
164
165         writeS64(os, authEntry.last_login);
166         leveldb::Status s = m_database->Put(leveldb::WriteOptions(),
167                 authEntry.name, os.str());
168         return s.ok();
169 }
170
171 bool AuthDatabaseLevelDB::createAuth(AuthEntry &authEntry)
172 {
173         return saveAuth(authEntry);
174 }
175
176 bool AuthDatabaseLevelDB::deleteAuth(const std::string &name)
177 {
178         leveldb::Status s = m_database->Delete(leveldb::WriteOptions(), name);
179         return s.ok();
180 }
181
182 void AuthDatabaseLevelDB::listNames(std::vector<std::string> &res)
183 {
184         leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions());
185         res.clear();
186         for (it->SeekToFirst(); it->Valid(); it->Next()) {
187                 res.emplace_back(it->key().ToString());
188         }
189         delete it;
190 }
191
192 void AuthDatabaseLevelDB::reload()
193 {
194         // No-op for LevelDB.
195 }
196
197 #endif // USE_LEVELDB