1 #include "sqlstorage.h"
4 #include <sys/statvfs.h>
11 #include "logging/logging.h"
12 #include "sql_utils.h"
13 #include "utilities/utils.h"
19 if (!db.beginTransaction()) {
20 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
24 auto statement = db.prepareStatement<int, int,
int>(
25 "SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);", static_cast<int>(repo), role.ToInt(), -1);
27 int result = statement.step();
29 if (
result == SQLITE_DONE) {
30 LOG_TRACE <<
"meta with role " << role.ToString() <<
" in repo " << repo.toString() <<
" not present in db";
32 }
else if (
result != SQLITE_ROW) {
33 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
36 std::string meta = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
38 int version = Uptane::extractVersionUntrusted(meta);
40 LOG_ERROR <<
"Corrupted metadata";
45 statement = db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
46 static_cast<int>(repo), role.ToInt(), version);
48 if (statement.step() != SQLITE_DONE) {
49 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
53 statement = db.prepareStatement<int, int, int,
int>(
54 "UPDATE meta SET version = ? WHERE (repo=? AND meta_type=? AND version=?);", version, static_cast<int>(repo),
57 if (statement.step() != SQLITE_DONE) {
58 LOG_ERROR <<
"Can't update metadata: " << db.errmsg();
62 db.commitTransaction();
65 SQLStorage::SQLStorage(
const StorageConfig& config,
bool readonly)
66 :
SQLStorageBase(config.sqldb_path.get(config.path), readonly, libaktualizr_schema_migrations,
67 libaktualizr_schema_rollback_migrations, libaktualizr_current_schema,
68 libaktualizr_current_schema_version),
71 cleanMetaVersion(Uptane::RepositoryType::Director(), Uptane::Role::Root());
72 cleanMetaVersion(Uptane::RepositoryType::Image(), Uptane::Role::Root());
74 LOG_ERROR <<
"SQLite database metadata version migration failed";
78 void SQLStorage::storePrimaryKeys(
const std::string& public_key,
const std::string& private_key) {
81 auto statement = db.prepareStatement<std::string>(
82 "INSERT OR REPLACE INTO primary_keys(unique_mark,public,private) VALUES (0,?,?);", public_key, private_key);
83 if (statement.step() != SQLITE_DONE) {
84 LOG_ERROR <<
"Can't set primary keys: " << db.errmsg();
89 bool SQLStorage::loadPrimaryKeys(std::string* public_key, std::string* private_key) {
90 return loadPrimaryPublic(public_key) && loadPrimaryPrivate(private_key);
93 bool SQLStorage::loadPrimaryPublic(std::string* public_key) {
96 auto statement = db.prepareStatement(
"SELECT public FROM primary_keys LIMIT 1;");
98 int result = statement.step();
99 if (
result == SQLITE_DONE) {
100 LOG_TRACE <<
"No public key in db";
102 }
else if (
result != SQLITE_ROW) {
103 LOG_ERROR <<
"Can't get public key: " << db.errmsg();
107 auto pub = statement.get_result_col_str(0);
108 if (pub == boost::none) {
112 if (public_key !=
nullptr) {
113 *public_key = std::move(pub.value());
119 bool SQLStorage::loadPrimaryPrivate(std::string* private_key) {
122 auto statement = db.prepareStatement(
"SELECT private FROM primary_keys LIMIT 1;");
124 int result = statement.step();
125 if (
result == SQLITE_DONE) {
126 LOG_TRACE <<
"No private key in db";
128 }
else if (
result != SQLITE_ROW) {
129 LOG_ERROR <<
"Can't get private key: " << db.errmsg();
133 auto priv = statement.get_result_col_str(0);
134 if (priv == boost::none) {
138 if (private_key !=
nullptr) {
139 *private_key = std::move(priv.value());
145 void SQLStorage::clearPrimaryKeys() {
148 if (db.exec(
"DELETE FROM primary_keys;",
nullptr,
nullptr) != SQLITE_OK) {
149 LOG_ERROR <<
"Can't clear primary keys: " << db.errmsg();
154 void SQLStorage::saveSecondaryInfo(
const Uptane::EcuSerial& ecu_serial,
const std::string& sec_type,
158 std::stringstream key_type_ss;
159 key_type_ss << public_key.Type();
160 std::string key_type_str;
161 key_type_str = key_type_ss.str();
162 key_type_str.erase(std::remove(key_type_str.begin(), key_type_str.end(),
'"'), key_type_str.end());
164 if (!db.beginTransaction()) {
165 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
170 db.prepareStatement<std::string>(
"SELECT count(*) FROM secondary_ecus WHERE serial = ?;", ecu_serial.ToString());
171 if (statement.step() != SQLITE_ROW) {
172 LOG_ERROR <<
"Can't get count of secondary_ecus table: " << db.errmsg();
177 if (statement.get_result_col_int(0) != 0) {
178 req =
"UPDATE secondary_ecus SET sec_type = ?, public_key_type = ?, public_key = ? WHERE serial = ?;";
181 "INSERT INTO secondary_ecus (serial, sec_type, public_key_type, public_key) SELECT "
182 "serial,?,?,? FROM ecus WHERE (serial = ? AND is_primary = 0);";
185 statement = db.prepareStatement<std::string, std::string, std::string, std::string>(
186 req, sec_type, key_type_str, public_key.Value(), ecu_serial.ToString());
187 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
188 LOG_ERROR <<
"Can't save secondary key: " << db.errmsg();
192 db.commitTransaction();
198 if (!db.beginTransaction()) {
199 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
204 db.prepareStatement<std::string>(
"SELECT count(*) FROM secondary_ecus WHERE serial = ?;", ecu_serial.ToString());
205 if (statement.step() != SQLITE_ROW) {
206 LOG_ERROR <<
"Can't get count of secondary_ecus table: " << db.errmsg();
211 if (statement.get_result_col_int(0) != 0) {
212 req =
"UPDATE secondary_ecus SET extra = ? WHERE serial = ?;";
214 req =
"INSERT INTO secondary_ecus (extra, serial) VALUES (?,?);";
217 statement = db.prepareStatement<std::string, std::string>(req,
data, ecu_serial.ToString());
218 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
219 LOG_ERROR <<
"Can't save secondary data: " << db.errmsg();
223 db.commitTransaction();
231 auto statement = db.prepareStatement<std::string>(
232 "SELECT serial, hardware_id, sec_type, public_key_type, public_key, extra FROM ecus LEFT JOIN secondary_ecus "
234 "(serial) WHERE (serial = ? AND is_primary = 0);",
235 ecu_serial.ToString());
236 int statement_state = statement.step();
237 if (statement_state == SQLITE_DONE) {
238 LOG_TRACE <<
"Secondary ecu " << ecu_serial <<
" not found";
240 }
else if (statement_state != SQLITE_ROW) {
241 LOG_ERROR <<
"Cannot load secondary info: " << db.errmsg();
248 std::string sec_type = statement.get_result_col_str(2).value_or(
"");
249 std::string kt_str = statement.get_result_col_str(3).value_or(
"");
253 std::stringstream(kt_str) >> key_type;
254 key =
PublicKey(statement.get_result_col_str(4).value_or(
""), key_type);
256 std::string extra = statement.get_result_col_str(5).value_or(
"");
257 new_sec =
SecondaryInfo{serial, hw_id, sec_type, key, extra};
258 }
catch (
const boost::bad_optional_access&) {
262 if (secondary !=
nullptr) {
263 *secondary = std::move(new_sec);
269 bool SQLStorage::loadSecondariesInfo(std::vector<SecondaryInfo>* secondaries) {
272 std::vector<SecondaryInfo> new_secs;
277 auto statement = db.prepareStatement(
278 "SELECT serial, hardware_id, sec_type, public_key_type, public_key, extra FROM ecus LEFT JOIN secondary_ecus "
280 "(serial) WHERE is_primary = 0 ORDER BY ecus.id;");
281 while ((statement_state = statement.step()) == SQLITE_ROW) {
285 std::string sec_type = statement.get_result_col_str(2).value_or(
"");
286 std::string kt_str = statement.get_result_col_str(3).value_or(
"");
290 std::stringstream(kt_str) >> key_type;
291 key =
PublicKey(statement.get_result_col_str(4).value_or(
""), key_type);
293 std::string extra = statement.get_result_col_str(5).value_or(
"");
294 new_secs.emplace_back(
SecondaryInfo{serial, hw_id, sec_type, key, extra});
296 }
catch (
const boost::bad_optional_access&) {
300 if (statement_state != SQLITE_DONE) {
301 LOG_ERROR <<
"Can't load secondary info" << db.errmsg();
304 if (secondaries !=
nullptr) {
305 *secondaries = std::move(new_secs);
311 void SQLStorage::storeTlsCreds(
const std::string& ca,
const std::string& cert,
const std::string& pkey) {
317 void SQLStorage::storeTlsCa(
const std::string& ca) {
320 if (!db.beginTransaction()) {
321 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
325 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
326 if (statement.step() != SQLITE_ROW) {
327 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
332 if (statement.get_result_col_int(0) != 0) {
333 req =
"UPDATE OR REPLACE tls_creds SET ca_cert = ?;";
335 req =
"INSERT INTO tls_creds(ca_cert) VALUES (?);";
339 if (statement.step() != SQLITE_DONE) {
340 LOG_ERROR <<
"Can't set ca_cert: " << db.errmsg();
344 db.commitTransaction();
347 void SQLStorage::storeTlsCert(
const std::string& cert) {
350 if (!db.beginTransaction()) {
351 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
355 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
356 if (statement.step() != SQLITE_ROW) {
357 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
362 if (statement.get_result_col_int(0) != 0) {
363 req =
"UPDATE OR REPLACE tls_creds SET client_cert = ?;";
365 req =
"INSERT INTO tls_creds(client_cert) VALUES (?);";
369 if (statement.step() != SQLITE_DONE) {
370 LOG_ERROR <<
"Can't set client_cert: " << db.errmsg();
374 db.commitTransaction();
377 void SQLStorage::storeTlsPkey(
const std::string& pkey) {
380 if (!db.beginTransaction()) {
381 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
384 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
385 if (statement.step() != SQLITE_ROW) {
386 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
391 if (statement.get_result_col_int(0) != 0) {
392 req =
"UPDATE OR REPLACE tls_creds SET client_pkey = ?;";
394 req =
"INSERT INTO tls_creds(client_pkey) VALUES (?);";
398 if (statement.step() != SQLITE_DONE) {
399 LOG_ERROR <<
"Can't set client_pkey: " << db.errmsg();
403 db.commitTransaction();
406 bool SQLStorage::loadTlsCreds(std::string* ca, std::string* cert, std::string* pkey) {
409 if (!db.beginTransaction()) {
410 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
413 auto statement = db.prepareStatement(
"SELECT ca_cert, client_cert, client_pkey FROM tls_creds LIMIT 1;");
415 int result = statement.step();
416 if (
result == SQLITE_DONE) {
417 LOG_TRACE <<
"Tls creds not present";
419 }
else if (
result != SQLITE_ROW) {
420 LOG_ERROR <<
"Can't get tls_creds: " << db.errmsg();
424 std::string ca_v, cert_v, pkey_v;
426 ca_v = statement.get_result_col_str(0).value();
427 cert_v = statement.get_result_col_str(1).value();
428 pkey_v = statement.get_result_col_str(2).value();
429 }
catch (
const boost::bad_optional_access&) {
434 *ca = std::move(ca_v);
436 if (cert !=
nullptr) {
437 *cert = std::move(cert_v);
439 if (pkey !=
nullptr) {
440 *pkey = std::move(pkey_v);
443 db.commitTransaction();
448 void SQLStorage::clearTlsCreds() {
451 if (db.exec(
"DELETE FROM tls_creds;",
nullptr,
nullptr) != SQLITE_OK) {
452 LOG_ERROR <<
"Can't clear tls_creds: " << db.errmsg();
457 bool SQLStorage::loadTlsCa(std::string* ca) {
460 auto statement = db.prepareStatement(
"SELECT ca_cert FROM tls_creds LIMIT 1;");
462 int result = statement.step();
463 if (
result == SQLITE_DONE) {
464 LOG_TRACE <<
"ca_cert not present";
466 }
else if (
result != SQLITE_ROW) {
467 LOG_ERROR <<
"Can't get ca_cert: " << db.errmsg();
471 auto ca_r = statement.get_result_col_str(0);
472 if (ca_r == boost::none) {
477 *ca = std::move(ca_r.value());
483 bool SQLStorage::loadTlsCert(std::string* cert) {
486 auto statement = db.prepareStatement(
"SELECT client_cert FROM tls_creds LIMIT 1;");
488 int result = statement.step();
489 if (
result == SQLITE_DONE) {
490 LOG_TRACE <<
"client_cert not present in db";
492 }
else if (
result != SQLITE_ROW) {
493 LOG_ERROR <<
"Can't get client_cert: " << db.errmsg();
497 auto cert_r = statement.get_result_col_str(0);
498 if (cert_r == boost::none) {
502 if (cert !=
nullptr) {
503 *cert = std::move(cert_r.value());
509 bool SQLStorage::loadTlsPkey(std::string* pkey) {
512 auto statement = db.prepareStatement(
"SELECT client_pkey FROM tls_creds LIMIT 1;");
514 int result = statement.step();
515 if (
result == SQLITE_DONE) {
516 LOG_TRACE <<
"client_pkey not present in db";
518 }
else if (
result != SQLITE_ROW) {
519 LOG_ERROR <<
"Can't get client_pkey: " << db.errmsg();
523 auto pkey_r = statement.get_result_col_str(0);
524 if (pkey_r == boost::none) {
528 if (pkey !=
nullptr) {
529 *pkey = std::move(pkey_r.value());
538 if (!db.beginTransaction()) {
539 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
544 db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
545 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
547 if (del_statement.step() != SQLITE_DONE) {
548 LOG_ERROR <<
"Can't clear Root metadata: " << db.errmsg();
552 auto ins_statement = db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
554 Uptane::Role::Root().ToInt(), version.version());
556 if (ins_statement.step() != SQLITE_DONE) {
557 LOG_ERROR <<
"Can't add metadata: " << db.errmsg();
561 db.commitTransaction();
567 if (!db.beginTransaction()) {
568 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
572 auto del_statement = db.prepareStatement<int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=?);",
573 static_cast<int>(repo), role.ToInt());
575 if (del_statement.step() != SQLITE_DONE) {
576 LOG_ERROR <<
"Can't clear " << role.ToString() <<
" metadata: " << db.errmsg();
581 db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
SQLBlob(
data),
584 if (ins_statement.step() != SQLITE_DONE) {
585 LOG_ERROR <<
"Can't add " << role.ToString() <<
"metadata: " << db.errmsg();
589 db.commitTransaction();
596 if (version.version() < 0) {
597 auto statement = db.prepareStatement<int,
int>(
598 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;", static_cast<int>(repo),
599 Uptane::Role::Root().ToInt());
600 int result = statement.step();
602 if (
result == SQLITE_DONE) {
603 LOG_TRACE <<
"Root metadata not present";
605 }
else if (
result != SQLITE_ROW) {
606 LOG_ERROR <<
"Can't get Root metadata: " << db.errmsg();
609 if (
data !=
nullptr) {
610 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
614 db.prepareStatement<int, int,
int>(
"SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
615 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
617 int result = statement.step();
619 if (
result == SQLITE_DONE) {
620 LOG_TRACE <<
"Root metadata not present";
622 }
else if (
result != SQLITE_ROW) {
623 LOG_ERROR <<
"Can't get Root metadata: " << db.errmsg();
627 const auto blob = reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0));
628 if (blob ==
nullptr) {
629 LOG_ERROR <<
"Can't get Root metadata: " << db.errmsg();
633 if (
data !=
nullptr) {
634 *
data = std::string(blob);
644 auto statement = db.prepareStatement<int,
int>(
645 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;", static_cast<int>(repo),
647 int result = statement.step();
649 if (
result == SQLITE_DONE) {
650 LOG_TRACE << role.ToString() <<
" metadata not present";
652 }
else if (
result != SQLITE_ROW) {
653 LOG_ERROR <<
"Can't get " << role.ToString() <<
" metadata: " << db.errmsg();
656 if (
data !=
nullptr) {
657 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
667 db.prepareStatement<
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type != 0);", static_cast<int>(repo));
669 if (del_statement.step() != SQLITE_DONE) {
670 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
674 void SQLStorage::clearMetadata() {
677 if (db.exec(
"DELETE FROM meta;",
nullptr,
nullptr) != SQLITE_OK) {
678 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
683 void SQLStorage::storeDelegation(
const std::string&
data,
const Uptane::Role role) {
686 if (!db.beginTransaction()) {
687 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
691 auto statement = db.prepareStatement<
SQLBlob, std::string>(
"INSERT OR REPLACE INTO delegations VALUES (?, ?);",
694 if (statement.step() != SQLITE_DONE) {
695 LOG_ERROR <<
"Can't add delegation metadata: " << db.errmsg();
699 db.commitTransaction();
702 bool SQLStorage::loadDelegation(std::string*
data,
const Uptane::Role role) {
706 db.prepareStatement<std::string>(
"SELECT meta FROM delegations WHERE role_name=? LIMIT 1;", role.ToString());
707 int result = statement.step();
709 if (
result == SQLITE_DONE) {
710 LOG_TRACE <<
"Delegations metadata not present";
712 }
else if (
result != SQLITE_ROW) {
713 LOG_ERROR <<
"Can't get delegations metadata: " << db.errmsg();
716 if (
data !=
nullptr) {
717 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
723 bool SQLStorage::loadAllDelegations(std::vector<std::pair<Uptane::Role, std::string>>&
data)
const {
729 auto statement = db.prepareStatement(
"SELECT meta, role_name FROM delegations;");
730 auto statement_state = statement.step();
732 if (statement_state == SQLITE_DONE) {
733 LOG_TRACE <<
"Delegations metadata are not present";
735 }
else if (statement_state != SQLITE_ROW) {
736 LOG_ERROR <<
"Can't get delegations metadata: " << db.errmsg();
741 data.emplace_back(Uptane::Role::Delegation(statement.get_result_col_str(1).value()),
742 statement.get_result_col_blob(0).value());
743 }
while ((statement_state = statement.step()) == SQLITE_ROW);
746 }
catch (
const std::exception& exc) {
747 LOG_ERROR <<
"Failed to fetch records from `delegations` table: " << exc.what();
753 void SQLStorage::deleteDelegation(
const Uptane::Role role) {
756 auto statement = db.prepareStatement<std::string>(
"DELETE FROM delegations WHERE role_name=?;", role.ToString());
760 void SQLStorage::clearDelegations() {
763 if (db.exec(
"DELETE FROM delegations;",
nullptr,
nullptr) != SQLITE_OK) {
764 LOG_ERROR <<
"Can't clear delegations metadata: " << db.errmsg();
768 void SQLStorage::storeDeviceId(
const std::string& device_id) {
771 auto statement = db.prepareStatement<std::string>(
772 "INSERT OR REPLACE INTO device_info(unique_mark,device_id,is_registered) VALUES(0,?,0);", device_id);
773 if (statement.step() != SQLITE_DONE) {
774 LOG_ERROR <<
"Can't set device ID: " << db.errmsg();
779 bool SQLStorage::loadDeviceId(std::string* device_id) {
782 auto statement = db.prepareStatement(
"SELECT device_id FROM device_info LIMIT 1;");
784 int result = statement.step();
785 if (
result == SQLITE_DONE) {
786 LOG_TRACE <<
"device_id not present in db";
788 }
else if (
result != SQLITE_ROW) {
789 LOG_ERROR <<
"Can't get device ID: " << db.errmsg();
793 auto did = statement.get_result_col_str(0);
794 if (did == boost::none) {
795 LOG_ERROR <<
"Empty device ID" << db.errmsg();
799 if (device_id !=
nullptr) {
800 *device_id = std::move(did.value());
806 void SQLStorage::clearDeviceId() {
809 if (db.exec(
"DELETE FROM device_info;",
nullptr,
nullptr) != SQLITE_OK) {
810 LOG_ERROR <<
"Can't clear device ID: " << db.errmsg();
815 void SQLStorage::storeEcuRegistered() {
818 if (!db.beginTransaction()) {
819 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
823 auto statement = db.prepareStatement(
"SELECT count(*) FROM device_info;");
824 if (statement.step() != SQLITE_ROW) {
825 throw std::runtime_error(
"Could not get device_info count");
827 if (statement.get_result_col_int(0) != 1) {
828 throw std::runtime_error(
"Cannot set ecu registered if no device_info set");
831 std::string req =
"UPDATE device_info SET is_registered = 1";
832 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
833 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
837 db.commitTransaction();
840 bool SQLStorage::loadEcuRegistered() {
843 auto statement = db.prepareStatement(
"SELECT is_registered FROM device_info LIMIT 1;");
845 int result = statement.step();
846 if (
result == SQLITE_DONE) {
848 }
else if (
result != SQLITE_ROW) {
849 LOG_ERROR <<
"Can't get is_registered in device_info " << db.errmsg();
853 return statement.get_result_col_int(0) != 0;
856 void SQLStorage::clearEcuRegistered() {
860 std::string req =
"UPDATE device_info SET is_registered = 0";
861 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
862 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
867 void SQLStorage::storeNeedReboot() {
870 auto statement = db.prepareStatement<
int>(
"INSERT OR REPLACE INTO need_reboot(unique_mark,flag) VALUES(0,?);", 1);
871 if (statement.step() != SQLITE_DONE) {
872 LOG_ERROR <<
"Can't set need_reboot: " << db.errmsg();
877 bool SQLStorage::loadNeedReboot(
bool* need_reboot) {
880 auto statement = db.prepareStatement(
"SELECT flag FROM need_reboot LIMIT 1;");
882 int result = statement.step();
883 if (
result == SQLITE_DONE) {
884 if (need_reboot !=
nullptr) {
885 *need_reboot =
false;
888 }
else if (
result != SQLITE_ROW) {
889 LOG_ERROR <<
"Can't get need_reboot: " << db.errmsg();
893 auto flag = static_cast<bool>(statement.get_result_col_int(0));
894 if (need_reboot !=
nullptr) {
901 void SQLStorage::clearNeedReboot() {
904 if (db.exec(
"DELETE FROM need_reboot;",
nullptr,
nullptr) != SQLITE_OK) {
905 LOG_ERROR <<
"Can't clear need_reboot: " << db.errmsg();
910 void SQLStorage::storeEcuSerials(
const EcuSerials& serials) {
911 if (serials.size() >= 1) {
914 if (!db.beginTransaction()) {
915 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
919 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
920 LOG_ERROR <<
"Can't clear ecus: " << db.errmsg();
925 std::string serial = serials[0].first.ToString();
926 std::string hwid = serials[0].second.ToString();
928 auto statement = db.prepareStatement<std::string, std::string>(
929 "INSERT INTO ecus(id, serial,hardware_id,is_primary) VALUES (0, ?,?,1);", serial, hwid);
930 if (statement.step() != SQLITE_DONE) {
931 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
936 auto statement_ivupdate = db.prepareStatement<std::string>(
937 "UPDATE installed_versions SET ecu_serial = ? WHERE ecu_serial = '';", serial);
939 if (statement_ivupdate.step() != SQLITE_DONE) {
940 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
945 for (
auto it = serials.cbegin() + 1; it != serials.cend(); it++) {
946 auto statement = db.prepareStatement<int64_t, std::string, std::string>(
947 "INSERT INTO ecus(id,serial,hardware_id) VALUES (?,?,?);", it - serials.cbegin(), it->first.ToString(),
948 it->second.ToString());
950 if (statement.step() != SQLITE_DONE) {
951 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
956 db.commitTransaction();
960 bool SQLStorage::loadEcuSerials(EcuSerials* serials) {
964 auto statement = db.prepareStatement(
"SELECT serial, hardware_id FROM ecus ORDER BY id;");
967 EcuSerials new_serials;
969 while ((statement_state = statement.step()) == SQLITE_ROW) {
971 new_serials.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
974 }
catch (
const boost::bad_optional_access&) {
979 if (statement_state != SQLITE_DONE) {
980 LOG_ERROR <<
"Can't get ecu serials: " << db.errmsg();
984 if (serials !=
nullptr) {
985 *serials = std::move(new_serials);
991 void SQLStorage::clearEcuSerials() {
994 if (!db.beginTransaction()) {
995 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
999 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1000 LOG_ERROR <<
"Can't clear ecus: " << db.errmsg();
1004 if (db.exec(
"DELETE FROM secondary_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1005 LOG_ERROR <<
"Can't clear secondary ecus: " << db.errmsg();
1009 db.commitTransaction();
1012 void SQLStorage::storeCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial,
const std::string& manifest) {
1015 auto statement = db.prepareStatement<std::string, std::string>(
1016 "UPDATE secondary_ecus SET manifest = ? WHERE (serial = ?);", manifest, ecu_serial.ToString());
1017 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
1018 LOG_ERROR <<
"Can't save secondary manifest " << db.errmsg();
1023 bool SQLStorage::loadCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial, std::string* manifest) {
1026 std::string stmanifest;
1030 auto statement = db.prepareStatement<std::string>(
"SELECT manifest FROM secondary_ecus WHERE (serial = ?);",
1031 ecu_serial.ToString());
1033 if (statement.step() != SQLITE_ROW) {
1034 LOG_WARNING <<
"Could not find manifest for ecu " << ecu_serial;
1037 stmanifest = statement.get_result_col_str(0).value_or(
"");
1039 empty = stmanifest ==
"";
1042 if (manifest !=
nullptr) {
1043 *manifest = std::move(stmanifest);
1049 void SQLStorage::storeMisconfiguredEcus(
const std::vector<MisconfiguredEcu>& ecus) {
1050 if (ecus.size() >= 1) {
1053 if (!db.beginTransaction()) {
1054 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
1058 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1059 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
1063 std::vector<MisconfiguredEcu>::const_iterator it;
1064 for (it = ecus.begin(); it != ecus.end(); it++) {
1065 auto statement = db.prepareStatement<std::string, std::string,
int>(
1066 "INSERT INTO misconfigured_ecus VALUES (?,?,?);", it->serial.ToString(), it->hardware_id.ToString(),
1067 static_cast<int>(it->state));
1069 if (statement.step() != SQLITE_DONE) {
1070 LOG_ERROR <<
"Can't set misconfigured_ecus: " << db.errmsg();
1075 db.commitTransaction();
1079 bool SQLStorage::loadMisconfiguredEcus(std::vector<MisconfiguredEcu>* ecus) {
1082 auto statement = db.prepareStatement(
"SELECT serial, hardware_id, state FROM misconfigured_ecus;");
1083 int statement_state;
1085 std::vector<MisconfiguredEcu> new_ecus;
1087 while ((statement_state = statement.step()) == SQLITE_ROW) {
1089 new_ecus.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
1091 static_cast<EcuState>(statement.get_result_col_int(2)));
1093 }
catch (
const boost::bad_optional_access&) {
1098 if (statement_state != SQLITE_DONE) {
1099 LOG_ERROR <<
"Can't get misconfigured_ecus: " << db.errmsg();
1103 if (ecus !=
nullptr) {
1104 *ecus = std::move(new_ecus);
1110 void SQLStorage::clearMisconfiguredEcus() {
1113 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1114 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
1119 void SQLStorage::saveInstalledVersion(
const std::string& ecu_serial,
const Uptane::Target& target,
1120 InstalledVersionUpdateMode update_mode) {
1123 if (!db.beginTransaction()) {
1124 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
1131 std::string ecu_serial_real = ecu_serial;
1132 if (ecu_serial_real.empty()) {
1133 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1134 if (statement.step() == SQLITE_ROW) {
1135 ecu_serial_real = statement.get_result_col_str(0).value();
1137 LOG_WARNING <<
"Could not find primary ecu serial, set to lazy init mode";
1141 std::string hashes_encoded = Uptane::Hash::encodeVector(target.hashes());
1144 boost::optional<int64_t> old_id;
1145 bool old_was_installed =
false;
1147 auto statement = db.prepareStatement<std::string>(
1148 "SELECT id, sha256, name, was_installed FROM installed_versions WHERE ecu_serial = ? ORDER BY id DESC "
1152 if (statement.step() == SQLITE_ROW) {
1153 int64_t rid = statement.get_result_col_int(0);
1154 std::string rsha256 = statement.get_result_col_str(1).value_or(
"");
1155 std::string rname = statement.get_result_col_str(2).value_or(
"");
1156 bool rwasi = statement.get_result_col_int(3) == 1;
1158 if (rsha256 == target.sha256Hash() && rname == target.filename()) {
1160 old_was_installed = rwasi;
1165 if (update_mode == InstalledVersionUpdateMode::kCurrent) {
1167 auto statement = db.prepareStatement<std::string>(
1168 "UPDATE installed_versions SET is_current = 0, is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1169 if (statement.step() != SQLITE_DONE) {
1170 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1173 }
else if (update_mode == InstalledVersionUpdateMode::kPending) {
1175 auto statement = db.prepareStatement<std::string>(
1176 "UPDATE installed_versions SET is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1177 if (statement.step() != SQLITE_DONE) {
1178 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1184 auto statement = db.prepareStatement<std::string, int, int, int64_t>(
1185 "UPDATE installed_versions SET correlation_id = ?, is_current = ?, is_pending = ?, was_installed = ? WHERE id "
1187 target.correlation_id(), static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1188 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1189 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent || old_was_installed), old_id.value());
1191 if (statement.step() != SQLITE_DONE) {
1192 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1196 std::string custom = Utils::jsonToCanonicalStr(target.custom_data());
1197 auto statement = db.prepareStatement<std::string, std::string, std::string, std::string, int64_t, std::string,
1198 std::string, int,
int>(
1199 "INSERT INTO installed_versions(ecu_serial, sha256, name, hashes, length, custom_meta, correlation_id, "
1200 "is_current, is_pending, was_installed) VALUES (?,?,?,?,?,?,?,?,?,?);",
1201 ecu_serial_real, target.sha256Hash(), target.filename(), hashes_encoded, static_cast<int64_t>(target.length()),
1202 custom, target.correlation_id(), static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1203 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1204 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent));
1206 if (statement.step() != SQLITE_DONE) {
1207 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1212 db.commitTransaction();
1215 static void loadEcuMap(
SQLite3Guard& db, std::string& ecu_serial, Uptane::EcuMap& ecu_map) {
1218 if (ecu_serial.empty()) {
1219 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1220 if (statement.step() == SQLITE_ROW) {
1221 ecu_serial = statement.get_result_col_str(0).value();
1222 }
else if (statement.step() == SQLITE_DONE) {
1223 LOG_DEBUG <<
"No serial found in database for this ECU, defaulting to empty serial";
1225 LOG_ERROR <<
"Error getting serial for this ECU, defaulting to empty serial: " << db.errmsg();
1229 if (!ecu_serial.empty()) {
1230 auto statement = db.prepareStatement<std::string>(
"SELECT hardware_id FROM ecus WHERE serial = ?;", ecu_serial);
1231 if (statement.step() == SQLITE_ROW) {
1234 }
else if (statement.step() == SQLITE_DONE) {
1235 LOG_DEBUG <<
"No hardware ID found in database for ECU serial " << ecu_serial;
1237 LOG_ERROR <<
"Error getting hardware ID for ECU serial " << ecu_serial <<
": " << db.errmsg();
1242 bool SQLStorage::loadInstallationLog(
const std::string& ecu_serial, std::vector<Uptane::Target>* log,
1243 bool only_installed) {
1246 std::string ecu_serial_real = ecu_serial;
1247 Uptane::EcuMap ecu_map;
1248 loadEcuMap(db, ecu_serial_real, ecu_map);
1251 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1252 "ecu_serial = ? ORDER BY id;";
1253 if (only_installed) {
1255 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1256 "ecu_serial = ? AND was_installed = 1 ORDER BY id;";
1259 auto statement = db.prepareStatement<std::string>(query, ecu_serial_real);
1260 int statement_state;
1262 std::vector<Uptane::Target> new_log;
1263 std::map<int64_t, size_t> ids_map;
1265 while ((statement_state = statement.step()) == SQLITE_ROW) {
1267 auto id = statement.get_result_col_int(0);
1268 auto sha256 = statement.get_result_col_str(1).value();
1269 auto filename = statement.get_result_col_str(2).value();
1270 auto hashes_str = statement.get_result_col_str(3).value();
1271 auto length = statement.get_result_col_int(4);
1272 auto correlation_id = statement.get_result_col_str(5).value();
1273 auto custom_str = statement.get_result_col_str(6).value();
1277 std::vector<Uptane::Hash> hashes = Uptane::Hash::decodeVector(hashes_str);
1279 auto find_sha256 = std::find_if(hashes.cbegin(), hashes.cend(),
1280 [](
const Uptane::Hash& h) {
return h.type() == Uptane::Hash::Type::kSha256; });
1281 if (find_sha256 == hashes.cend()) {
1282 LOG_WARNING <<
"No sha256 in hashes list";
1283 hashes.emplace_back(Uptane::Hash::Type::kSha256, sha256);
1286 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1287 if (!custom_str.empty()) {
1288 std::istringstream css(custom_str);
1291 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom,
nullptr)) {
1292 t.updateCustom(custom);
1294 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1297 new_log.emplace_back(t);
1301 }
catch (
const boost::bad_optional_access&) {
1302 LOG_ERROR <<
"Incompleted installed version, keeping old one";
1307 if (statement_state != SQLITE_DONE) {
1308 LOG_ERROR <<
"Can't get installed_versions: " << db.errmsg();
1312 if (log ==
nullptr) {
1316 *log = std::move(new_log);
1321 bool SQLStorage::loadInstalledVersions(
const std::string& ecu_serial, boost::optional<Uptane::Target>* current_version,
1322 boost::optional<Uptane::Target>* pending_version) {
1325 std::string ecu_serial_real = ecu_serial;
1326 Uptane::EcuMap ecu_map;
1327 loadEcuMap(db, ecu_serial_real, ecu_map);
1330 auto sha256 = statement.get_result_col_str(0).value();
1331 auto filename = statement.get_result_col_str(1).value();
1332 auto hashes_str = statement.get_result_col_str(2).value();
1333 auto length = statement.get_result_col_int(3);
1334 auto correlation_id = statement.get_result_col_str(4).value();
1335 auto custom_str = statement.get_result_col_str(5).value();
1339 std::vector<Uptane::Hash> hashes = Uptane::Hash::decodeVector(hashes_str);
1341 auto find_sha256 = std::find_if(hashes.cbegin(), hashes.cend(),
1342 [](
const Uptane::Hash& h) {
return h.type() == Uptane::Hash::Type::kSha256; });
1343 if (find_sha256 == hashes.cend()) {
1344 LOG_WARNING <<
"No sha256 in hashes list";
1345 hashes.emplace_back(Uptane::Hash::Type::kSha256, sha256);
1347 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1348 if (!custom_str.empty()) {
1349 std::istringstream css(custom_str);
1352 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom, &errs)) {
1353 t.updateCustom(custom);
1355 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1362 if (current_version !=
nullptr) {
1363 auto statement = db.prepareStatement<std::string>(
1364 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1365 "ecu_serial = ? AND is_current = 1 LIMIT 1;",
1368 if (statement.step() == SQLITE_ROW) {
1370 *current_version = read_target(statement);
1371 }
catch (
const boost::bad_optional_access&) {
1372 LOG_ERROR <<
"Could not read current installed version";
1376 LOG_TRACE <<
"Cannot get current installed version: " << db.errmsg();
1377 *current_version = boost::none;
1381 if (pending_version !=
nullptr) {
1382 auto statement = db.prepareStatement<std::string>(
1383 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1384 "ecu_serial = ? AND is_pending = 1 LIMIT 1;",
1387 if (statement.step() == SQLITE_ROW) {
1389 *pending_version = read_target(statement);
1390 }
catch (
const boost::bad_optional_access&) {
1391 LOG_ERROR <<
"Could not read pending installed version";
1395 LOG_TRACE <<
"Cannot get pending installed version: " << db.errmsg();
1396 *pending_version = boost::none;
1403 bool SQLStorage::hasPendingInstall() {
1406 auto statement = db.prepareStatement(
"SELECT count(*) FROM installed_versions where is_pending = 1");
1407 if (statement.step() != SQLITE_ROW) {
1408 LOG_ERROR <<
"Can't get tables count: " << db.errmsg();
1409 throw std::runtime_error(
"Could not count pending installations");
1412 return statement.get_result_col_int(0) > 0;
1415 void SQLStorage::getPendingEcus(std::vector<std::pair<Uptane::EcuSerial, Uptane::Hash>>* pendingEcus) {
1418 auto statement = db.prepareStatement(
"SELECT ecu_serial, sha256 FROM installed_versions where is_pending = 1");
1419 int statement_result = statement.step();
1420 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1421 throw std::runtime_error(
"Failed to get ECUs with a pending target installation: " + db.errmsg());
1424 std::vector<std::pair<Uptane::EcuSerial, Uptane::Hash>> ecu_res;
1426 if (statement_result == SQLITE_DONE) {
1431 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1432 std::string ecu_serial = statement.get_result_col_str(0).value();
1433 std::string hash = statement.get_result_col_str(1).value();
1434 ecu_res.emplace_back(
1438 if (pendingEcus !=
nullptr) {
1439 *pendingEcus = std::move(ecu_res);
1443 void SQLStorage::clearInstalledVersions() {
1446 if (db.exec(
"DELETE FROM installed_versions;",
nullptr,
nullptr) != SQLITE_OK) {
1447 LOG_ERROR <<
"Can't clear installed_versions: " << db.errmsg();
1456 auto statement = db.prepareStatement<std::string, int, std::string, std::string>(
1457 "INSERT OR REPLACE INTO ecu_installation_results (ecu_serial, success, result_code, description) VALUES "
1459 ecu_serial.ToString(), static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description);
1460 if (statement.step() != SQLITE_DONE) {
1461 LOG_ERROR <<
"Can't set ecu installation result: " << db.errmsg();
1466 bool SQLStorage::loadEcuInstallationResults(
1467 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>>* results) {
1470 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_res;
1473 auto statement = db.prepareStatement(
1474 "SELECT ecu_serial, success, result_code, description FROM ecu_installation_results INNER JOIN ecus ON "
1475 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1476 int statement_result = statement.step();
1477 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1478 LOG_ERROR <<
"Can't get ecu_installation_results: " << db.errmsg();
1482 if (statement_result == SQLITE_DONE) {
1487 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1489 std::string ecu_serial = statement.get_result_col_str(0).value();
1490 auto success = static_cast<bool>(statement.get_result_col_int(1));
1491 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(2).value());
1492 std::string description = statement.get_result_col_str(3).value();
1495 }
catch (
const boost::bad_optional_access&) {
1500 if (results !=
nullptr) {
1501 *results = std::move(ecu_res);
1508 const std::string& correlation_id) {
1511 auto statement = db.prepareStatement<int, std::string, std::string, std::string, std::string>(
1512 "INSERT OR REPLACE INTO device_installation_result (unique_mark, success, result_code, description, raw_report, "
1514 "VALUES (0,?,?,?,?,?);",
1515 static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description, raw_report, correlation_id);
1516 if (statement.step() != SQLITE_DONE) {
1517 LOG_ERROR <<
"Can't set device installation result: " << db.errmsg();
1523 std::string* correlation_id) {
1527 std::string raw_report_res;
1528 std::string corrid_res;
1530 auto statement = db.prepareStatement(
1531 "SELECT success, result_code, description, raw_report, correlation_id FROM device_installation_result;");
1532 int statement_result = statement.step();
1533 if (statement_result == SQLITE_DONE) {
1534 LOG_TRACE <<
"No device installation result in db";
1536 }
else if (statement_result != SQLITE_ROW) {
1537 LOG_ERROR <<
"Can't get device_installation_result: " << db.errmsg();
1542 auto success = static_cast<bool>(statement.get_result_col_int(0));
1543 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(1).value());
1544 std::string description = statement.get_result_col_str(2).value();
1545 raw_report_res = statement.get_result_col_str(3).value();
1546 corrid_res = statement.get_result_col_str(4).value();
1549 }
catch (
const boost::bad_optional_access&) {
1554 *
result = std::move(dev_res);
1557 if (raw_report !=
nullptr) {
1558 *raw_report = std::move(raw_report_res);
1561 if (correlation_id !=
nullptr) {
1562 *correlation_id = std::move(corrid_res);
1568 void SQLStorage::saveEcuReportCounter(
const Uptane::EcuSerial& ecu_serial,
const int64_t counter) {
1571 auto statement = db.prepareStatement<std::string, int64_t>(
1572 "INSERT OR REPLACE INTO ecu_report_counter (ecu_serial, counter) VALUES "
1574 ecu_serial.ToString(), counter);
1575 if (statement.step() != SQLITE_DONE) {
1576 LOG_ERROR <<
"Can't set ecu counter: " << db.errmsg();
1581 bool SQLStorage::loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results) {
1584 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
1587 auto statement = db.prepareStatement(
1588 "SELECT ecu_serial, counter FROM ecu_report_counter INNER JOIN ecus ON "
1589 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1590 int statement_result = statement.step();
1591 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1592 LOG_ERROR <<
"Can't get ecu_report_counter: " << db.errmsg();
1596 if (statement_result == SQLITE_DONE) {
1601 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1603 std::string ecu_serial = statement.get_result_col_str(0).value();
1604 int64_t counter = statement.get_result_col_int(1);
1607 }
catch (
const boost::bad_optional_access&) {
1612 if (results !=
nullptr) {
1613 *results = std::move(ecu_cnt);
1619 void SQLStorage::saveReportEvent(
const Json::Value& json_value) {
1620 std::string json_string = Utils::jsonToCanonicalStr(json_value);
1622 auto statement = db.prepareStatement<std::string>(
1623 "INSERT INTO report_events SELECT MAX(id) + 1, ? FROM report_events", json_string);
1624 if (statement.step() != SQLITE_DONE) {
1625 LOG_ERROR <<
"Can't save report event: " << db.errmsg();
1630 bool SQLStorage::loadReportEvents(Json::Value* report_array, int64_t* id_max) {
1632 auto statement = db.prepareStatement(
"SELECT id, json_string FROM report_events;");
1633 int statement_result = statement.step();
1634 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1635 LOG_ERROR <<
"Can't get report_events: " << db.errmsg();
1638 if (statement_result == SQLITE_DONE) {
1643 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1645 int64_t
id = statement.get_result_col_int(0);
1646 std::string json_string = statement.get_result_col_str(1).value();
1647 std::istringstream jss(json_string);
1648 Json::Value event_json;
1650 if (Json::parseFromStream(Json::CharReaderBuilder(), jss, &event_json, &errs)) {
1651 report_array->append(event_json);
1652 *id_max = (*id_max) >
id ? (*id_max) : id;
1654 LOG_ERROR <<
"Unable to parse event data: " << errs;
1656 }
catch (
const boost::bad_optional_access&) {
1664 void SQLStorage::deleteReportEvents(int64_t id_max) {
1666 if (!db.beginTransaction()) {
1667 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
1671 auto statement = db.prepareStatement<int64_t>(
"DELETE FROM report_events WHERE id <= ?;", id_max);
1672 if (statement.step() != SQLITE_DONE) {
1673 LOG_ERROR <<
"Can't delete report_events";
1676 db.commitTransaction();
1679 void SQLStorage::clearInstallationResults() {
1681 if (!db.beginTransaction()) {
1682 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
1686 if (db.exec(
"DELETE FROM device_installation_result;",
nullptr,
nullptr) != SQLITE_OK) {
1687 LOG_ERROR <<
"Can't clear device_installation_result: " << db.errmsg();
1691 if (db.exec(
"DELETE FROM ecu_installation_results;",
nullptr,
nullptr) != SQLITE_OK) {
1692 LOG_ERROR <<
"Can't clear ecu_installation_results: " << db.errmsg();
1696 db.commitTransaction();
1699 bool SQLStorage::checkAvailableDiskSpace(
const uint64_t required_bytes)
const {
1700 struct statvfs stvfsbuf {};
1701 const int stat_res = statvfs(dbPath().c_str(), &stvfsbuf);
1703 LOG_WARNING <<
"Unable to read filesystem statistics: error code " << stat_res;
1706 const uint64_t available_bytes = (static_cast<uint64_t>(stvfsbuf.f_bsize) * stvfsbuf.f_bavail);
1707 const uint64_t reserved_bytes = 1 << 20;
1709 if (required_bytes + reserved_bytes < available_bytes) {
1712 LOG_ERROR <<
"Insufficient disk space available to download target! Required: " << required_bytes
1713 <<
", available: " << available_bytes <<
", reserved: " << reserved_bytes;
1718 boost::optional<std::pair<uintmax_t, std::string>> SQLStorage::checkTargetFile(
const Uptane::Target& target)
const {
1721 auto statement = db.prepareStatement<std::string>(
1722 "SELECT sha256, sha512, filename FROM target_images WHERE targetname = ?;", target.filename());
1724 int statement_state;
1725 while ((statement_state = statement.step()) == SQLITE_ROW) {
1726 auto sha256 = statement.get_result_col_str(0);
1727 auto sha512 = statement.get_result_col_str(1);
1728 auto filename = statement.get_result_col_str(2);
1729 if ((*sha256).empty() && (*sha512).empty()) {
1731 LOG_WARNING <<
"Image without checksum: " << target.filename();
1734 bool sha256_match =
false;
1735 bool sha512_match =
false;
1736 if (!(*sha256).empty()) {
1737 if (target.MatchHash(
Uptane::Hash(Uptane::Hash::Type::kSha256, *sha256))) {
1738 sha256_match =
true;
1742 if (!(*sha512).empty()) {
1743 if (target.MatchHash(
Uptane::Hash(Uptane::Hash::Type::kSha512, *sha512))) {
1744 sha512_match =
true;
1747 if (((*sha256).empty() || sha256_match) && ((*sha512).empty() || sha512_match)) {
1748 if (boost::filesystem::exists(images_path_ / *filename)) {
1749 return {{boost::filesystem::file_size(images_path_ / *filename), *filename}};
1756 if (statement_state == SQLITE_DONE) {
1759 assert(statement_state != SQLITE_ROW);
1760 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1768 : db_path_(storage.dbPath()), target_(std::move(target)), storage_(&storage) {
1771 std::string sha256Hash;
1772 std::string sha512Hash;
1773 for (
const auto& hash : target_.hashes()) {
1774 if (hash.type() == Uptane::Hash::Type::kSha256) {
1775 sha256Hash = hash.HashString();
1776 }
else if (hash.type() == Uptane::Hash::Type::kSha512) {
1777 sha512Hash = hash.HashString();
1780 std::string filename = (storage.images_path_ / target_.hashes()[0].HashString()).
string();
1782 auto statement = db.prepareStatement<std::string, std::string, std::string>(
1783 "INSERT OR REPLACE INTO target_images (targetname, sha256, sha512, filename) VALUES ( ?, ?, ?, ?);",
1784 target_.filename(), sha256Hash, sha512Hash, target_.hashes()[0].HashString());
1786 if (statement.step() != SQLITE_DONE) {
1787 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1790 boost::filesystem::create_directories(storage.images_path_);
1791 stream_.open(filename);
1792 if (!stream_.good()) {
1793 LOG_ERROR <<
"Could not open image for write: " << storage.images_path_ / target_.filename();
1800 SQLTargetWHandle::wcommit();
1801 }
catch (std::exception& ex) {
1802 LOG_ERROR <<
"Failed to commit to database: " << ex.what();
1804 LOG_ERROR <<
"Failed to commit to database: unknown error";
1808 size_t wfeed(
const uint8_t* buf,
size_t size)
override {
1809 stream_.write(reinterpret_cast<const char*>(buf), static_cast<std::streamsize>(size));
1810 written_size_ += size;
1815 void wcommit()
override {
1821 void wabort() noexcept
override {
1826 if (storage_ !=
nullptr) {
1829 db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_.filename());
1830 if (statement.step() != SQLITE_DONE) {
1831 LOG_ERROR <<
"could not delete " << target_.filename() <<
" from sql storage";
1840 const boost::filesystem::path& image_path,
const uintmax_t& start_from = 0)
1841 : db_path_(db_path), target_(std::move(target)) {
1842 stream_.open(image_path.string(), std::ofstream::out | std::ofstream::app);
1843 if (!stream_.good()) {
1844 LOG_ERROR <<
"Could not open image for write: " << image_path;
1848 written_size_ = start_from;
1850 boost::filesystem::path db_path_;
1852 std::ofstream stream_;
1856 std::unique_ptr<StorageTargetWHandle> SQLStorage::allocateTargetFile(
const Uptane::Target& target) {
1857 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(*
this, target));
1863 : db_path_(storage.dbPath()), target_(std::move(target)), size_(0) {
1866 auto exists = storage.checkTargetFile(target_);
1868 LOG_ERROR <<
"File " << target_.filename() <<
" with expected hash not found in the database!";
1872 size_ = exists->first;
1873 partial_ = size_ < target_.length();
1874 image_path_ = storage.images_path_ / exists->second;
1875 stream_.open(image_path_.string());
1876 if (!stream_.good()) {
1877 LOG_ERROR <<
"Could not open image: " << storage.images_path_ / target_.filename();
1884 uintmax_t rsize()
const override {
return size_; }
1886 size_t rread(uint8_t* buf,
size_t size)
override {
1887 stream_.read(reinterpret_cast<char*>(buf), static_cast<std::streamsize>(size));
1888 return static_cast<size_t>(stream_.gcount());
1891 void rclose() noexcept
override {
1892 if (stream_.is_open()) {
1897 bool isPartial()
const noexcept
override {
return partial_; }
1898 std::unique_ptr<StorageTargetWHandle> toWriteHandle()
override {
1899 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(db_path_, target_, image_path_, size_));
1903 boost::filesystem::path db_path_;
1906 bool partial_{
false};
1907 boost::filesystem::path image_path_;
1908 std::ifstream stream_;
1911 std::unique_ptr<StorageTargetRHandle> SQLStorage::openTargetFile(
const Uptane::Target& target) {
1912 return std_::make_unique<SQLTargetRHandle>(*
this, target);
1915 std::vector<Uptane::Target> SQLStorage::getTargetFiles() {
1918 auto statement = db.prepareStatement<>(
"SELECT targetname, filename, sha256, sha512 FROM target_images;");
1920 std::vector<Uptane::Target> v;
1922 int result = statement.step();
1923 while (
result != SQLITE_DONE) {
1924 if (
result != SQLITE_ROW) {
1925 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1926 throw std::runtime_error(
"Error getting target files");
1929 auto tname = statement.get_result_col_str(0).value();
1930 auto fname = statement.get_result_col_str(1).value();
1931 auto tsize = boost::filesystem::file_size(images_path_ / fname);
1932 auto sha256 = statement.get_result_col_str(2).value();
1933 auto sha512 = statement.get_result_col_str(3).value();
1935 std::vector<Uptane::Hash> hashes;
1936 if (!sha256.empty()) {
1937 hashes.emplace_back(Uptane::Hash::Type::kSha256, sha256);
1939 if (!sha512.empty()) {
1940 hashes.emplace_back(Uptane::Hash::Type::kSha512, sha512);
1942 v.emplace_back(tname, Uptane::EcuMap{}, hashes, tsize);
1944 result = statement.step();
1950 void SQLStorage::removeTargetFile(
const std::string& target_name) {
1953 if (!db.beginTransaction()) {
1954 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
1959 db.prepareStatement<std::string>(
"SELECT filename FROM target_images WHERE targetname = ?;", target_name);
1961 if (statement.step() != SQLITE_ROW) {
1962 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1963 throw std::runtime_error(
"Could not find target file");
1966 std::string filename = statement.get_result_col_str(0).value();
1968 statement = db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_name);
1970 if (statement.step() != SQLITE_DONE) {
1971 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1972 throw std::runtime_error(
"Could not remove target file");
1975 boost::filesystem::remove(images_path_ / filename);
1976 }
catch (std::exception& e) {
1977 LOG_ERROR <<
"Could not remove target file";
1981 db.commitTransaction();
1984 void SQLStorage::cleanUp() { boost::filesystem::remove_all(dbPath()); }