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 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 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 <<
"Meta not present";
605 }
else if (
result != SQLITE_ROW) {
606 LOG_ERROR <<
"Can't get meta: " << 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 <<
"Meta not present";
622 }
else if (
result != SQLITE_ROW) {
623 LOG_ERROR <<
"Can't get meta: " << 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 meta: " << 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 <<
"Meta not present";
652 }
else if (
result != SQLITE_ROW) {
653 LOG_ERROR <<
"Can't get meta: " << 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) {
1216 if (ecu_serial.empty()) {
1217 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1218 if (statement.step() == SQLITE_ROW) {
1219 ecu_serial = statement.get_result_col_str(0).value();
1221 LOG_WARNING <<
"Could not find primary ecu serial, defaulting to empty serial: " << db.errmsg();
1226 auto statement = db.prepareStatement<std::string>(
"SELECT hardware_id FROM ecus WHERE serial = ?;", ecu_serial);
1227 if (statement.step() == SQLITE_ROW) {
1231 LOG_WARNING <<
"Could not find hardware_id for serial " << ecu_serial <<
": " << db.errmsg();
1236 bool SQLStorage::loadInstallationLog(
const std::string& ecu_serial, std::vector<Uptane::Target>* log,
1237 bool only_installed) {
1240 std::string ecu_serial_real = ecu_serial;
1241 Uptane::EcuMap ecu_map;
1242 loadEcuMap(db, ecu_serial_real, ecu_map);
1245 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1246 "ecu_serial = ? ORDER BY id;";
1247 if (only_installed) {
1249 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1250 "ecu_serial = ? AND was_installed = 1 ORDER BY id;";
1253 auto statement = db.prepareStatement<std::string>(query, ecu_serial_real);
1254 int statement_state;
1256 std::vector<Uptane::Target> new_log;
1257 std::map<int64_t, size_t> ids_map;
1259 while ((statement_state = statement.step()) == SQLITE_ROW) {
1261 auto id = statement.get_result_col_int(0);
1262 auto sha256 = statement.get_result_col_str(1).value();
1263 auto filename = statement.get_result_col_str(2).value();
1264 auto hashes_str = statement.get_result_col_str(3).value();
1265 auto length = statement.get_result_col_int(4);
1266 auto correlation_id = statement.get_result_col_str(5).value();
1267 auto custom_str = statement.get_result_col_str(6).value();
1271 std::vector<Uptane::Hash> hashes = Uptane::Hash::decodeVector(hashes_str);
1273 auto find_sha256 = std::find_if(hashes.cbegin(), hashes.cend(),
1274 [](
const Uptane::Hash& h) {
return h.type() == Uptane::Hash::Type::kSha256; });
1275 if (find_sha256 == hashes.cend()) {
1276 LOG_WARNING <<
"No sha256 in hashes list";
1277 hashes.emplace_back(Uptane::Hash::Type::kSha256, sha256);
1280 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1281 if (!custom_str.empty()) {
1282 std::istringstream css(custom_str);
1285 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom,
nullptr)) {
1286 t.updateCustom(custom);
1288 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1291 new_log.emplace_back(t);
1295 }
catch (
const boost::bad_optional_access&) {
1296 LOG_ERROR <<
"Incompleted installed version, keeping old one";
1301 if (statement_state != SQLITE_DONE) {
1302 LOG_ERROR <<
"Can't get installed_versions: " << db.errmsg();
1306 if (log ==
nullptr) {
1310 *log = std::move(new_log);
1315 bool SQLStorage::loadInstalledVersions(
const std::string& ecu_serial, boost::optional<Uptane::Target>* current_version,
1316 boost::optional<Uptane::Target>* pending_version) {
1319 std::string ecu_serial_real = ecu_serial;
1320 Uptane::EcuMap ecu_map;
1321 loadEcuMap(db, ecu_serial_real, ecu_map);
1324 auto sha256 = statement.get_result_col_str(0).value();
1325 auto filename = statement.get_result_col_str(1).value();
1326 auto hashes_str = statement.get_result_col_str(2).value();
1327 auto length = statement.get_result_col_int(3);
1328 auto correlation_id = statement.get_result_col_str(4).value();
1329 auto custom_str = statement.get_result_col_str(5).value();
1333 std::vector<Uptane::Hash> hashes = Uptane::Hash::decodeVector(hashes_str);
1335 auto find_sha256 = std::find_if(hashes.cbegin(), hashes.cend(),
1336 [](
const Uptane::Hash& h) {
return h.type() == Uptane::Hash::Type::kSha256; });
1337 if (find_sha256 == hashes.cend()) {
1338 LOG_WARNING <<
"No sha256 in hashes list";
1339 hashes.emplace_back(Uptane::Hash::Type::kSha256, sha256);
1341 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1342 if (!custom_str.empty()) {
1343 std::istringstream css(custom_str);
1346 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom, &errs)) {
1347 t.updateCustom(custom);
1349 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1356 if (current_version !=
nullptr) {
1357 auto statement = db.prepareStatement<std::string>(
1358 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1359 "ecu_serial = ? AND is_current = 1 LIMIT 1;",
1362 if (statement.step() == SQLITE_ROW) {
1364 *current_version = read_target(statement);
1365 }
catch (
const boost::bad_optional_access&) {
1366 LOG_ERROR <<
"Could not read current installed version";
1370 LOG_TRACE <<
"Cannot get current installed version: " << db.errmsg();
1371 *current_version = boost::none;
1375 if (pending_version !=
nullptr) {
1376 auto statement = db.prepareStatement<std::string>(
1377 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1378 "ecu_serial = ? AND is_pending = 1 LIMIT 1;",
1381 if (statement.step() == SQLITE_ROW) {
1383 *pending_version = read_target(statement);
1384 }
catch (
const boost::bad_optional_access&) {
1385 LOG_ERROR <<
"Could not read pending installed version";
1389 LOG_TRACE <<
"Cannot get pending installed version: " << db.errmsg();
1390 *pending_version = boost::none;
1397 bool SQLStorage::hasPendingInstall() {
1400 auto statement = db.prepareStatement(
"SELECT count(*) FROM installed_versions where is_pending = 1");
1401 if (statement.step() != SQLITE_ROW) {
1402 LOG_ERROR <<
"Can't get tables count: " << db.errmsg();
1403 throw std::runtime_error(
"Could not count pending installations");
1406 return statement.get_result_col_int(0) > 0;
1409 void SQLStorage::getPendingEcus(std::vector<std::pair<Uptane::EcuSerial, Uptane::Hash>>* pendingEcus) {
1412 auto statement = db.prepareStatement(
"SELECT ecu_serial, sha256 FROM installed_versions where is_pending = 1");
1413 int statement_result = statement.step();
1414 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1415 throw std::runtime_error(
"Failed to get ECUs with a pending target installation: " + db.errmsg());
1418 std::vector<std::pair<Uptane::EcuSerial, Uptane::Hash>> ecu_res;
1420 if (statement_result == SQLITE_DONE) {
1425 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1426 std::string ecu_serial = statement.get_result_col_str(0).value();
1427 std::string hash = statement.get_result_col_str(1).value();
1428 ecu_res.emplace_back(
1432 if (pendingEcus !=
nullptr) {
1433 *pendingEcus = std::move(ecu_res);
1437 void SQLStorage::clearInstalledVersions() {
1440 if (db.exec(
"DELETE FROM installed_versions;",
nullptr,
nullptr) != SQLITE_OK) {
1441 LOG_ERROR <<
"Can't clear installed_versions: " << db.errmsg();
1450 auto statement = db.prepareStatement<std::string, int, std::string, std::string>(
1451 "INSERT OR REPLACE INTO ecu_installation_results (ecu_serial, success, result_code, description) VALUES "
1453 ecu_serial.ToString(), static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description);
1454 if (statement.step() != SQLITE_DONE) {
1455 LOG_ERROR <<
"Can't set ecu installation result: " << db.errmsg();
1460 bool SQLStorage::loadEcuInstallationResults(
1461 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>>* results) {
1464 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_res;
1467 auto statement = db.prepareStatement(
1468 "SELECT ecu_serial, success, result_code, description FROM ecu_installation_results INNER JOIN ecus ON "
1469 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1470 int statement_result = statement.step();
1471 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1472 LOG_ERROR <<
"Can't get ecu_installation_results: " << db.errmsg();
1476 if (statement_result == SQLITE_DONE) {
1481 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1483 std::string ecu_serial = statement.get_result_col_str(0).value();
1484 auto success = static_cast<bool>(statement.get_result_col_int(1));
1485 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(2).value());
1486 std::string description = statement.get_result_col_str(3).value();
1489 }
catch (
const boost::bad_optional_access&) {
1494 if (results !=
nullptr) {
1495 *results = std::move(ecu_res);
1502 const std::string& correlation_id) {
1505 auto statement = db.prepareStatement<int, std::string, std::string, std::string, std::string>(
1506 "INSERT OR REPLACE INTO device_installation_result (unique_mark, success, result_code, description, raw_report, "
1508 "VALUES (0,?,?,?,?,?);",
1509 static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description, raw_report, correlation_id);
1510 if (statement.step() != SQLITE_DONE) {
1511 LOG_ERROR <<
"Can't set device installation result: " << db.errmsg();
1517 std::string* correlation_id) {
1521 std::string raw_report_res;
1522 std::string corrid_res;
1524 auto statement = db.prepareStatement(
1525 "SELECT success, result_code, description, raw_report, correlation_id FROM device_installation_result;");
1526 int statement_result = statement.step();
1527 if (statement_result == SQLITE_DONE) {
1528 LOG_TRACE <<
"No device installation result in db";
1530 }
else if (statement_result != SQLITE_ROW) {
1531 LOG_ERROR <<
"Can't get device_installation_result: " << db.errmsg();
1536 auto success = static_cast<bool>(statement.get_result_col_int(0));
1537 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(1).value());
1538 std::string description = statement.get_result_col_str(2).value();
1539 raw_report_res = statement.get_result_col_str(3).value();
1540 corrid_res = statement.get_result_col_str(4).value();
1543 }
catch (
const boost::bad_optional_access&) {
1548 *
result = std::move(dev_res);
1551 if (raw_report !=
nullptr) {
1552 *raw_report = std::move(raw_report_res);
1555 if (correlation_id !=
nullptr) {
1556 *correlation_id = std::move(corrid_res);
1562 void SQLStorage::saveEcuReportCounter(
const Uptane::EcuSerial& ecu_serial,
const int64_t counter) {
1565 auto statement = db.prepareStatement<std::string, int64_t>(
1566 "INSERT OR REPLACE INTO ecu_report_counter (ecu_serial, counter) VALUES "
1568 ecu_serial.ToString(), counter);
1569 if (statement.step() != SQLITE_DONE) {
1570 LOG_ERROR <<
"Can't set ecu counter: " << db.errmsg();
1575 bool SQLStorage::loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results) {
1578 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
1581 auto statement = db.prepareStatement(
1582 "SELECT ecu_serial, counter FROM ecu_report_counter INNER JOIN ecus ON "
1583 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1584 int statement_result = statement.step();
1585 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1586 LOG_ERROR <<
"Can't get ecu_report_counter: " << db.errmsg();
1590 if (statement_result == SQLITE_DONE) {
1595 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1597 std::string ecu_serial = statement.get_result_col_str(0).value();
1598 int64_t counter = statement.get_result_col_int(1);
1601 }
catch (
const boost::bad_optional_access&) {
1606 if (results !=
nullptr) {
1607 *results = std::move(ecu_cnt);
1613 void SQLStorage::clearInstallationResults() {
1615 if (!db.beginTransaction()) {
1616 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
1620 if (db.exec(
"DELETE FROM device_installation_result;",
nullptr,
nullptr) != SQLITE_OK) {
1621 LOG_ERROR <<
"Can't clear device_installation_result: " << db.errmsg();
1625 if (db.exec(
"DELETE FROM ecu_installation_results;",
nullptr,
nullptr) != SQLITE_OK) {
1626 LOG_ERROR <<
"Can't clear ecu_installation_results: " << db.errmsg();
1630 db.commitTransaction();
1633 bool SQLStorage::checkAvailableDiskSpace(
const uint64_t required_bytes)
const {
1634 struct statvfs stvfsbuf {};
1635 const int stat_res = statvfs(dbPath().c_str(), &stvfsbuf);
1637 LOG_WARNING <<
"Unable to read filesystem statistics: error code " << stat_res;
1640 const uint64_t available_bytes = (stvfsbuf.f_bsize * stvfsbuf.f_bavail);
1641 const uint64_t reserved_bytes = 1 << 20;
1643 if (required_bytes + reserved_bytes < available_bytes) {
1646 LOG_ERROR <<
"Insufficient disk space available to download target! Required: " << required_bytes
1647 <<
", available: " << available_bytes <<
", reserved: " << reserved_bytes;
1652 boost::optional<std::pair<uintmax_t, std::string>> SQLStorage::checkTargetFile(
const Uptane::Target& target)
const {
1655 auto statement = db.prepareStatement<std::string>(
1656 "SELECT sha256, sha512, filename FROM target_images WHERE targetname = ?;", target.filename());
1658 int statement_state;
1659 while ((statement_state = statement.step()) == SQLITE_ROW) {
1660 auto sha256 = statement.get_result_col_str(0);
1661 auto sha512 = statement.get_result_col_str(1);
1662 auto filename = statement.get_result_col_str(2);
1663 if ((*sha256).empty() && (*sha512).empty()) {
1665 LOG_WARNING <<
"Image without checksum: " << target.filename();
1668 bool sha256_match =
false;
1669 bool sha512_match =
false;
1670 if (!(*sha256).empty()) {
1671 if (target.MatchHash(
Uptane::Hash(Uptane::Hash::Type::kSha256, *sha256))) {
1672 sha256_match =
true;
1676 if (!(*sha512).empty()) {
1677 if (target.MatchHash(
Uptane::Hash(Uptane::Hash::Type::kSha512, *sha512))) {
1678 sha512_match =
true;
1681 if (((*sha256).empty() || sha256_match) && ((*sha512).empty() || sha512_match)) {
1682 if (boost::filesystem::exists(images_path_ / *filename)) {
1683 return {{boost::filesystem::file_size(images_path_ / *filename), *filename}};
1690 if (statement_state == SQLITE_DONE) {
1691 LOG_INFO <<
"No file '" + target.filename() <<
"' with matched hash in the database";
1694 assert(statement_state != SQLITE_ROW);
1695 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1703 : db_(storage.dbPath()), target_(std::move(target)) {
1706 std::string sha256Hash;
1707 std::string sha512Hash;
1708 for (
const auto& hash : target_.hashes()) {
1709 if (hash.type() == Uptane::Hash::Type::kSha256) {
1710 sha256Hash = hash.HashString();
1711 }
else if (hash.type() == Uptane::Hash::Type::kSha512) {
1712 sha512Hash = hash.HashString();
1715 std::string filename = (storage.images_path_ / target_.hashes()[0].HashString()).
string();
1716 auto statement = db_.prepareStatement<std::string, std::string, std::string>(
1717 "INSERT OR REPLACE INTO target_images (targetname, sha256, sha512, filename) VALUES ( ?, ?, ?, ?);",
1718 target_.filename(), sha256Hash, sha512Hash, target_.hashes()[0].HashString());
1720 if (statement.step() != SQLITE_DONE) {
1721 LOG_ERROR <<
"Statement step failure: " << db_.errmsg();
1724 boost::filesystem::create_directories(storage.images_path_);
1725 stream_.open(filename);
1726 if (!stream_.good()) {
1727 LOG_ERROR <<
"Could not open image for write: " << storage.images_path_ / target_.filename();
1734 SQLTargetWHandle::wcommit();
1735 }
catch (std::exception& ex) {
1736 LOG_ERROR <<
"Failed to commit to database: " << ex.what();
1738 LOG_ERROR <<
"Failed to commit to database: unknown error";
1742 size_t wfeed(
const uint8_t* buf,
size_t size)
override {
1743 stream_.write(reinterpret_cast<const char*>(buf), static_cast<std::streamsize>(size));
1744 written_size_ += size;
1749 void wcommit()
override {
1755 void wabort() noexcept
override {
1759 if (sqlite3_changes(db_.get()) > 0) {
1761 db_.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_.filename());
1762 if (statement.step() != SQLITE_DONE) {
1763 LOG_ERROR <<
"could not delete " << target_.filename() <<
" from sql storage";
1772 const boost::filesystem::path& image_path,
const uintmax_t& start_from = 0)
1773 : db_(db_path), target_(std::move(target)) {
1774 if (db_.get_rc() != SQLITE_OK) {
1775 LOG_ERROR <<
"Can't open database: " << db_.errmsg();
1778 stream_.open(image_path.string(), std::ofstream::out | std::ofstream::app);
1779 if (!stream_.good()) {
1780 LOG_ERROR <<
"Could not open image for write: " << image_path;
1784 written_size_ = start_from;
1788 std::ofstream stream_;
1791 std::unique_ptr<StorageTargetWHandle> SQLStorage::allocateTargetFile(
const Uptane::Target& target) {
1792 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(*
this, target));
1798 : db_path_(storage.dbPath()), db_(db_path_), target_(std::move(target)), size_(0) {
1801 auto exists = storage.checkTargetFile(target_);
1806 size_ = exists->first;
1807 partial_ = size_ < target_.length();
1808 image_path_ = storage.images_path_ / exists->second;
1809 stream_.open(image_path_.string());
1810 if (!stream_.good()) {
1811 LOG_ERROR <<
"Could not open image: " << storage.images_path_ / target_.filename();
1818 uintmax_t rsize()
const override {
return size_; }
1820 size_t rread(uint8_t* buf,
size_t size)
override {
1821 stream_.read(reinterpret_cast<char*>(buf), static_cast<std::streamsize>(size));
1822 return static_cast<size_t>(stream_.gcount());
1825 void rclose() noexcept
override {
1826 if (stream_.is_open()) {
1831 bool isPartial()
const noexcept
override {
return partial_; }
1832 std::unique_ptr<StorageTargetWHandle> toWriteHandle()
override {
1833 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(db_path_, target_, image_path_, size_));
1837 boost::filesystem::path db_path_;
1841 bool partial_{
false};
1842 boost::filesystem::path image_path_;
1843 std::ifstream stream_;
1846 std::unique_ptr<StorageTargetRHandle> SQLStorage::openTargetFile(
const Uptane::Target& target) {
1847 return std_::make_unique<SQLTargetRHandle>(*
this, target);
1850 std::vector<Uptane::Target> SQLStorage::getTargetFiles() {
1853 auto statement = db.prepareStatement<>(
"SELECT targetname, filename, sha256, sha512 FROM target_images;");
1855 std::vector<Uptane::Target> v;
1857 int result = statement.step();
1858 while (
result != SQLITE_DONE) {
1859 if (
result != SQLITE_ROW) {
1860 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1861 throw std::runtime_error(
"Error getting target files");
1864 auto tname = statement.get_result_col_str(0).value();
1865 auto fname = statement.get_result_col_str(1).value();
1866 auto tsize = boost::filesystem::file_size(images_path_ / fname);
1867 auto sha256 = statement.get_result_col_str(2).value();
1868 auto sha512 = statement.get_result_col_str(3).value();
1870 std::vector<Uptane::Hash> hashes;
1871 if (!sha256.empty()) {
1872 hashes.emplace_back(Uptane::Hash::Type::kSha256, sha256);
1874 if (!sha512.empty()) {
1875 hashes.emplace_back(Uptane::Hash::Type::kSha512, sha512);
1877 v.emplace_back(tname, Uptane::EcuMap{}, hashes, tsize);
1879 result = statement.step();
1885 void SQLStorage::removeTargetFile(
const std::string& target_name) {
1888 if (!db.beginTransaction()) {
1889 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
1894 db.prepareStatement<std::string>(
"SELECT filename FROM target_images WHERE targetname = ?;", target_name);
1896 if (statement.step() != SQLITE_ROW) {
1897 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1898 throw std::runtime_error(
"Could not find target file");
1901 std::string filename = statement.get_result_col_str(0).value();
1903 statement = db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_name);
1905 if (statement.step() != SQLITE_DONE) {
1906 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1907 throw std::runtime_error(
"Could not remove target file");
1910 boost::filesystem::remove(images_path_ / filename);
1911 }
catch (std::exception& e) {
1912 LOG_ERROR <<
"Could not remove target file";
1916 db.commitTransaction();
1919 void SQLStorage::cleanUp() { boost::filesystem::remove_all(dbPath()); }