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 db.beginTransaction();
21 auto statement = db.prepareStatement<int, int,
int>(
22 "SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);", static_cast<int>(repo), role.ToInt(), -1);
24 int result = statement.step();
26 if (
result == SQLITE_DONE) {
27 LOG_TRACE <<
"meta with role " << role.ToString() <<
" in repo " << repo.toString() <<
" not present in db";
29 }
else if (
result != SQLITE_ROW) {
30 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
33 std::string meta = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
35 int version = Uptane::extractVersionUntrusted(meta);
37 LOG_ERROR <<
"Corrupted metadata";
42 statement = db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
43 static_cast<int>(repo), role.ToInt(), version);
45 if (statement.step() != SQLITE_DONE) {
46 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
50 statement = db.prepareStatement<int, int, int,
int>(
51 "UPDATE meta SET version = ? WHERE (repo=? AND meta_type=? AND version=?);", version, static_cast<int>(repo),
54 if (statement.step() != SQLITE_DONE) {
55 LOG_ERROR <<
"Can't update metadata: " << db.errmsg();
59 db.commitTransaction();
62 SQLStorage::SQLStorage(
const StorageConfig& config,
bool readonly)
63 :
SQLStorageBase(config.sqldb_path.get(config.path), readonly, libaktualizr_schema_migrations,
64 libaktualizr_schema_rollback_migrations, libaktualizr_current_schema,
65 libaktualizr_current_schema_version),
68 cleanMetaVersion(Uptane::RepositoryType::Director(), Uptane::Role::Root());
69 cleanMetaVersion(Uptane::RepositoryType::Image(), Uptane::Role::Root());
71 LOG_ERROR <<
"SQLite database metadata version migration failed";
75 void SQLStorage::storePrimaryKeys(
const std::string& public_key,
const std::string& private_key) {
78 auto statement = db.prepareStatement<std::string>(
79 "INSERT OR REPLACE INTO primary_keys(unique_mark,public,private) VALUES (0,?,?);", public_key, private_key);
80 if (statement.step() != SQLITE_DONE) {
81 LOG_ERROR <<
"Can't set Primary keys: " << db.errmsg();
86 bool SQLStorage::loadPrimaryKeys(std::string* public_key, std::string* private_key) {
87 return loadPrimaryPublic(public_key) && loadPrimaryPrivate(private_key);
90 bool SQLStorage::loadPrimaryPublic(std::string* public_key) {
93 auto statement = db.prepareStatement(
"SELECT public FROM primary_keys LIMIT 1;");
95 int result = statement.step();
96 if (
result == SQLITE_DONE) {
97 LOG_TRACE <<
"No public key in db";
99 }
else if (
result != SQLITE_ROW) {
100 LOG_ERROR <<
"Can't get public key: " << db.errmsg();
104 auto pub = statement.get_result_col_str(0);
105 if (pub == boost::none) {
109 if (public_key !=
nullptr) {
110 *public_key = std::move(pub.value());
116 bool SQLStorage::loadPrimaryPrivate(std::string* private_key) {
119 auto statement = db.prepareStatement(
"SELECT private FROM primary_keys LIMIT 1;");
121 int result = statement.step();
122 if (
result == SQLITE_DONE) {
123 LOG_TRACE <<
"No private key in db";
125 }
else if (
result != SQLITE_ROW) {
126 LOG_ERROR <<
"Can't get private key: " << db.errmsg();
130 auto priv = statement.get_result_col_str(0);
131 if (priv == boost::none) {
135 if (private_key !=
nullptr) {
136 *private_key = std::move(priv.value());
142 void SQLStorage::clearPrimaryKeys() {
145 if (db.exec(
"DELETE FROM primary_keys;",
nullptr,
nullptr) != SQLITE_OK) {
146 LOG_ERROR <<
"Can't clear Primary keys: " << db.errmsg();
151 void SQLStorage::saveSecondaryInfo(
const Uptane::EcuSerial& ecu_serial,
const std::string& sec_type,
155 std::stringstream key_type_ss;
156 key_type_ss << public_key.Type();
157 std::string key_type_str;
158 key_type_str = key_type_ss.str();
159 key_type_str.erase(std::remove(key_type_str.begin(), key_type_str.end(),
'"'), key_type_str.end());
161 db.beginTransaction();
164 db.prepareStatement<std::string>(
"SELECT count(*) FROM secondary_ecus WHERE serial = ?;", ecu_serial.ToString());
165 if (statement.step() != SQLITE_ROW) {
166 LOG_ERROR <<
"Can't get count of secondary_ecus table: " << db.errmsg();
171 if (statement.get_result_col_int(0) != 0) {
172 req =
"UPDATE secondary_ecus SET sec_type = ?, public_key_type = ?, public_key = ? WHERE serial = ?;";
175 "INSERT INTO secondary_ecus (serial, sec_type, public_key_type, public_key) SELECT "
176 "serial,?,?,? FROM ecus WHERE (serial = ? AND is_primary = 0);";
179 statement = db.prepareStatement<std::string, std::string, std::string, std::string>(
180 req, sec_type, key_type_str, public_key.Value(), ecu_serial.ToString());
181 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
182 LOG_ERROR <<
"Can't save Secondary key: " << db.errmsg();
186 db.commitTransaction();
192 db.beginTransaction();
195 db.prepareStatement<std::string>(
"SELECT count(*) FROM secondary_ecus WHERE serial = ?;", ecu_serial.ToString());
196 if (statement.step() != SQLITE_ROW) {
197 LOG_ERROR <<
"Can't get count of secondary_ecus table: " << db.errmsg();
202 if (statement.get_result_col_int(0) != 0) {
203 req =
"UPDATE secondary_ecus SET extra = ? WHERE serial = ?;";
205 req =
"INSERT INTO secondary_ecus (extra, serial) VALUES (?,?);";
208 statement = db.prepareStatement<std::string, std::string>(req,
data, ecu_serial.ToString());
209 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
210 LOG_ERROR <<
"Can't save Secondary data: " << db.errmsg();
214 db.commitTransaction();
222 auto statement = db.prepareStatement<std::string>(
223 "SELECT serial, hardware_id, sec_type, public_key_type, public_key, extra FROM ecus LEFT JOIN secondary_ecus "
225 "(serial) WHERE (serial = ? AND is_primary = 0);",
226 ecu_serial.ToString());
227 int statement_state = statement.step();
228 if (statement_state == SQLITE_DONE) {
229 LOG_TRACE <<
"Secondary ECU " << ecu_serial <<
" not found";
231 }
else if (statement_state != SQLITE_ROW) {
232 LOG_ERROR <<
"Cannot load Secondary info: " << db.errmsg();
239 std::string sec_type = statement.get_result_col_str(2).value_or(
"");
240 std::string kt_str = statement.get_result_col_str(3).value_or(
"");
244 std::stringstream(kt_str) >> key_type;
245 key =
PublicKey(statement.get_result_col_str(4).value_or(
""), key_type);
247 std::string extra = statement.get_result_col_str(5).value_or(
"");
248 new_sec =
SecondaryInfo{serial, hw_id, sec_type, key, extra};
249 }
catch (
const boost::bad_optional_access&) {
253 if (secondary !=
nullptr) {
254 *secondary = std::move(new_sec);
260 bool SQLStorage::loadSecondariesInfo(std::vector<SecondaryInfo>* secondaries) {
263 std::vector<SecondaryInfo> new_secs;
268 auto statement = db.prepareStatement(
269 "SELECT serial, hardware_id, sec_type, public_key_type, public_key, extra FROM ecus LEFT JOIN secondary_ecus "
271 "(serial) WHERE is_primary = 0 ORDER BY ecus.id;");
272 while ((statement_state = statement.step()) == SQLITE_ROW) {
276 std::string sec_type = statement.get_result_col_str(2).value_or(
"");
277 std::string kt_str = statement.get_result_col_str(3).value_or(
"");
281 std::stringstream(kt_str) >> key_type;
282 key =
PublicKey(statement.get_result_col_str(4).value_or(
""), key_type);
284 std::string extra = statement.get_result_col_str(5).value_or(
"");
285 new_secs.emplace_back(
SecondaryInfo{serial, hw_id, sec_type, key, extra});
287 }
catch (
const boost::bad_optional_access&) {
291 if (statement_state != SQLITE_DONE) {
292 LOG_ERROR <<
"Can't load Secondary info" << db.errmsg();
295 if (secondaries !=
nullptr) {
296 *secondaries = std::move(new_secs);
302 void SQLStorage::storeTlsCreds(
const std::string& ca,
const std::string& cert,
const std::string& pkey) {
308 void SQLStorage::storeTlsCa(
const std::string& ca) {
311 db.beginTransaction();
313 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
314 if (statement.step() != SQLITE_ROW) {
315 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
320 if (statement.get_result_col_int(0) != 0) {
321 req =
"UPDATE OR REPLACE tls_creds SET ca_cert = ?;";
323 req =
"INSERT INTO tls_creds(ca_cert) VALUES (?);";
327 if (statement.step() != SQLITE_DONE) {
328 LOG_ERROR <<
"Can't set ca_cert: " << db.errmsg();
332 db.commitTransaction();
335 void SQLStorage::storeTlsCert(
const std::string& cert) {
338 db.beginTransaction();
340 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
341 if (statement.step() != SQLITE_ROW) {
342 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
347 if (statement.get_result_col_int(0) != 0) {
348 req =
"UPDATE OR REPLACE tls_creds SET client_cert = ?;";
350 req =
"INSERT INTO tls_creds(client_cert) VALUES (?);";
354 if (statement.step() != SQLITE_DONE) {
355 LOG_ERROR <<
"Can't set client_cert: " << db.errmsg();
359 db.commitTransaction();
362 void SQLStorage::storeTlsPkey(
const std::string& pkey) {
365 db.beginTransaction();
367 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
368 if (statement.step() != SQLITE_ROW) {
369 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
374 if (statement.get_result_col_int(0) != 0) {
375 req =
"UPDATE OR REPLACE tls_creds SET client_pkey = ?;";
377 req =
"INSERT INTO tls_creds(client_pkey) VALUES (?);";
381 if (statement.step() != SQLITE_DONE) {
382 LOG_ERROR <<
"Can't set client_pkey: " << db.errmsg();
386 db.commitTransaction();
389 bool SQLStorage::loadTlsCreds(std::string* ca, std::string* cert, std::string* pkey) {
392 db.beginTransaction();
394 auto statement = db.prepareStatement(
"SELECT ca_cert, client_cert, client_pkey FROM tls_creds LIMIT 1;");
396 int result = statement.step();
397 if (
result == SQLITE_DONE) {
398 LOG_TRACE <<
"Tls creds not present";
400 }
else if (
result != SQLITE_ROW) {
401 LOG_ERROR <<
"Can't get tls_creds: " << db.errmsg();
405 std::string ca_v, cert_v, pkey_v;
407 ca_v = statement.get_result_col_str(0).value();
408 cert_v = statement.get_result_col_str(1).value();
409 pkey_v = statement.get_result_col_str(2).value();
410 }
catch (
const boost::bad_optional_access&) {
415 *ca = std::move(ca_v);
417 if (cert !=
nullptr) {
418 *cert = std::move(cert_v);
420 if (pkey !=
nullptr) {
421 *pkey = std::move(pkey_v);
424 db.commitTransaction();
429 void SQLStorage::clearTlsCreds() {
432 if (db.exec(
"DELETE FROM tls_creds;",
nullptr,
nullptr) != SQLITE_OK) {
433 LOG_ERROR <<
"Can't clear tls_creds: " << db.errmsg();
438 bool SQLStorage::loadTlsCa(std::string* ca) {
441 auto statement = db.prepareStatement(
"SELECT ca_cert FROM tls_creds LIMIT 1;");
443 int result = statement.step();
444 if (
result == SQLITE_DONE) {
445 LOG_TRACE <<
"ca_cert not present";
447 }
else if (
result != SQLITE_ROW) {
448 LOG_ERROR <<
"Can't get ca_cert: " << db.errmsg();
452 auto ca_r = statement.get_result_col_str(0);
453 if (ca_r == boost::none) {
458 *ca = std::move(ca_r.value());
464 bool SQLStorage::loadTlsCert(std::string* cert) {
467 auto statement = db.prepareStatement(
"SELECT client_cert FROM tls_creds LIMIT 1;");
469 int result = statement.step();
470 if (
result == SQLITE_DONE) {
471 LOG_TRACE <<
"client_cert not present in db";
473 }
else if (
result != SQLITE_ROW) {
474 LOG_ERROR <<
"Can't get client_cert: " << db.errmsg();
478 auto cert_r = statement.get_result_col_str(0);
479 if (cert_r == boost::none) {
483 if (cert !=
nullptr) {
484 *cert = std::move(cert_r.value());
490 bool SQLStorage::loadTlsPkey(std::string* pkey) {
493 auto statement = db.prepareStatement(
"SELECT client_pkey FROM tls_creds LIMIT 1;");
495 int result = statement.step();
496 if (
result == SQLITE_DONE) {
497 LOG_TRACE <<
"client_pkey not present in db";
499 }
else if (
result != SQLITE_ROW) {
500 LOG_ERROR <<
"Can't get client_pkey: " << db.errmsg();
504 auto pkey_r = statement.get_result_col_str(0);
505 if (pkey_r == boost::none) {
509 if (pkey !=
nullptr) {
510 *pkey = std::move(pkey_r.value());
519 db.beginTransaction();
522 db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
523 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
525 if (del_statement.step() != SQLITE_DONE) {
526 LOG_ERROR <<
"Can't clear Root metadata: " << db.errmsg();
530 auto ins_statement = db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
532 Uptane::Role::Root().ToInt(), version.version());
534 if (ins_statement.step() != SQLITE_DONE) {
535 LOG_ERROR <<
"Can't add metadata: " << db.errmsg();
539 db.commitTransaction();
545 db.beginTransaction();
547 auto del_statement = db.prepareStatement<int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=?);",
548 static_cast<int>(repo), role.ToInt());
550 if (del_statement.step() != SQLITE_DONE) {
551 LOG_ERROR <<
"Can't clear " << role.ToString() <<
" metadata: " << db.errmsg();
556 db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
SQLBlob(
data),
559 if (ins_statement.step() != SQLITE_DONE) {
560 LOG_ERROR <<
"Can't add " << role.ToString() <<
"metadata: " << db.errmsg();
564 db.commitTransaction();
571 if (version.version() < 0) {
572 auto statement = db.prepareStatement<int,
int>(
573 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;", static_cast<int>(repo),
574 Uptane::Role::Root().ToInt());
575 int result = statement.step();
577 if (
result == SQLITE_DONE) {
578 LOG_TRACE <<
"Root metadata not present";
580 }
else if (
result != SQLITE_ROW) {
581 LOG_ERROR <<
"Can't get Root metadata: " << db.errmsg();
584 if (
data !=
nullptr) {
585 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
589 db.prepareStatement<int, int,
int>(
"SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
590 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
592 int result = statement.step();
594 if (
result == SQLITE_DONE) {
595 LOG_TRACE <<
"Root metadata not present";
597 }
else if (
result != SQLITE_ROW) {
598 LOG_ERROR <<
"Can't get Root metadata: " << db.errmsg();
602 const auto blob = reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0));
603 if (blob ==
nullptr) {
604 LOG_ERROR <<
"Can't get Root metadata: " << db.errmsg();
608 if (
data !=
nullptr) {
609 *
data = std::string(blob);
619 auto statement = db.prepareStatement<int,
int>(
620 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;", static_cast<int>(repo),
622 int result = statement.step();
624 if (
result == SQLITE_DONE) {
625 LOG_TRACE << role.ToString() <<
" metadata not present";
627 }
else if (
result != SQLITE_ROW) {
628 LOG_ERROR <<
"Can't get " << role.ToString() <<
" metadata: " << db.errmsg();
631 if (
data !=
nullptr) {
632 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
642 db.prepareStatement<
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type != 0);", static_cast<int>(repo));
644 if (del_statement.step() != SQLITE_DONE) {
645 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
649 void SQLStorage::clearMetadata() {
652 if (db.exec(
"DELETE FROM meta;",
nullptr,
nullptr) != SQLITE_OK) {
653 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
658 void SQLStorage::storeDelegation(
const std::string&
data,
const Uptane::Role role) {
661 db.beginTransaction();
663 auto statement = db.prepareStatement<
SQLBlob, std::string>(
"INSERT OR REPLACE INTO delegations VALUES (?, ?);",
666 if (statement.step() != SQLITE_DONE) {
667 LOG_ERROR <<
"Can't add delegation metadata: " << db.errmsg();
671 db.commitTransaction();
674 bool SQLStorage::loadDelegation(std::string*
data,
const Uptane::Role role) {
678 db.prepareStatement<std::string>(
"SELECT meta FROM delegations WHERE role_name=? LIMIT 1;", role.ToString());
679 int result = statement.step();
681 if (
result == SQLITE_DONE) {
682 LOG_TRACE <<
"Delegations metadata not present";
684 }
else if (
result != SQLITE_ROW) {
685 LOG_ERROR <<
"Can't get delegations metadata: " << db.errmsg();
688 if (
data !=
nullptr) {
689 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
695 bool SQLStorage::loadAllDelegations(std::vector<std::pair<Uptane::Role, std::string>>&
data)
const {
701 auto statement = db.prepareStatement(
"SELECT meta, role_name FROM delegations;");
702 auto statement_state = statement.step();
704 if (statement_state == SQLITE_DONE) {
705 LOG_TRACE <<
"Delegations metadata are not present";
707 }
else if (statement_state != SQLITE_ROW) {
708 LOG_ERROR <<
"Can't get delegations metadata: " << db.errmsg();
713 data.emplace_back(Uptane::Role::Delegation(statement.get_result_col_str(1).value()),
714 statement.get_result_col_blob(0).value());
715 }
while ((statement_state = statement.step()) == SQLITE_ROW);
718 }
catch (
const std::exception& exc) {
719 LOG_ERROR <<
"Failed to fetch records from `delegations` table: " << exc.what();
725 void SQLStorage::deleteDelegation(
const Uptane::Role role) {
728 auto statement = db.prepareStatement<std::string>(
"DELETE FROM delegations WHERE role_name=?;", role.ToString());
732 void SQLStorage::clearDelegations() {
735 if (db.exec(
"DELETE FROM delegations;",
nullptr,
nullptr) != SQLITE_OK) {
736 LOG_ERROR <<
"Can't clear delegations metadata: " << db.errmsg();
740 void SQLStorage::storeDeviceId(
const std::string& device_id) {
743 auto statement = db.prepareStatement<std::string>(
744 "INSERT OR REPLACE INTO device_info(unique_mark,device_id,is_registered) VALUES(0,?,0);", device_id);
745 if (statement.step() != SQLITE_DONE) {
746 LOG_ERROR <<
"Can't set device ID: " << db.errmsg();
751 bool SQLStorage::loadDeviceId(std::string* device_id) {
754 auto statement = db.prepareStatement(
"SELECT device_id FROM device_info LIMIT 1;");
756 int result = statement.step();
757 if (
result == SQLITE_DONE) {
758 LOG_TRACE <<
"device_id not present in db";
760 }
else if (
result != SQLITE_ROW) {
761 LOG_ERROR <<
"Can't get device ID: " << db.errmsg();
765 auto did = statement.get_result_col_str(0);
766 if (did == boost::none) {
767 LOG_ERROR <<
"Empty device ID" << db.errmsg();
771 if (device_id !=
nullptr) {
772 *device_id = std::move(did.value());
778 void SQLStorage::clearDeviceId() {
781 if (db.exec(
"DELETE FROM device_info;",
nullptr,
nullptr) != SQLITE_OK) {
782 LOG_ERROR <<
"Can't clear device ID: " << db.errmsg();
787 void SQLStorage::storeEcuRegistered() {
790 db.beginTransaction();
792 auto statement = db.prepareStatement(
"SELECT count(*) FROM device_info;");
793 if (statement.step() != SQLITE_ROW) {
794 throw std::runtime_error(
"Could not get device_info count");
796 if (statement.get_result_col_int(0) != 1) {
797 throw std::runtime_error(
"Cannot set ECU registered if no device_info set");
800 std::string req =
"UPDATE device_info SET is_registered = 1";
801 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
802 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
806 db.commitTransaction();
809 bool SQLStorage::loadEcuRegistered() {
812 auto statement = db.prepareStatement(
"SELECT is_registered FROM device_info LIMIT 1;");
814 int result = statement.step();
815 if (
result == SQLITE_DONE) {
817 }
else if (
result != SQLITE_ROW) {
818 LOG_ERROR <<
"Can't get is_registered in device_info " << db.errmsg();
822 return statement.get_result_col_int(0) != 0;
825 void SQLStorage::clearEcuRegistered() {
829 std::string req =
"UPDATE device_info SET is_registered = 0";
830 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
831 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
836 void SQLStorage::storeNeedReboot() {
839 auto statement = db.prepareStatement<
int>(
"INSERT OR REPLACE INTO need_reboot(unique_mark,flag) VALUES(0,?);", 1);
840 if (statement.step() != SQLITE_DONE) {
841 LOG_ERROR <<
"Can't set need_reboot: " << db.errmsg();
846 bool SQLStorage::loadNeedReboot(
bool* need_reboot) {
849 auto statement = db.prepareStatement(
"SELECT flag FROM need_reboot LIMIT 1;");
851 int result = statement.step();
852 if (
result == SQLITE_DONE) {
853 if (need_reboot !=
nullptr) {
854 *need_reboot =
false;
857 }
else if (
result != SQLITE_ROW) {
858 LOG_ERROR <<
"Can't get need_reboot: " << db.errmsg();
862 auto flag = static_cast<bool>(statement.get_result_col_int(0));
863 if (need_reboot !=
nullptr) {
870 void SQLStorage::clearNeedReboot() {
873 if (db.exec(
"DELETE FROM need_reboot;",
nullptr,
nullptr) != SQLITE_OK) {
874 LOG_ERROR <<
"Can't clear need_reboot: " << db.errmsg();
879 void SQLStorage::storeEcuSerials(
const EcuSerials& serials) {
880 if (serials.size() >= 1) {
883 db.beginTransaction();
885 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
886 LOG_ERROR <<
"Can't clear ecus: " << db.errmsg();
891 std::string serial = serials[0].first.ToString();
892 std::string hwid = serials[0].second.ToString();
894 auto statement = db.prepareStatement<std::string, std::string>(
895 "INSERT INTO ecus(id, serial,hardware_id,is_primary) VALUES (0, ?,?,1);", serial, hwid);
896 if (statement.step() != SQLITE_DONE) {
897 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
902 auto statement_ivupdate = db.prepareStatement<std::string>(
903 "UPDATE installed_versions SET ecu_serial = ? WHERE ecu_serial = '';", serial);
905 if (statement_ivupdate.step() != SQLITE_DONE) {
906 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
911 for (
auto it = serials.cbegin() + 1; it != serials.cend(); it++) {
912 auto statement = db.prepareStatement<int64_t, std::string, std::string>(
913 "INSERT INTO ecus(id,serial,hardware_id) VALUES (?,?,?);", it - serials.cbegin(), it->first.ToString(),
914 it->second.ToString());
916 if (statement.step() != SQLITE_DONE) {
917 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
922 db.commitTransaction();
926 bool SQLStorage::loadEcuSerials(EcuSerials* serials) {
930 auto statement = db.prepareStatement(
"SELECT serial, hardware_id FROM ecus ORDER BY id;");
933 EcuSerials new_serials;
935 while ((statement_state = statement.step()) == SQLITE_ROW) {
937 new_serials.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
940 }
catch (
const boost::bad_optional_access&) {
945 if (statement_state != SQLITE_DONE) {
946 LOG_ERROR <<
"Can't get ECU serials: " << db.errmsg();
950 if (serials !=
nullptr) {
951 *serials = std::move(new_serials);
957 void SQLStorage::clearEcuSerials() {
960 db.beginTransaction();
962 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
963 LOG_ERROR <<
"Can't clear ECUs: " << db.errmsg();
967 if (db.exec(
"DELETE FROM secondary_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
968 LOG_ERROR <<
"Can't clear Secondary ECUs: " << db.errmsg();
972 db.commitTransaction();
975 void SQLStorage::storeCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial,
const std::string& manifest) {
978 auto statement = db.prepareStatement<std::string, std::string>(
979 "UPDATE secondary_ecus SET manifest = ? WHERE (serial = ?);", manifest, ecu_serial.ToString());
980 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
981 LOG_ERROR <<
"Can't save Secondary manifest " << db.errmsg();
986 bool SQLStorage::loadCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial, std::string* manifest) {
989 std::string stmanifest;
993 auto statement = db.prepareStatement<std::string>(
"SELECT manifest FROM secondary_ecus WHERE (serial = ?);",
994 ecu_serial.ToString());
996 if (statement.step() != SQLITE_ROW) {
997 LOG_WARNING <<
"Could not find manifest for ECU " << ecu_serial;
1000 stmanifest = statement.get_result_col_str(0).value_or(
"");
1002 empty = stmanifest ==
"";
1005 if (manifest !=
nullptr) {
1006 *manifest = std::move(stmanifest);
1012 void SQLStorage::storeMisconfiguredEcus(
const std::vector<MisconfiguredEcu>& ecus) {
1013 if (ecus.size() >= 1) {
1016 db.beginTransaction();
1018 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1019 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
1023 std::vector<MisconfiguredEcu>::const_iterator it;
1024 for (it = ecus.begin(); it != ecus.end(); it++) {
1025 auto statement = db.prepareStatement<std::string, std::string,
int>(
1026 "INSERT INTO misconfigured_ecus VALUES (?,?,?);", it->serial.ToString(), it->hardware_id.ToString(),
1027 static_cast<int>(it->state));
1029 if (statement.step() != SQLITE_DONE) {
1030 LOG_ERROR <<
"Can't set misconfigured_ecus: " << db.errmsg();
1035 db.commitTransaction();
1039 bool SQLStorage::loadMisconfiguredEcus(std::vector<MisconfiguredEcu>* ecus) {
1042 auto statement = db.prepareStatement(
"SELECT serial, hardware_id, state FROM misconfigured_ecus;");
1043 int statement_state;
1045 std::vector<MisconfiguredEcu> new_ecus;
1047 while ((statement_state = statement.step()) == SQLITE_ROW) {
1049 new_ecus.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
1051 static_cast<EcuState>(statement.get_result_col_int(2)));
1053 }
catch (
const boost::bad_optional_access&) {
1058 if (statement_state != SQLITE_DONE) {
1059 LOG_ERROR <<
"Can't get misconfigured_ecus: " << db.errmsg();
1063 if (ecus !=
nullptr) {
1064 *ecus = std::move(new_ecus);
1070 void SQLStorage::clearMisconfiguredEcus() {
1073 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1074 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
1079 void SQLStorage::saveInstalledVersion(
const std::string& ecu_serial,
const Uptane::Target& target,
1080 InstalledVersionUpdateMode update_mode) {
1083 db.beginTransaction();
1088 std::string ecu_serial_real = ecu_serial;
1089 if (ecu_serial_real.empty()) {
1090 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1091 if (statement.step() == SQLITE_ROW) {
1092 ecu_serial_real = statement.get_result_col_str(0).value();
1094 LOG_WARNING <<
"Could not find Primary ECU serial, set to lazy init mode";
1098 std::string hashes_encoded = Hash::encodeVector(target.hashes());
1101 boost::optional<int64_t> old_id;
1102 bool old_was_installed =
false;
1104 auto statement = db.prepareStatement<std::string>(
1105 "SELECT id, sha256, name, was_installed FROM installed_versions WHERE ecu_serial = ? ORDER BY id DESC "
1109 if (statement.step() == SQLITE_ROW) {
1110 int64_t rid = statement.get_result_col_int(0);
1111 std::string rsha256 = statement.get_result_col_str(1).value_or(
"");
1112 std::string rname = statement.get_result_col_str(2).value_or(
"");
1113 bool rwasi = statement.get_result_col_int(3) == 1;
1115 if (rsha256 == target.sha256Hash() && rname == target.filename()) {
1117 old_was_installed = rwasi;
1122 if (update_mode == InstalledVersionUpdateMode::kCurrent) {
1124 auto statement = db.prepareStatement<std::string>(
1125 "UPDATE installed_versions SET is_current = 0, is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1126 if (statement.step() != SQLITE_DONE) {
1127 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1130 }
else if (update_mode == InstalledVersionUpdateMode::kPending) {
1132 auto statement = db.prepareStatement<std::string>(
1133 "UPDATE installed_versions SET is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1134 if (statement.step() != SQLITE_DONE) {
1135 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1141 auto statement = db.prepareStatement<std::string, int, int, int64_t>(
1142 "UPDATE installed_versions SET correlation_id = ?, is_current = ?, is_pending = ?, was_installed = ? WHERE id "
1144 target.correlation_id(), static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1145 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1146 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent || old_was_installed), old_id.value());
1148 if (statement.step() != SQLITE_DONE) {
1149 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1153 std::string custom = Utils::jsonToCanonicalStr(target.custom_data());
1154 auto statement = db.prepareStatement<std::string, std::string, std::string, std::string, int64_t, std::string,
1155 std::string, int,
int>(
1156 "INSERT INTO installed_versions(ecu_serial, sha256, name, hashes, length, custom_meta, correlation_id, "
1157 "is_current, is_pending, was_installed) VALUES (?,?,?,?,?,?,?,?,?,?);",
1158 ecu_serial_real, target.sha256Hash(), target.filename(), hashes_encoded, static_cast<int64_t>(target.length()),
1159 custom, target.correlation_id(), static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1160 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1161 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent));
1163 if (statement.step() != SQLITE_DONE) {
1164 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1169 db.commitTransaction();
1172 static void loadEcuMap(
SQLite3Guard& db, std::string& ecu_serial, Uptane::EcuMap& ecu_map) {
1175 if (ecu_serial.empty()) {
1176 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1177 if (statement.step() == SQLITE_ROW) {
1178 ecu_serial = statement.get_result_col_str(0).value();
1179 }
else if (statement.step() == SQLITE_DONE) {
1180 LOG_DEBUG <<
"No serial found in database for this ECU, defaulting to empty serial";
1182 LOG_ERROR <<
"Error getting serial for this ECU, defaulting to empty serial: " << db.errmsg();
1186 if (!ecu_serial.empty()) {
1187 auto statement = db.prepareStatement<std::string>(
"SELECT hardware_id FROM ecus WHERE serial = ?;", ecu_serial);
1188 if (statement.step() == SQLITE_ROW) {
1191 }
else if (statement.step() == SQLITE_DONE) {
1192 LOG_DEBUG <<
"No hardware ID found in database for ECU serial " << ecu_serial;
1194 LOG_ERROR <<
"Error getting hardware ID for ECU serial " << ecu_serial <<
": " << db.errmsg();
1199 bool SQLStorage::loadInstallationLog(
const std::string& ecu_serial, std::vector<Uptane::Target>* log,
1200 bool only_installed) {
1203 std::string ecu_serial_real = ecu_serial;
1204 Uptane::EcuMap ecu_map;
1205 loadEcuMap(db, ecu_serial_real, ecu_map);
1208 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1209 "ecu_serial = ? ORDER BY id;";
1210 if (only_installed) {
1212 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1213 "ecu_serial = ? AND was_installed = 1 ORDER BY id;";
1216 auto statement = db.prepareStatement<std::string>(query, ecu_serial_real);
1217 int statement_state;
1219 std::vector<Uptane::Target> new_log;
1220 std::map<int64_t, size_t> ids_map;
1222 while ((statement_state = statement.step()) == SQLITE_ROW) {
1224 auto id = statement.get_result_col_int(0);
1225 auto sha256 = statement.get_result_col_str(1).value();
1226 auto filename = statement.get_result_col_str(2).value();
1227 auto hashes_str = statement.get_result_col_str(3).value();
1228 auto length = statement.get_result_col_int(4);
1229 auto correlation_id = statement.get_result_col_str(5).value();
1230 auto custom_str = statement.get_result_col_str(6).value();
1234 std::vector<Hash> hashes = Hash::decodeVector(hashes_str);
1237 std::find_if(hashes.cbegin(), hashes.cend(), [](
const Hash& h) {
return h.type() == Hash::Type::kSha256; });
1238 if (find_sha256 == hashes.cend()) {
1239 LOG_WARNING <<
"No sha256 in hashes list";
1240 hashes.emplace_back(Hash::Type::kSha256, sha256);
1243 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1244 if (!custom_str.empty()) {
1245 std::istringstream css(custom_str);
1248 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom,
nullptr)) {
1249 t.updateCustom(custom);
1251 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1254 new_log.emplace_back(t);
1258 }
catch (
const boost::bad_optional_access&) {
1259 LOG_ERROR <<
"Incompleted installed version, keeping old one";
1264 if (statement_state != SQLITE_DONE) {
1265 LOG_ERROR <<
"Can't get installed_versions: " << db.errmsg();
1269 if (log ==
nullptr) {
1273 *log = std::move(new_log);
1278 bool SQLStorage::loadInstalledVersions(
const std::string& ecu_serial, boost::optional<Uptane::Target>* current_version,
1279 boost::optional<Uptane::Target>* pending_version) {
1282 std::string ecu_serial_real = ecu_serial;
1283 Uptane::EcuMap ecu_map;
1284 loadEcuMap(db, ecu_serial_real, ecu_map);
1287 auto sha256 = statement.get_result_col_str(0).value();
1288 auto filename = statement.get_result_col_str(1).value();
1289 auto hashes_str = statement.get_result_col_str(2).value();
1290 auto length = statement.get_result_col_int(3);
1291 auto correlation_id = statement.get_result_col_str(4).value();
1292 auto custom_str = statement.get_result_col_str(5).value();
1296 std::vector<Hash> hashes = Hash::decodeVector(hashes_str);
1299 std::find_if(hashes.cbegin(), hashes.cend(), [](
const Hash& h) {
return h.type() == Hash::Type::kSha256; });
1300 if (find_sha256 == hashes.cend()) {
1301 LOG_WARNING <<
"No sha256 in hashes list";
1302 hashes.emplace_back(Hash::Type::kSha256, sha256);
1304 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1305 if (!custom_str.empty()) {
1306 std::istringstream css(custom_str);
1309 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom, &errs)) {
1310 t.updateCustom(custom);
1312 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1319 if (current_version !=
nullptr) {
1320 auto statement = db.prepareStatement<std::string>(
1321 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1322 "ecu_serial = ? AND is_current = 1 LIMIT 1;",
1325 if (statement.step() == SQLITE_ROW) {
1327 *current_version = read_target(statement);
1328 }
catch (
const boost::bad_optional_access&) {
1329 LOG_ERROR <<
"Could not read current installed version";
1333 LOG_TRACE <<
"Cannot get current installed version: " << db.errmsg();
1334 *current_version = boost::none;
1338 if (pending_version !=
nullptr) {
1339 auto statement = db.prepareStatement<std::string>(
1340 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1341 "ecu_serial = ? AND is_pending = 1 LIMIT 1;",
1344 if (statement.step() == SQLITE_ROW) {
1346 *pending_version = read_target(statement);
1347 }
catch (
const boost::bad_optional_access&) {
1348 LOG_ERROR <<
"Could not read pending installed version";
1352 LOG_TRACE <<
"Cannot get pending installed version: " << db.errmsg();
1353 *pending_version = boost::none;
1360 bool SQLStorage::hasPendingInstall() {
1363 auto statement = db.prepareStatement(
"SELECT count(*) FROM installed_versions where is_pending = 1");
1364 if (statement.step() != SQLITE_ROW) {
1365 LOG_ERROR <<
"Can't get tables count: " << db.errmsg();
1366 throw std::runtime_error(
"Could not count pending installations");
1369 return statement.get_result_col_int(0) > 0;
1372 void SQLStorage::getPendingEcus(std::vector<std::pair<Uptane::EcuSerial, Hash>>* pendingEcus) {
1375 auto statement = db.prepareStatement(
"SELECT ecu_serial, sha256 FROM installed_versions where is_pending = 1");
1376 int statement_result = statement.step();
1377 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1378 throw std::runtime_error(
"Failed to get ECUs with a pending target installation: " + db.errmsg());
1381 std::vector<std::pair<Uptane::EcuSerial, Hash>> ecu_res;
1383 if (statement_result == SQLITE_DONE) {
1388 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1389 std::string ecu_serial = statement.get_result_col_str(0).value();
1390 std::string hash = statement.get_result_col_str(1).value();
1391 ecu_res.emplace_back(std::make_pair(
Uptane::EcuSerial(ecu_serial),
Hash(Hash::Type::kSha256, hash)));
1394 if (pendingEcus !=
nullptr) {
1395 *pendingEcus = std::move(ecu_res);
1399 void SQLStorage::clearInstalledVersions() {
1402 if (db.exec(
"DELETE FROM installed_versions;",
nullptr,
nullptr) != SQLITE_OK) {
1403 LOG_ERROR <<
"Can't clear installed_versions: " << db.errmsg();
1412 auto statement = db.prepareStatement<std::string, int, std::string, std::string>(
1413 "INSERT OR REPLACE INTO ecu_installation_results (ecu_serial, success, result_code, description) VALUES "
1415 ecu_serial.ToString(), static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description);
1416 if (statement.step() != SQLITE_DONE) {
1417 LOG_ERROR <<
"Can't set ECU installation result: " << db.errmsg();
1422 bool SQLStorage::loadEcuInstallationResults(
1423 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>>* results) {
1426 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_res;
1429 auto statement = db.prepareStatement(
1430 "SELECT ecu_serial, success, result_code, description FROM ecu_installation_results INNER JOIN ecus ON "
1431 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1432 int statement_result = statement.step();
1433 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1434 LOG_ERROR <<
"Can't get ecu_installation_results: " << db.errmsg();
1438 if (statement_result == SQLITE_DONE) {
1443 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1445 std::string ecu_serial = statement.get_result_col_str(0).value();
1446 auto success = static_cast<bool>(statement.get_result_col_int(1));
1447 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(2).value());
1448 std::string description = statement.get_result_col_str(3).value();
1451 }
catch (
const boost::bad_optional_access&) {
1456 if (results !=
nullptr) {
1457 *results = std::move(ecu_res);
1464 const std::string& correlation_id) {
1467 auto statement = db.prepareStatement<int, std::string, std::string, std::string, std::string>(
1468 "INSERT OR REPLACE INTO device_installation_result (unique_mark, success, result_code, description, raw_report, "
1470 "VALUES (0,?,?,?,?,?);",
1471 static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description, raw_report, correlation_id);
1472 if (statement.step() != SQLITE_DONE) {
1473 LOG_ERROR <<
"Can't set device installation result: " << db.errmsg();
1479 std::string* correlation_id) {
1483 std::string raw_report_res;
1484 std::string corrid_res;
1486 auto statement = db.prepareStatement(
1487 "SELECT success, result_code, description, raw_report, correlation_id FROM device_installation_result;");
1488 int statement_result = statement.step();
1489 if (statement_result == SQLITE_DONE) {
1490 LOG_TRACE <<
"No device installation result in db";
1492 }
else if (statement_result != SQLITE_ROW) {
1493 LOG_ERROR <<
"Can't get device_installation_result: " << db.errmsg();
1498 auto success = static_cast<bool>(statement.get_result_col_int(0));
1499 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(1).value());
1500 std::string description = statement.get_result_col_str(2).value();
1501 raw_report_res = statement.get_result_col_str(3).value();
1502 corrid_res = statement.get_result_col_str(4).value();
1505 }
catch (
const boost::bad_optional_access&) {
1510 *
result = std::move(dev_res);
1513 if (raw_report !=
nullptr) {
1514 *raw_report = std::move(raw_report_res);
1517 if (correlation_id !=
nullptr) {
1518 *correlation_id = std::move(corrid_res);
1524 void SQLStorage::saveEcuReportCounter(
const Uptane::EcuSerial& ecu_serial,
const int64_t counter) {
1527 auto statement = db.prepareStatement<std::string, int64_t>(
1528 "INSERT OR REPLACE INTO ecu_report_counter (ecu_serial, counter) VALUES "
1530 ecu_serial.ToString(), counter);
1531 if (statement.step() != SQLITE_DONE) {
1532 LOG_ERROR <<
"Can't set ECU counter: " << db.errmsg();
1537 bool SQLStorage::loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results) {
1540 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
1543 auto statement = db.prepareStatement(
1544 "SELECT ecu_serial, counter FROM ecu_report_counter INNER JOIN ecus ON "
1545 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1546 int statement_result = statement.step();
1547 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1548 LOG_ERROR <<
"Can't get ecu_report_counter: " << db.errmsg();
1552 if (statement_result == SQLITE_DONE) {
1557 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1559 std::string ecu_serial = statement.get_result_col_str(0).value();
1560 int64_t counter = statement.get_result_col_int(1);
1563 }
catch (
const boost::bad_optional_access&) {
1568 if (results !=
nullptr) {
1569 *results = std::move(ecu_cnt);
1575 void SQLStorage::saveReportEvent(
const Json::Value& json_value) {
1576 std::string json_string = Utils::jsonToCanonicalStr(json_value);
1578 auto statement = db.prepareStatement<std::string>(
1579 "INSERT INTO report_events SELECT MAX(id) + 1, ? FROM report_events", json_string);
1580 if (statement.step() != SQLITE_DONE) {
1581 LOG_ERROR <<
"Can't save report event: " << db.errmsg();
1586 bool SQLStorage::loadReportEvents(Json::Value* report_array, int64_t* id_max) {
1588 auto statement = db.prepareStatement(
"SELECT id, json_string FROM report_events;");
1589 int statement_result = statement.step();
1590 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1591 LOG_ERROR <<
"Can't get report_events: " << db.errmsg();
1594 if (statement_result == SQLITE_DONE) {
1599 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1601 int64_t
id = statement.get_result_col_int(0);
1602 std::string json_string = statement.get_result_col_str(1).value();
1603 std::istringstream jss(json_string);
1604 Json::Value event_json;
1606 if (Json::parseFromStream(Json::CharReaderBuilder(), jss, &event_json, &errs)) {
1607 report_array->append(event_json);
1608 *id_max = (*id_max) >
id ? (*id_max) : id;
1610 LOG_ERROR <<
"Unable to parse event data: " << errs;
1612 }
catch (
const boost::bad_optional_access&) {
1620 void SQLStorage::deleteReportEvents(int64_t id_max) {
1623 db.beginTransaction();
1625 auto statement = db.prepareStatement<int64_t>(
"DELETE FROM report_events WHERE id <= ?;", id_max);
1626 if (statement.step() != SQLITE_DONE) {
1627 LOG_ERROR <<
"Can't delete report_events";
1630 db.commitTransaction();
1633 void SQLStorage::clearInstallationResults() {
1636 db.beginTransaction();
1638 if (db.exec(
"DELETE FROM device_installation_result;",
nullptr,
nullptr) != SQLITE_OK) {
1639 LOG_ERROR <<
"Can't clear device_installation_result: " << db.errmsg();
1643 if (db.exec(
"DELETE FROM ecu_installation_results;",
nullptr,
nullptr) != SQLITE_OK) {
1644 LOG_ERROR <<
"Can't clear ecu_installation_results: " << db.errmsg();
1648 db.commitTransaction();
1651 bool SQLStorage::checkAvailableDiskSpace(
const uint64_t required_bytes)
const {
1652 struct statvfs stvfsbuf {};
1653 const int stat_res = statvfs(dbPath().c_str(), &stvfsbuf);
1655 LOG_WARNING <<
"Unable to read filesystem statistics: error code " << stat_res;
1658 const uint64_t available_bytes = (static_cast<uint64_t>(stvfsbuf.f_bsize) * stvfsbuf.f_bavail);
1659 const uint64_t reserved_bytes = 1 << 20;
1661 if (required_bytes + reserved_bytes < available_bytes) {
1664 LOG_ERROR <<
"Insufficient disk space available to download target! Required: " << required_bytes
1665 <<
", available: " << available_bytes <<
", reserved: " << reserved_bytes;
1670 boost::optional<std::pair<uintmax_t, std::string>> SQLStorage::checkTargetFile(
const Uptane::Target& target)
const {
1673 auto statement = db.prepareStatement<std::string>(
1674 "SELECT sha256, sha512, filename FROM target_images WHERE targetname = ?;", target.filename());
1676 int statement_state;
1677 while ((statement_state = statement.step()) == SQLITE_ROW) {
1678 auto sha256 = statement.get_result_col_str(0);
1679 auto sha512 = statement.get_result_col_str(1);
1680 auto filename = statement.get_result_col_str(2);
1681 if ((*sha256).empty() && (*sha512).empty()) {
1683 LOG_WARNING <<
"Image without checksum: " << target.filename();
1686 bool sha256_match =
false;
1687 bool sha512_match =
false;
1688 if (!(*sha256).empty()) {
1689 if (target.MatchHash(
Hash(Hash::Type::kSha256, *sha256))) {
1690 sha256_match =
true;
1694 if (!(*sha512).empty()) {
1695 if (target.MatchHash(
Hash(Hash::Type::kSha512, *sha512))) {
1696 sha512_match =
true;
1699 if (((*sha256).empty() || sha256_match) && ((*sha512).empty() || sha512_match)) {
1700 if (boost::filesystem::exists(images_path_ / *filename)) {
1701 return {{boost::filesystem::file_size(images_path_ / *filename), *filename}};
1708 if (statement_state == SQLITE_DONE) {
1711 assert(statement_state != SQLITE_ROW);
1712 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1720 : db_path_(storage.dbPath()), target_(std::move(target)), storage_(&storage) {
1723 std::string sha256Hash;
1724 std::string sha512Hash;
1725 for (
const auto& hash : target_.hashes()) {
1726 if (hash.type() == Hash::Type::kSha256) {
1727 sha256Hash = hash.HashString();
1728 }
else if (hash.type() == Hash::Type::kSha512) {
1729 sha512Hash = hash.HashString();
1732 std::string filename = (storage.images_path_ / target_.hashes()[0].HashString()).
string();
1734 auto statement = db.prepareStatement<std::string, std::string, std::string>(
1735 "INSERT OR REPLACE INTO target_images (targetname, sha256, sha512, filename) VALUES ( ?, ?, ?, ?);",
1736 target_.filename(), sha256Hash, sha512Hash, target_.hashes()[0].HashString());
1738 if (statement.step() != SQLITE_DONE) {
1739 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1742 boost::filesystem::create_directories(storage.images_path_);
1743 stream_.open(filename);
1744 if (!stream_.good()) {
1745 LOG_ERROR <<
"Could not open image for write: " << storage.images_path_ / target_.filename();
1752 SQLTargetWHandle::wcommit();
1753 }
catch (std::exception& ex) {
1754 LOG_ERROR <<
"Failed to commit to database: " << ex.what();
1756 LOG_ERROR <<
"Failed to commit to database: unknown error";
1760 size_t wfeed(
const uint8_t* buf,
size_t size)
override {
1761 stream_.write(reinterpret_cast<const char*>(buf), static_cast<std::streamsize>(size));
1762 written_size_ += size;
1767 void wcommit()
override {
1773 void wabort() noexcept
override {
1778 if (storage_ !=
nullptr) {
1781 db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_.filename());
1782 if (statement.step() != SQLITE_DONE) {
1783 LOG_ERROR <<
"could not delete " << target_.filename() <<
" from sql storage";
1792 const boost::filesystem::path& image_path,
const uintmax_t& start_from = 0)
1793 : db_path_(db_path), target_(std::move(target)) {
1794 stream_.open(image_path.string(), std::ofstream::out | std::ofstream::app);
1795 if (!stream_.good()) {
1796 LOG_ERROR <<
"Could not open image for write: " << image_path;
1800 written_size_ = start_from;
1802 boost::filesystem::path db_path_;
1804 std::ofstream stream_;
1808 std::unique_ptr<StorageTargetWHandle> SQLStorage::allocateTargetFile(
const Uptane::Target& target) {
1809 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(*
this, target));
1815 : db_path_(storage.dbPath()), target_(std::move(target)), size_(0) {
1818 auto exists = storage.checkTargetFile(target_);
1820 LOG_ERROR <<
"File " << target_.filename() <<
" with expected hash not found in the database!";
1824 size_ = exists->first;
1825 partial_ = size_ < target_.length();
1826 image_path_ = storage.images_path_ / exists->second;
1827 stream_.open(image_path_.string());
1828 if (!stream_.good()) {
1829 LOG_ERROR <<
"Could not open image: " << storage.images_path_ / target_.filename();
1836 uintmax_t rsize()
const override {
return size_; }
1838 size_t rread(uint8_t* buf,
size_t size)
override {
1839 stream_.read(reinterpret_cast<char*>(buf), static_cast<std::streamsize>(size));
1840 return static_cast<size_t>(stream_.gcount());
1843 void rclose() noexcept
override {
1844 if (stream_.is_open()) {
1849 bool isPartial()
const noexcept
override {
return partial_; }
1850 std::unique_ptr<StorageTargetWHandle> toWriteHandle()
override {
1851 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(db_path_, target_, image_path_, size_));
1855 boost::filesystem::path db_path_;
1858 bool partial_{
false};
1859 boost::filesystem::path image_path_;
1860 std::ifstream stream_;
1863 std::unique_ptr<StorageTargetRHandle> SQLStorage::openTargetFile(
const Uptane::Target& target) {
1864 return std_::make_unique<SQLTargetRHandle>(*
this, target);
1867 std::vector<Uptane::Target> SQLStorage::getTargetFiles() {
1870 auto statement = db.prepareStatement<>(
"SELECT targetname, filename, sha256, sha512 FROM target_images;");
1872 std::vector<Uptane::Target> v;
1874 int result = statement.step();
1875 while (
result != SQLITE_DONE) {
1876 if (
result != SQLITE_ROW) {
1877 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1878 throw std::runtime_error(
"Error getting target files");
1881 auto tname = statement.get_result_col_str(0).value();
1882 auto fname = statement.get_result_col_str(1).value();
1883 auto tsize = boost::filesystem::file_size(images_path_ / fname);
1884 auto sha256 = statement.get_result_col_str(2).value();
1885 auto sha512 = statement.get_result_col_str(3).value();
1887 std::vector<Hash> hashes;
1888 if (!sha256.empty()) {
1889 hashes.emplace_back(Hash::Type::kSha256, sha256);
1891 if (!sha512.empty()) {
1892 hashes.emplace_back(Hash::Type::kSha512, sha512);
1894 v.emplace_back(tname, Uptane::EcuMap{}, hashes, tsize);
1896 result = statement.step();
1902 void SQLStorage::removeTargetFile(
const std::string& target_name) {
1905 db.beginTransaction();
1908 db.prepareStatement<std::string>(
"SELECT filename FROM target_images WHERE targetname = ?;", target_name);
1910 if (statement.step() != SQLITE_ROW) {
1911 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1912 throw std::runtime_error(
"Could not find target file");
1915 std::string filename = statement.get_result_col_str(0).value();
1917 statement = db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_name);
1919 if (statement.step() != SQLITE_DONE) {
1920 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1921 throw std::runtime_error(
"Could not remove target file");
1924 boost::filesystem::remove(images_path_ / filename);
1925 }
catch (std::exception& e) {
1926 LOG_ERROR <<
"Could not remove target file";
1930 db.commitTransaction();
1933 void SQLStorage::cleanUp() { boost::filesystem::remove_all(dbPath()); }