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::storeTlsCreds(
const std::string& ca,
const std::string& cert,
const std::string& pkey) {
160 void SQLStorage::storeTlsCa(
const std::string& ca) {
163 if (!db.beginTransaction()) {
164 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
168 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
169 if (statement.step() != SQLITE_ROW) {
170 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
175 if (statement.get_result_col_int(0) != 0) {
176 req =
"UPDATE OR REPLACE tls_creds SET ca_cert = ?;";
178 req =
"INSERT INTO tls_creds(ca_cert) VALUES (?);";
182 if (statement.step() != SQLITE_DONE) {
183 LOG_ERROR <<
"Can't set ca_cert: " << db.errmsg();
187 db.commitTransaction();
190 void SQLStorage::storeTlsCert(
const std::string& cert) {
193 if (!db.beginTransaction()) {
194 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
198 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
199 if (statement.step() != SQLITE_ROW) {
200 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
205 if (statement.get_result_col_int(0) != 0) {
206 req =
"UPDATE OR REPLACE tls_creds SET client_cert = ?;";
208 req =
"INSERT INTO tls_creds(client_cert) VALUES (?);";
212 if (statement.step() != SQLITE_DONE) {
213 LOG_ERROR <<
"Can't set client_cert: " << db.errmsg();
217 db.commitTransaction();
220 void SQLStorage::storeTlsPkey(
const std::string& pkey) {
223 if (!db.beginTransaction()) {
224 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
227 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
228 if (statement.step() != SQLITE_ROW) {
229 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
234 if (statement.get_result_col_int(0) != 0) {
235 req =
"UPDATE OR REPLACE tls_creds SET client_pkey = ?;";
237 req =
"INSERT INTO tls_creds(client_pkey) VALUES (?);";
241 if (statement.step() != SQLITE_DONE) {
242 LOG_ERROR <<
"Can't set client_pkey: " << db.errmsg();
246 db.commitTransaction();
249 bool SQLStorage::loadTlsCreds(std::string* ca, std::string* cert, std::string* pkey) {
252 if (!db.beginTransaction()) {
253 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
256 auto statement = db.prepareStatement(
"SELECT ca_cert, client_cert, client_pkey FROM tls_creds LIMIT 1;");
258 int result = statement.step();
259 if (
result == SQLITE_DONE) {
260 LOG_TRACE <<
"Tls creds not present";
262 }
else if (
result != SQLITE_ROW) {
263 LOG_ERROR <<
"Can't get tls_creds: " << db.errmsg();
267 std::string ca_v, cert_v, pkey_v;
269 ca_v = statement.get_result_col_str(0).value();
270 cert_v = statement.get_result_col_str(1).value();
271 pkey_v = statement.get_result_col_str(2).value();
272 }
catch (
const boost::bad_optional_access&) {
277 *ca = std::move(ca_v);
279 if (cert !=
nullptr) {
280 *cert = std::move(cert_v);
282 if (pkey !=
nullptr) {
283 *pkey = std::move(pkey_v);
286 db.commitTransaction();
291 void SQLStorage::clearTlsCreds() {
294 if (db.exec(
"DELETE FROM tls_creds;",
nullptr,
nullptr) != SQLITE_OK) {
295 LOG_ERROR <<
"Can't clear tls_creds: " << db.errmsg();
300 bool SQLStorage::loadTlsCa(std::string* ca) {
303 auto statement = db.prepareStatement(
"SELECT ca_cert FROM tls_creds LIMIT 1;");
305 int result = statement.step();
306 if (
result == SQLITE_DONE) {
307 LOG_TRACE <<
"ca_cert not present";
309 }
else if (
result != SQLITE_ROW) {
310 LOG_ERROR <<
"Can't get ca_cert: " << db.errmsg();
314 auto ca_r = statement.get_result_col_str(0);
315 if (ca_r == boost::none) {
320 *ca = std::move(ca_r.value());
326 bool SQLStorage::loadTlsCert(std::string* cert) {
329 auto statement = db.prepareStatement(
"SELECT client_cert FROM tls_creds LIMIT 1;");
331 int result = statement.step();
332 if (
result == SQLITE_DONE) {
333 LOG_TRACE <<
"client_cert not present in db";
335 }
else if (
result != SQLITE_ROW) {
336 LOG_ERROR <<
"Can't get client_cert: " << db.errmsg();
340 auto cert_r = statement.get_result_col_str(0);
341 if (cert_r == boost::none) {
345 if (cert !=
nullptr) {
346 *cert = std::move(cert_r.value());
352 bool SQLStorage::loadTlsPkey(std::string* pkey) {
355 auto statement = db.prepareStatement(
"SELECT client_pkey FROM tls_creds LIMIT 1;");
357 int result = statement.step();
358 if (
result == SQLITE_DONE) {
359 LOG_TRACE <<
"client_pkey not present in db";
361 }
else if (
result != SQLITE_ROW) {
362 LOG_ERROR <<
"Can't get client_pkey: " << db.errmsg();
366 auto pkey_r = statement.get_result_col_str(0);
367 if (pkey_r == boost::none) {
371 if (pkey !=
nullptr) {
372 *pkey = std::move(pkey_r.value());
381 if (!db.beginTransaction()) {
382 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
387 db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
388 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
390 if (del_statement.step() != SQLITE_DONE) {
391 LOG_ERROR <<
"Can't clear root metadata: " << db.errmsg();
395 auto ins_statement = db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
397 Uptane::Role::Root().ToInt(), version.version());
399 if (ins_statement.step() != SQLITE_DONE) {
400 LOG_ERROR <<
"Can't add metadata: " << db.errmsg();
404 db.commitTransaction();
410 if (!db.beginTransaction()) {
411 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
415 auto del_statement = db.prepareStatement<int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=?);",
416 static_cast<int>(repo), role.ToInt());
418 if (del_statement.step() != SQLITE_DONE) {
419 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
424 db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
SQLBlob(
data),
427 if (ins_statement.step() != SQLITE_DONE) {
428 LOG_ERROR <<
"Can't add metadata: " << db.errmsg();
432 db.commitTransaction();
439 if (version.version() < 0) {
440 auto statement = db.prepareStatement<int,
int>(
441 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;", static_cast<int>(repo),
442 Uptane::Role::Root().ToInt());
443 int result = statement.step();
445 if (
result == SQLITE_DONE) {
446 LOG_TRACE <<
"Meta not present";
448 }
else if (
result != SQLITE_ROW) {
449 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
452 if (
data !=
nullptr) {
453 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
457 db.prepareStatement<int, int,
int>(
"SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
458 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
460 int result = statement.step();
462 if (
result == SQLITE_DONE) {
463 LOG_TRACE <<
"Meta not present";
465 }
else if (
result != SQLITE_ROW) {
466 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
470 const auto blob = reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0));
471 if (blob ==
nullptr) {
472 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
476 if (
data !=
nullptr) {
477 *
data = std::string(blob);
487 auto statement = db.prepareStatement<int,
int>(
488 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;", static_cast<int>(repo),
490 int result = statement.step();
492 if (
result == SQLITE_DONE) {
493 LOG_TRACE <<
"Meta not present";
495 }
else if (
result != SQLITE_ROW) {
496 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
499 if (
data !=
nullptr) {
500 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
510 db.prepareStatement<
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type != 0);", static_cast<int>(repo));
512 if (del_statement.step() != SQLITE_DONE) {
513 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
517 void SQLStorage::clearMetadata() {
520 if (db.exec(
"DELETE FROM meta;",
nullptr,
nullptr) != SQLITE_OK) {
521 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
526 void SQLStorage::storeDelegation(
const std::string&
data,
const Uptane::Role role) {
529 if (!db.beginTransaction()) {
530 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
534 auto statement = db.prepareStatement<
SQLBlob, std::string>(
"INSERT OR REPLACE INTO delegations VALUES (?, ?);",
537 if (statement.step() != SQLITE_DONE) {
538 LOG_ERROR <<
"Can't add delegation metadata: " << db.errmsg();
542 db.commitTransaction();
545 bool SQLStorage::loadDelegation(std::string*
data,
const Uptane::Role role) {
549 db.prepareStatement<std::string>(
"SELECT meta FROM delegations WHERE role_name=? LIMIT 1;", role.ToString());
550 int result = statement.step();
552 if (
result == SQLITE_DONE) {
553 LOG_TRACE <<
"Delegations metadata not present";
555 }
else if (
result != SQLITE_ROW) {
556 LOG_ERROR <<
"Can't get delegations metadata: " << db.errmsg();
559 if (
data !=
nullptr) {
560 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
566 bool SQLStorage::loadAllDelegations(std::vector<std::pair<Uptane::Role, std::string>>&
data)
const {
572 auto statement = db.prepareStatement(
"SELECT meta, role_name FROM delegations;");
573 auto statement_state = statement.step();
575 if (statement_state == SQLITE_DONE) {
576 LOG_TRACE <<
"Delegations metadata are not present";
578 }
else if (statement_state != SQLITE_ROW) {
579 LOG_ERROR <<
"Can't get delegations metadata: " << db.errmsg();
584 data.emplace_back(Uptane::Role::Delegation(statement.get_result_col_str(1).value()),
585 statement.get_result_col_blob(0).value());
586 }
while ((statement_state = statement.step()) == SQLITE_ROW);
589 }
catch (
const std::exception& exc) {
590 LOG_ERROR <<
"Failed to fetch records from `delegations` table: " << exc.what();
596 void SQLStorage::deleteDelegation(
const Uptane::Role role) {
599 auto statement = db.prepareStatement<std::string>(
"DELETE FROM delegations WHERE role_name=?;", role.ToString());
603 void SQLStorage::clearDelegations() {
606 if (db.exec(
"DELETE FROM delegations;",
nullptr,
nullptr) != SQLITE_OK) {
607 LOG_ERROR <<
"Can't clear delegations metadata: " << db.errmsg();
611 void SQLStorage::storeDeviceId(
const std::string& device_id) {
614 auto statement = db.prepareStatement<std::string>(
615 "INSERT OR REPLACE INTO device_info(unique_mark,device_id,is_registered) VALUES(0,?,0);", device_id);
616 if (statement.step() != SQLITE_DONE) {
617 LOG_ERROR <<
"Can't set device ID: " << db.errmsg();
622 bool SQLStorage::loadDeviceId(std::string* device_id) {
625 auto statement = db.prepareStatement(
"SELECT device_id FROM device_info LIMIT 1;");
627 int result = statement.step();
628 if (
result == SQLITE_DONE) {
629 LOG_TRACE <<
"device_id not present in db";
631 }
else if (
result != SQLITE_ROW) {
632 LOG_ERROR <<
"Can't get device ID: " << db.errmsg();
636 auto did = statement.get_result_col_str(0);
637 if (did == boost::none) {
638 LOG_ERROR <<
"Empty device ID" << db.errmsg();
642 if (device_id !=
nullptr) {
643 *device_id = std::move(did.value());
649 void SQLStorage::clearDeviceId() {
652 if (db.exec(
"DELETE FROM device_info;",
nullptr,
nullptr) != SQLITE_OK) {
653 LOG_ERROR <<
"Can't clear device ID: " << db.errmsg();
658 void SQLStorage::storeEcuRegistered() {
661 if (!db.beginTransaction()) {
662 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
666 auto statement = db.prepareStatement(
"SELECT count(*) FROM device_info;");
667 if (statement.step() != SQLITE_ROW) {
668 throw std::runtime_error(
"Could not get device_info count");
670 if (statement.get_result_col_int(0) != 1) {
671 throw std::runtime_error(
"Cannot set ecu registered if no device_info set");
674 std::string req =
"UPDATE device_info SET is_registered = 1";
675 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
676 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
680 db.commitTransaction();
683 bool SQLStorage::loadEcuRegistered() {
686 auto statement = db.prepareStatement(
"SELECT is_registered FROM device_info LIMIT 1;");
688 int result = statement.step();
689 if (
result == SQLITE_DONE) {
691 }
else if (
result != SQLITE_ROW) {
692 LOG_ERROR <<
"Can't get is_registered in device_info " << db.errmsg();
696 return statement.get_result_col_int(0) != 0;
699 void SQLStorage::clearEcuRegistered() {
703 std::string req =
"UPDATE device_info SET is_registered = 0";
704 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
705 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
710 void SQLStorage::storeNeedReboot() {
713 auto statement = db.prepareStatement<
int>(
"INSERT OR REPLACE INTO need_reboot(unique_mark,flag) VALUES(0,?);", 1);
714 if (statement.step() != SQLITE_DONE) {
715 LOG_ERROR <<
"Can't set need_reboot: " << db.errmsg();
720 bool SQLStorage::loadNeedReboot(
bool* need_reboot) {
723 auto statement = db.prepareStatement(
"SELECT flag FROM need_reboot LIMIT 1;");
725 int result = statement.step();
726 if (
result == SQLITE_DONE) {
727 if (need_reboot !=
nullptr) {
728 *need_reboot =
false;
731 }
else if (
result != SQLITE_ROW) {
732 LOG_ERROR <<
"Can't get need_reboot: " << db.errmsg();
736 auto flag = static_cast<bool>(statement.get_result_col_int(0));
737 if (need_reboot !=
nullptr) {
744 void SQLStorage::clearNeedReboot() {
747 if (db.exec(
"DELETE FROM need_reboot;",
nullptr,
nullptr) != SQLITE_OK) {
748 LOG_ERROR <<
"Can't clear need_reboot: " << db.errmsg();
753 void SQLStorage::storeEcuSerials(
const EcuSerials& serials) {
754 if (serials.size() >= 1) {
757 if (!db.beginTransaction()) {
758 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
762 if (db.exec(
"DELETE FROM ecu_serials;",
nullptr,
nullptr) != SQLITE_OK) {
763 LOG_ERROR <<
"Can't clear ecu_serials: " << db.errmsg();
768 std::string serial = serials[0].first.ToString();
769 std::string hwid = serials[0].second.ToString();
771 auto statement = db.prepareStatement<std::string, std::string>(
772 "INSERT INTO ecu_serials(id, serial,hardware_id,is_primary) VALUES (0, ?,?,1);", serial, hwid);
773 if (statement.step() != SQLITE_DONE) {
774 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
779 auto statement_ivupdate = db.prepareStatement<std::string>(
780 "UPDATE installed_versions SET ecu_serial = ? WHERE ecu_serial = '';", serial);
782 if (statement_ivupdate.step() != SQLITE_DONE) {
783 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
788 for (
auto it = serials.cbegin() + 1; it != serials.cend(); it++) {
789 auto statement = db.prepareStatement<int64_t, std::string, std::string>(
790 "INSERT INTO ecu_serials(id,serial,hardware_id) VALUES (?,?,?);", it - serials.cbegin(), it->first.ToString(),
791 it->second.ToString());
793 if (statement.step() != SQLITE_DONE) {
794 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
799 db.commitTransaction();
803 bool SQLStorage::loadEcuSerials(EcuSerials* serials) {
807 auto statement = db.prepareStatement(
"SELECT serial, hardware_id FROM ecu_serials ORDER BY id;");
810 EcuSerials new_serials;
812 while ((statement_state = statement.step()) == SQLITE_ROW) {
814 new_serials.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
817 }
catch (
const boost::bad_optional_access&) {
822 if (statement_state != SQLITE_DONE) {
823 LOG_ERROR <<
"Can't get ecu_serials: " << db.errmsg();
827 if (serials !=
nullptr) {
828 *serials = std::move(new_serials);
834 void SQLStorage::clearEcuSerials() {
837 if (db.exec(
"DELETE FROM ecu_serials;",
nullptr,
nullptr) != SQLITE_OK) {
838 LOG_ERROR <<
"Can't clear ecu_serials: " << db.errmsg();
843 void SQLStorage::storeMisconfiguredEcus(
const std::vector<MisconfiguredEcu>& ecus) {
844 if (ecus.size() >= 1) {
847 if (!db.beginTransaction()) {
848 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
852 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
853 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
857 std::vector<MisconfiguredEcu>::const_iterator it;
858 for (it = ecus.begin(); it != ecus.end(); it++) {
859 auto statement = db.prepareStatement<std::string, std::string,
int>(
860 "INSERT INTO misconfigured_ecus VALUES (?,?,?);", it->serial.ToString(), it->hardware_id.ToString(),
861 static_cast<int>(it->state));
863 if (statement.step() != SQLITE_DONE) {
864 LOG_ERROR <<
"Can't set misconfigured_ecus: " << db.errmsg();
869 db.commitTransaction();
873 bool SQLStorage::loadMisconfiguredEcus(std::vector<MisconfiguredEcu>* ecus) {
876 auto statement = db.prepareStatement(
"SELECT serial, hardware_id, state FROM misconfigured_ecus;");
879 std::vector<MisconfiguredEcu> new_ecus;
881 while ((statement_state = statement.step()) == SQLITE_ROW) {
883 new_ecus.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
885 static_cast<EcuState>(statement.get_result_col_int(2)));
887 }
catch (
const boost::bad_optional_access&) {
892 if (statement_state != SQLITE_DONE) {
893 LOG_ERROR <<
"Can't get misconfigured_ecus: " << db.errmsg();
897 if (ecus !=
nullptr) {
898 *ecus = std::move(new_ecus);
904 void SQLStorage::clearMisconfiguredEcus() {
907 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
908 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
913 void SQLStorage::saveInstalledVersion(
const std::string& ecu_serial,
const Uptane::Target& target,
914 InstalledVersionUpdateMode update_mode) {
917 if (!db.beginTransaction()) {
918 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
925 std::string ecu_serial_real = ecu_serial;
926 if (ecu_serial_real.empty()) {
927 auto statement = db.prepareStatement(
"SELECT serial FROM ecu_serials WHERE is_primary = 1;");
928 if (statement.step() == SQLITE_ROW) {
929 ecu_serial_real = statement.get_result_col_str(0).value();
931 LOG_WARNING <<
"Could not find primary ecu serial, set to lazy init mode";
935 std::string hashes_encoded = Uptane::Hash::encodeVector(target.hashes());
938 boost::optional<int64_t> old_id;
939 bool old_was_installed =
false;
941 auto statement = db.prepareStatement<std::string>(
942 "SELECT id, sha256, name, was_installed FROM installed_versions WHERE ecu_serial = ? ORDER BY id DESC "
946 if (statement.step() == SQLITE_ROW) {
947 int64_t rid = statement.get_result_col_int(0);
948 std::string rsha256 = statement.get_result_col_str(1).value_or(
"");
949 std::string rname = statement.get_result_col_str(2).value_or(
"");
950 bool rwasi = statement.get_result_col_int(3) == 1;
952 if (rsha256 == target.sha256Hash() && rname == target.filename()) {
954 old_was_installed = rwasi;
959 if (update_mode == InstalledVersionUpdateMode::kCurrent) {
961 auto statement = db.prepareStatement<std::string>(
962 "UPDATE installed_versions SET is_current = 0, is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
963 if (statement.step() != SQLITE_DONE) {
964 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
967 }
else if (update_mode == InstalledVersionUpdateMode::kPending) {
969 auto statement = db.prepareStatement<std::string>(
970 "UPDATE installed_versions SET is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
971 if (statement.step() != SQLITE_DONE) {
972 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
978 auto statement = db.prepareStatement<std::string, int, int, int64_t>(
979 "UPDATE installed_versions SET correlation_id = ?, is_current = ?, is_pending = ?, was_installed = ? WHERE id "
981 target.correlation_id(), static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
982 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
983 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent || old_was_installed), old_id.value());
985 if (statement.step() != SQLITE_DONE) {
986 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
990 std::string custom = Utils::jsonToCanonicalStr(target.custom_data());
991 auto statement = db.prepareStatement<std::string, std::string, std::string, std::string, int64_t, std::string,
992 std::string, int,
int>(
993 "INSERT INTO installed_versions(ecu_serial, sha256, name, hashes, length, custom_meta, correlation_id, "
994 "is_current, is_pending, was_installed) VALUES (?,?,?,?,?,?,?,?,?,?);",
995 ecu_serial_real, target.sha256Hash(), target.filename(), hashes_encoded, static_cast<int64_t>(target.length()),
996 custom, target.correlation_id(), static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
997 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
998 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent));
1000 if (statement.step() != SQLITE_DONE) {
1001 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1006 db.commitTransaction();
1009 static void loadEcuMap(
SQLite3Guard& db, std::string& ecu_serial, Uptane::EcuMap& ecu_map) {
1010 if (ecu_serial.empty()) {
1011 auto statement = db.prepareStatement(
"SELECT serial FROM ecu_serials WHERE is_primary = 1;");
1012 if (statement.step() == SQLITE_ROW) {
1013 ecu_serial = statement.get_result_col_str(0).value();
1015 LOG_WARNING <<
"Could not find primary ecu serial, defaulting to empty serial: " << db.errmsg();
1021 db.prepareStatement<std::string>(
"SELECT hardware_id FROM ecu_serials WHERE serial = ?;", ecu_serial);
1022 if (statement.step() == SQLITE_ROW) {
1026 LOG_WARNING <<
"Could not find hardware_id for serial " << ecu_serial <<
": " << db.errmsg();
1031 bool SQLStorage::loadInstallationLog(
const std::string& ecu_serial, std::vector<Uptane::Target>* log,
1032 bool only_installed) {
1035 std::string ecu_serial_real = ecu_serial;
1036 Uptane::EcuMap ecu_map;
1037 loadEcuMap(db, ecu_serial_real, ecu_map);
1040 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1041 "ecu_serial = ? ORDER BY id;";
1042 if (only_installed) {
1044 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1045 "ecu_serial = ? AND was_installed = 1 ORDER BY id;";
1048 auto statement = db.prepareStatement<std::string>(query, ecu_serial_real);
1049 int statement_state;
1051 std::vector<Uptane::Target> new_log;
1052 std::map<int64_t, size_t> ids_map;
1054 while ((statement_state = statement.step()) == SQLITE_ROW) {
1056 auto id = statement.get_result_col_int(0);
1057 auto sha256 = statement.get_result_col_str(1).value();
1058 auto filename = statement.get_result_col_str(2).value();
1059 auto hashes_str = statement.get_result_col_str(3).value();
1060 auto length = statement.get_result_col_int(4);
1061 auto correlation_id = statement.get_result_col_str(5).value();
1062 auto custom_str = statement.get_result_col_str(6).value();
1066 std::vector<Uptane::Hash> hashes = Uptane::Hash::decodeVector(hashes_str);
1068 auto find_sha256 = std::find_if(hashes.cbegin(), hashes.cend(),
1069 [](
const Uptane::Hash& h) {
return h.type() == Uptane::Hash::Type::kSha256; });
1070 if (find_sha256 == hashes.cend()) {
1071 LOG_WARNING <<
"No sha256 in hashes list";
1072 hashes.emplace_back(Uptane::Hash::Type::kSha256, sha256);
1075 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1076 if (!custom_str.empty()) {
1077 std::istringstream css(custom_str);
1080 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom,
nullptr)) {
1081 t.updateCustom(custom);
1083 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1086 new_log.emplace_back(t);
1090 }
catch (
const boost::bad_optional_access&) {
1091 LOG_ERROR <<
"Incompleted installed version, keeping old one";
1096 if (statement_state != SQLITE_DONE) {
1097 LOG_ERROR <<
"Can't get installed_versions: " << db.errmsg();
1101 if (log ==
nullptr) {
1105 *log = std::move(new_log);
1110 bool SQLStorage::loadInstalledVersions(
const std::string& ecu_serial, boost::optional<Uptane::Target>* current_version,
1111 boost::optional<Uptane::Target>* pending_version) {
1114 std::string ecu_serial_real = ecu_serial;
1115 Uptane::EcuMap ecu_map;
1116 loadEcuMap(db, ecu_serial_real, ecu_map);
1119 auto sha256 = statement.get_result_col_str(0).value();
1120 auto filename = statement.get_result_col_str(1).value();
1121 auto hashes_str = statement.get_result_col_str(2).value();
1122 auto length = statement.get_result_col_int(3);
1123 auto correlation_id = statement.get_result_col_str(4).value();
1124 auto custom_str = statement.get_result_col_str(5).value();
1128 std::vector<Uptane::Hash> hashes = Uptane::Hash::decodeVector(hashes_str);
1130 auto find_sha256 = std::find_if(hashes.cbegin(), hashes.cend(),
1131 [](
const Uptane::Hash& h) {
return h.type() == Uptane::Hash::Type::kSha256; });
1132 if (find_sha256 == hashes.cend()) {
1133 LOG_WARNING <<
"No sha256 in hashes list";
1134 hashes.emplace_back(Uptane::Hash::Type::kSha256, sha256);
1136 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1137 if (!custom_str.empty()) {
1138 std::istringstream css(custom_str);
1141 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom, &errs)) {
1142 t.updateCustom(custom);
1144 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1151 if (current_version !=
nullptr) {
1152 auto statement = db.prepareStatement<std::string>(
1153 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1154 "ecu_serial = ? AND is_current = 1 LIMIT 1;",
1157 if (statement.step() == SQLITE_ROW) {
1159 *current_version = read_target(statement);
1160 }
catch (
const boost::bad_optional_access&) {
1161 LOG_ERROR <<
"Could not read current installed version";
1165 LOG_TRACE <<
"Cannot get current installed version: " << db.errmsg();
1166 *current_version = boost::none;
1170 if (pending_version !=
nullptr) {
1171 auto statement = db.prepareStatement<std::string>(
1172 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1173 "ecu_serial = ? AND is_pending = 1 LIMIT 1;",
1176 if (statement.step() == SQLITE_ROW) {
1178 *pending_version = read_target(statement);
1179 }
catch (
const boost::bad_optional_access&) {
1180 LOG_ERROR <<
"Could not read pending installed version";
1184 LOG_TRACE <<
"Cannot get pending installed version: " << db.errmsg();
1185 *pending_version = boost::none;
1192 bool SQLStorage::hasPendingInstall() {
1195 auto statement = db.prepareStatement(
"SELECT count(*) FROM installed_versions where is_pending = 1");
1196 if (statement.step() != SQLITE_ROW) {
1197 LOG_ERROR <<
"Can't get tables count: " << db.errmsg();
1198 throw std::runtime_error(
"Could not count pending installations");
1201 return statement.get_result_col_int(0) > 0;
1204 void SQLStorage::getPendingEcus(std::vector<std::pair<Uptane::EcuSerial, Uptane::Hash>>* pendingEcus) {
1207 auto statement = db.prepareStatement(
"SELECT ecu_serial, sha256 FROM installed_versions where is_pending = 1");
1208 int statement_result = statement.step();
1209 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1210 throw std::runtime_error(
"Failed to get ECUs with a pending target installation: " + db.errmsg());
1213 std::vector<std::pair<Uptane::EcuSerial, Uptane::Hash>> ecu_res;
1215 if (statement_result == SQLITE_DONE) {
1220 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1221 std::string ecu_serial = statement.get_result_col_str(0).value();
1222 std::string hash = statement.get_result_col_str(1).value();
1223 ecu_res.emplace_back(
1227 if (pendingEcus !=
nullptr) {
1228 *pendingEcus = std::move(ecu_res);
1232 void SQLStorage::clearInstalledVersions() {
1235 if (db.exec(
"DELETE FROM installed_versions;",
nullptr,
nullptr) != SQLITE_OK) {
1236 LOG_ERROR <<
"Can't clear installed_versions: " << db.errmsg();
1245 auto statement = db.prepareStatement<std::string, int, std::string, std::string>(
1246 "INSERT OR REPLACE INTO ecu_installation_results (ecu_serial, success, result_code, description) VALUES "
1248 ecu_serial.ToString(), static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description);
1249 if (statement.step() != SQLITE_DONE) {
1250 LOG_ERROR <<
"Can't set ecu installation result: " << db.errmsg();
1255 bool SQLStorage::loadEcuInstallationResults(
1256 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>>* results) {
1259 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_res;
1262 auto statement = db.prepareStatement(
1263 "SELECT ecu_serial, success, result_code, description FROM ecu_installation_results INNER JOIN ecu_serials ON "
1264 "ecu_serials.serial = ecu_serial ORDER BY ecu_serials.id;");
1265 int statement_result = statement.step();
1266 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1267 LOG_ERROR <<
"Can't get ecu_installation_results: " << db.errmsg();
1271 if (statement_result == SQLITE_DONE) {
1276 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1278 std::string ecu_serial = statement.get_result_col_str(0).value();
1279 auto success = static_cast<bool>(statement.get_result_col_int(1));
1280 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(2).value());
1281 std::string description = statement.get_result_col_str(3).value();
1284 }
catch (
const boost::bad_optional_access&) {
1289 if (results !=
nullptr) {
1290 *results = std::move(ecu_res);
1297 const std::string& correlation_id) {
1300 auto statement = db.prepareStatement<int, std::string, std::string, std::string, std::string>(
1301 "INSERT OR REPLACE INTO device_installation_result (unique_mark, success, result_code, description, raw_report, "
1303 "VALUES (0,?,?,?,?,?);",
1304 static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description, raw_report, correlation_id);
1305 if (statement.step() != SQLITE_DONE) {
1306 LOG_ERROR <<
"Can't set device installation result: " << db.errmsg();
1312 std::string* correlation_id) {
1316 std::string raw_report_res;
1317 std::string corrid_res;
1319 auto statement = db.prepareStatement(
1320 "SELECT success, result_code, description, raw_report, correlation_id FROM device_installation_result;");
1321 int statement_result = statement.step();
1322 if (statement_result == SQLITE_DONE) {
1323 LOG_TRACE <<
"No device installation result in db";
1325 }
else if (statement_result != SQLITE_ROW) {
1326 LOG_ERROR <<
"Can't get device_installation_result: " << db.errmsg();
1331 auto success = static_cast<bool>(statement.get_result_col_int(0));
1332 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(1).value());
1333 std::string description = statement.get_result_col_str(2).value();
1334 raw_report_res = statement.get_result_col_str(3).value();
1335 corrid_res = statement.get_result_col_str(4).value();
1338 }
catch (
const boost::bad_optional_access&) {
1343 *
result = std::move(dev_res);
1346 if (raw_report !=
nullptr) {
1347 *raw_report = std::move(raw_report_res);
1350 if (correlation_id !=
nullptr) {
1351 *correlation_id = std::move(corrid_res);
1357 void SQLStorage::saveEcuReportCounter(
const Uptane::EcuSerial& ecu_serial,
const int64_t counter) {
1360 auto statement = db.prepareStatement<std::string, int64_t>(
1361 "INSERT OR REPLACE INTO ecu_report_counter (ecu_serial, counter) VALUES "
1363 ecu_serial.ToString(), counter);
1364 if (statement.step() != SQLITE_DONE) {
1365 LOG_ERROR <<
"Can't set ecu counter: " << db.errmsg();
1370 bool SQLStorage::loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results) {
1373 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
1376 auto statement = db.prepareStatement(
1377 "SELECT ecu_serial, counter FROM ecu_report_counter INNER JOIN ecu_serials ON "
1378 "ecu_serials.serial = ecu_serial ORDER BY ecu_serials.id;");
1379 int statement_result = statement.step();
1380 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1381 LOG_ERROR <<
"Can't get ecu_report_counter: " << db.errmsg();
1385 if (statement_result == SQLITE_DONE) {
1390 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1392 std::string ecu_serial = statement.get_result_col_str(0).value();
1393 int64_t counter = statement.get_result_col_int(1);
1396 }
catch (
const boost::bad_optional_access&) {
1401 if (results !=
nullptr) {
1402 *results = std::move(ecu_cnt);
1408 void SQLStorage::clearInstallationResults() {
1410 if (!db.beginTransaction()) {
1411 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
1415 if (db.exec(
"DELETE FROM device_installation_result;",
nullptr,
nullptr) != SQLITE_OK) {
1416 LOG_ERROR <<
"Can't clear device_installation_result: " << db.errmsg();
1420 if (db.exec(
"DELETE FROM ecu_installation_results;",
nullptr,
nullptr) != SQLITE_OK) {
1421 LOG_ERROR <<
"Can't clear ecu_installation_results: " << db.errmsg();
1425 db.commitTransaction();
1428 bool SQLStorage::checkAvailableDiskSpace(
const uint64_t required_bytes)
const {
1429 struct statvfs stvfsbuf {};
1430 const int stat_res = statvfs(dbPath().c_str(), &stvfsbuf);
1432 LOG_WARNING <<
"Unable to read filesystem statistics: error code " << stat_res;
1435 const uint64_t available_bytes = (stvfsbuf.f_bsize * stvfsbuf.f_bavail);
1436 const uint64_t reserved_bytes = 1 << 20;
1438 if (required_bytes + reserved_bytes < available_bytes) {
1441 LOG_ERROR <<
"Insufficient disk space available to download target! Required: " << required_bytes
1442 <<
", available: " << available_bytes <<
", reserved: " << reserved_bytes;
1447 boost::optional<std::pair<size_t, std::string>> SQLStorage::checkTargetFile(
const Uptane::Target& target)
const {
1450 auto statement = db.prepareStatement<std::string>(
1451 "SELECT real_size, sha256, sha512, filename FROM target_images WHERE targetname = ?;", target.filename());
1453 int statement_state;
1454 while ((statement_state = statement.step()) == SQLITE_ROW) {
1455 auto sha256 = statement.get_result_col_str(1);
1456 auto sha512 = statement.get_result_col_str(2);
1457 if ((*sha256).empty() && (*sha512).empty()) {
1459 LOG_WARNING <<
"Image without checksum: " << target.filename();
1462 bool sha256_match =
false;
1463 bool sha512_match =
false;
1464 if (!(*sha256).empty()) {
1465 if (target.MatchHash(
Uptane::Hash(Uptane::Hash::Type::kSha256, *sha256))) {
1466 sha256_match =
true;
1470 if (!(*sha512).empty()) {
1471 if (target.MatchHash(
Uptane::Hash(Uptane::Hash::Type::kSha512, *sha512))) {
1472 sha512_match =
true;
1475 if (((*sha256).empty() || sha256_match) && ((*sha512).empty() || sha512_match)) {
1476 if (boost::filesystem::exists(images_path_ / *statement.get_result_col_str(3))) {
1477 return {{static_cast<size_t>(statement.get_result_col_int(0)), *statement.get_result_col_str(3)}};
1484 if (statement_state == SQLITE_DONE) {
1485 LOG_INFO <<
"No file '" + target.filename() <<
"' with matched hash in the database";
1488 assert(statement_state != SQLITE_ROW);
1489 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1497 : db_(storage.dbPath()), target_(std::move(target)) {
1500 std::string sha256Hash;
1501 std::string sha512Hash;
1502 for (
const auto& hash : target_.hashes()) {
1503 if (hash.type() == Uptane::Hash::Type::kSha256) {
1504 sha256Hash = hash.HashString();
1505 }
else if (hash.type() == Uptane::Hash::Type::kSha512) {
1506 sha512Hash = hash.HashString();
1509 std::string filename = (storage.images_path_ / target_.hashes()[0].HashString()).
string();
1510 auto statement = db_.prepareStatement<std::string, std::string, std::string>(
1511 "INSERT OR REPLACE INTO target_images (targetname, sha256, sha512, filename) VALUES ( ?, ?, ?, ?);",
1512 target_.filename(), sha256Hash, sha512Hash, target_.hashes()[0].HashString());
1514 if (statement.step() != SQLITE_DONE) {
1515 LOG_ERROR <<
"Statement step failure: " << db_.errmsg();
1518 boost::filesystem::create_directories(storage.images_path_);
1519 stream_.open(filename);
1520 if (!stream_.good()) {
1521 LOG_ERROR <<
"Could not open image for write: " << storage.images_path_ / target_.filename();
1528 SQLTargetWHandle::wcommit();
1529 }
catch (std::exception& ex) {
1530 LOG_ERROR <<
"Failed to commit to database: " << ex.what();
1532 LOG_ERROR <<
"Failed to commit to database: unknown error";
1536 size_t wfeed(
const uint8_t* buf,
size_t size)
override {
1537 stream_.write(reinterpret_cast<const char*>(buf), static_cast<std::streamsize>(size));
1538 written_size_ += size;
1543 void wcommit()
override {
1547 db_.prepareStatement<int64_t, std::string>(
"UPDATE target_images SET real_size = ? WHERE targetname = ?;",
1548 static_cast<int64_t>(written_size_), target_.filename());
1550 int err = statement.step();
1551 if (err != SQLITE_DONE) {
1552 LOG_ERROR <<
"Could not save size in db: " << db_.errmsg();
1558 void wabort() noexcept
override {
1562 if (sqlite3_changes(db_.get()) > 0) {
1564 db_.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_.filename());
1565 if (statement.step() != SQLITE_DONE) {
1566 LOG_ERROR <<
"could not delete " << target_.filename() <<
" from sql storage";
1575 const boost::filesystem::path& image_path,
const size_t& start_from = 0)
1576 : db_(db_path), target_(std::move(target)) {
1577 if (db_.get_rc() != SQLITE_OK) {
1578 LOG_ERROR <<
"Can't open database: " << db_.errmsg();
1581 stream_.open(image_path.string(), std::ofstream::out | std::ofstream::app);
1582 if (!stream_.good()) {
1583 LOG_ERROR <<
"Could not open image for write: " << image_path;
1587 written_size_ = start_from;
1591 std::ofstream stream_;
1594 std::unique_ptr<StorageTargetWHandle> SQLStorage::allocateTargetFile(
bool from_director,
const Uptane::Target& target) {
1595 (void)from_director;
1596 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(*
this, target));
1602 : db_path_(storage.dbPath()), db_(db_path_), target_(std::move(target)), size_(0) {
1605 auto exists = storage.checkTargetFile(target_);
1610 size_ = exists->first;
1611 partial_ = size_ < target_.length();
1612 image_path_ = storage.images_path_ / exists->second;
1613 stream_.open(image_path_.string());
1614 if (!stream_.good()) {
1615 LOG_ERROR <<
"Could not open image: " << storage.images_path_ / target_.filename();
1622 size_t rsize()
const override {
return size_; }
1624 size_t rread(uint8_t* buf,
size_t size)
override {
1625 stream_.read(reinterpret_cast<char*>(buf), static_cast<std::streamsize>(size));
1626 return static_cast<size_t>(stream_.gcount());
1629 void rclose() noexcept
override {
1630 if (stream_.is_open()) {
1635 bool isPartial()
const noexcept
override {
return partial_; }
1636 std::unique_ptr<StorageTargetWHandle> toWriteHandle()
override {
1637 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(db_path_, target_, image_path_, size_));
1641 boost::filesystem::path db_path_;
1645 bool partial_{
false};
1646 boost::filesystem::path image_path_;
1647 std::ifstream stream_;
1650 std::unique_ptr<StorageTargetRHandle> SQLStorage::openTargetFile(
const Uptane::Target& target) {
1651 return std_::make_unique<SQLTargetRHandle>(*
this, target);
1654 std::vector<Uptane::Target> SQLStorage::getTargetFiles() {
1657 auto statement = db.prepareStatement<>(
"SELECT targetname, real_size, sha256, sha512 FROM target_images;");
1659 std::vector<Uptane::Target> v;
1661 int result = statement.step();
1662 while (
result != SQLITE_DONE) {
1663 if (
result != SQLITE_ROW) {
1664 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1665 throw std::runtime_error(
"Error getting target files");
1668 auto tname = statement.get_result_col_str(0).value();
1669 auto tsize = statement.get_result_col_int(1);
1670 auto sha256 = statement.get_result_col_str(2).value();
1671 auto sha512 = statement.get_result_col_str(3).value();
1673 std::vector<Uptane::Hash> hashes;
1674 if (!sha256.empty()) {
1675 hashes.emplace_back(Uptane::Hash::Type::kSha256, sha256);
1677 if (!sha512.empty()) {
1678 hashes.emplace_back(Uptane::Hash::Type::kSha512, sha512);
1680 v.emplace_back(tname, Uptane::EcuMap{}, hashes, static_cast<size_t>(tsize));
1682 result = statement.step();
1688 void SQLStorage::removeTargetFile(
const std::string& target_name) {
1691 if (!db.beginTransaction()) {
1692 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
1697 db.prepareStatement<std::string>(
"SELECT filename FROM target_images WHERE targetname = ?;", target_name);
1699 if (statement.step() != SQLITE_ROW) {
1700 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1701 throw std::runtime_error(
"Could not find target file");
1704 std::string filename = statement.get_result_col_str(0).value();
1706 statement = db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_name);
1708 if (statement.step() != SQLITE_DONE) {
1709 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1710 throw std::runtime_error(
"Could not remove target file");
1713 boost::filesystem::remove(images_path_ / filename);
1714 }
catch (std::exception& e) {
1715 LOG_ERROR <<
"Could not remove target file";
1719 db.commitTransaction();
1722 void SQLStorage::cleanUp() { boost::filesystem::remove_all(dbPath()); }