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)
const {
87 return loadPrimaryPublic(public_key) && loadPrimaryPrivate(private_key);
90 bool SQLStorage::loadPrimaryPublic(std::string* public_key)
const {
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)
const {
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 throw std::runtime_error(db.errmsg().insert(0,
"Can't get count of secondary_ecus table: "));
170 if (statement.get_result_col_int(0) != 0) {
171 req =
"UPDATE secondary_ecus SET sec_type = ?, public_key_type = ?, public_key = ? WHERE serial = ?;";
174 "INSERT INTO secondary_ecus (serial, sec_type, public_key_type, public_key) SELECT " 175 "serial,?,?,? FROM ecus WHERE (serial = ? AND is_primary = 0);";
178 statement = db.prepareStatement<std::string, std::string, std::string, std::string>(
179 req, sec_type, key_type_str, public_key.Value(), ecu_serial.ToString());
180 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
181 throw std::runtime_error(db.errmsg().insert(0,
"Can't save Secondary key: "));
184 db.commitTransaction();
190 db.beginTransaction();
193 db.prepareStatement<std::string>(
"SELECT count(*) FROM secondary_ecus WHERE serial = ?;", ecu_serial.ToString());
194 if (statement.step() != SQLITE_ROW) {
195 throw std::runtime_error(db.errmsg().insert(0,
"Can't get count of secondary_ecus table: "));
199 if (statement.get_result_col_int(0) != 0) {
200 req =
"UPDATE secondary_ecus SET extra = ? WHERE serial = ?;";
202 req =
"INSERT INTO secondary_ecus (extra, serial) VALUES (?,?);";
205 statement = db.prepareStatement<std::string, std::string>(req, data, ecu_serial.ToString());
206 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
207 throw std::runtime_error(db.errmsg().insert(0,
"Can't save Secondary data: "));
210 db.commitTransaction();
218 auto statement = db.prepareStatement<std::string>(
219 "SELECT serial, hardware_id, sec_type, public_key_type, public_key, extra FROM ecus LEFT JOIN secondary_ecus " 221 "(serial) WHERE (serial = ? AND is_primary = 0);",
222 ecu_serial.ToString());
223 int statement_state = statement.step();
224 if (statement_state == SQLITE_DONE) {
225 LOG_TRACE <<
"Secondary ECU " << ecu_serial <<
" not found";
227 }
else if (statement_state != SQLITE_ROW) {
228 LOG_ERROR <<
"Cannot load Secondary info: " << db.errmsg();
235 std::string sec_type = statement.get_result_col_str(2).value_or(
"");
236 std::string kt_str = statement.get_result_col_str(3).value_or(
"");
240 std::stringstream(kt_str) >> key_type;
241 key =
PublicKey(statement.get_result_col_str(4).value_or(
""), key_type);
243 std::string extra = statement.get_result_col_str(5).value_or(
"");
244 new_sec =
SecondaryInfo{serial, hw_id, sec_type, key, extra};
245 }
catch (
const boost::bad_optional_access&) {
249 if (secondary !=
nullptr) {
250 *secondary = std::move(new_sec);
256 bool SQLStorage::loadSecondariesInfo(std::vector<SecondaryInfo>* secondaries)
const {
259 std::vector<SecondaryInfo> new_secs;
264 auto statement = db.prepareStatement(
265 "SELECT serial, hardware_id, sec_type, public_key_type, public_key, extra FROM ecus LEFT JOIN secondary_ecus " 267 "(serial) WHERE is_primary = 0 ORDER BY ecus.id;");
268 while ((statement_state = statement.step()) == SQLITE_ROW) {
272 std::string sec_type = statement.get_result_col_str(2).value_or(
"");
273 std::string kt_str = statement.get_result_col_str(3).value_or(
"");
277 std::stringstream(kt_str) >> key_type;
278 key =
PublicKey(statement.get_result_col_str(4).value_or(
""), key_type);
280 std::string extra = statement.get_result_col_str(5).value_or(
"");
281 new_secs.emplace_back(
SecondaryInfo{serial, hw_id, sec_type, key, extra});
283 }
catch (
const boost::bad_optional_access&) {
287 if (statement_state != SQLITE_DONE) {
288 LOG_ERROR <<
"Can't load Secondary info" << db.errmsg();
291 if (secondaries !=
nullptr) {
292 *secondaries = std::move(new_secs);
298 void SQLStorage::storeTlsCreds(
const std::string& ca,
const std::string& cert,
const std::string& pkey) {
304 void SQLStorage::storeTlsCa(
const std::string& ca) {
307 db.beginTransaction();
309 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
310 if (statement.step() != SQLITE_ROW) {
311 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
316 if (statement.get_result_col_int(0) != 0) {
317 req =
"UPDATE OR REPLACE tls_creds SET ca_cert = ?;";
319 req =
"INSERT INTO tls_creds(ca_cert) VALUES (?);";
323 if (statement.step() != SQLITE_DONE) {
324 LOG_ERROR <<
"Can't set ca_cert: " << db.errmsg();
328 db.commitTransaction();
331 void SQLStorage::storeTlsCert(
const std::string& cert) {
334 db.beginTransaction();
336 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
337 if (statement.step() != SQLITE_ROW) {
338 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
343 if (statement.get_result_col_int(0) != 0) {
344 req =
"UPDATE OR REPLACE tls_creds SET client_cert = ?;";
346 req =
"INSERT INTO tls_creds(client_cert) VALUES (?);";
350 if (statement.step() != SQLITE_DONE) {
351 LOG_ERROR <<
"Can't set client_cert: " << db.errmsg();
355 db.commitTransaction();
358 void SQLStorage::storeTlsPkey(
const std::string& pkey) {
361 db.beginTransaction();
363 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
364 if (statement.step() != SQLITE_ROW) {
365 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
370 if (statement.get_result_col_int(0) != 0) {
371 req =
"UPDATE OR REPLACE tls_creds SET client_pkey = ?;";
373 req =
"INSERT INTO tls_creds(client_pkey) VALUES (?);";
377 if (statement.step() != SQLITE_DONE) {
378 LOG_ERROR <<
"Can't set client_pkey: " << db.errmsg();
382 db.commitTransaction();
385 bool SQLStorage::loadTlsCreds(std::string* ca, std::string* cert, std::string* pkey)
const {
388 db.beginTransaction();
390 auto statement = db.prepareStatement(
"SELECT ca_cert, client_cert, client_pkey FROM tls_creds LIMIT 1;");
392 int result = statement.step();
393 if (result == SQLITE_DONE) {
394 LOG_TRACE <<
"Tls creds not present";
396 }
else if (result != SQLITE_ROW) {
397 LOG_ERROR <<
"Can't get tls_creds: " << db.errmsg();
405 ca_v = statement.get_result_col_str(0).value();
406 cert_v = statement.get_result_col_str(1).value();
407 pkey_v = statement.get_result_col_str(2).value();
408 }
catch (
const boost::bad_optional_access&) {
413 *ca = std::move(ca_v);
415 if (cert !=
nullptr) {
416 *cert = std::move(cert_v);
418 if (pkey !=
nullptr) {
419 *pkey = std::move(pkey_v);
422 db.commitTransaction();
427 void SQLStorage::clearTlsCreds() {
430 if (db.exec(
"DELETE FROM tls_creds;",
nullptr,
nullptr) != SQLITE_OK) {
431 LOG_ERROR <<
"Can't clear tls_creds: " << db.errmsg();
436 bool SQLStorage::loadTlsCa(std::string* ca)
const {
439 auto statement = db.prepareStatement(
"SELECT ca_cert FROM tls_creds LIMIT 1;");
441 int result = statement.step();
442 if (result == SQLITE_DONE) {
443 LOG_TRACE <<
"ca_cert not present";
445 }
else if (result != SQLITE_ROW) {
446 LOG_ERROR <<
"Can't get ca_cert: " << db.errmsg();
450 auto ca_r = statement.get_result_col_str(0);
451 if (ca_r == boost::none) {
456 *ca = std::move(ca_r.value());
462 bool SQLStorage::loadTlsCert(std::string* cert)
const {
465 auto statement = db.prepareStatement(
"SELECT client_cert FROM tls_creds LIMIT 1;");
467 int result = statement.step();
468 if (result == SQLITE_DONE) {
469 LOG_TRACE <<
"client_cert not present in db";
471 }
else if (result != SQLITE_ROW) {
472 LOG_ERROR <<
"Can't get client_cert: " << db.errmsg();
476 auto cert_r = statement.get_result_col_str(0);
477 if (cert_r == boost::none) {
481 if (cert !=
nullptr) {
482 *cert = std::move(cert_r.value());
488 bool SQLStorage::loadTlsPkey(std::string* pkey)
const {
491 auto statement = db.prepareStatement(
"SELECT client_pkey FROM tls_creds LIMIT 1;");
493 int result = statement.step();
494 if (result == SQLITE_DONE) {
495 LOG_TRACE <<
"client_pkey not present in db";
497 }
else if (result != SQLITE_ROW) {
498 LOG_ERROR <<
"Can't get client_pkey: " << db.errmsg();
502 auto pkey_r = statement.get_result_col_str(0);
503 if (pkey_r == boost::none) {
507 if (pkey !=
nullptr) {
508 *pkey = std::move(pkey_r.value());
517 db.beginTransaction();
520 db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
521 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
523 if (del_statement.step() != SQLITE_DONE) {
524 LOG_ERROR <<
"Can't clear Root metadata: " << db.errmsg();
528 auto ins_statement = db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
529 SQLBlob(data),
static_cast<int>(repo),
530 Uptane::Role::Root().ToInt(), version.version());
532 if (ins_statement.step() != SQLITE_DONE) {
533 LOG_ERROR <<
"Can't add metadata: " << db.errmsg();
537 db.commitTransaction();
543 db.beginTransaction();
545 auto del_statement = db.prepareStatement<int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=?);",
546 static_cast<int>(repo), role.ToInt());
548 if (del_statement.step() != SQLITE_DONE) {
549 LOG_ERROR <<
"Can't clear " << role.ToString() <<
" metadata: " << db.errmsg();
554 db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
SQLBlob(data),
557 if (ins_statement.step() != SQLITE_DONE) {
558 LOG_ERROR <<
"Can't add " << role.ToString() <<
"metadata: " << db.errmsg();
562 db.commitTransaction();
569 if (version.version() < 0) {
570 auto statement = db.prepareStatement<int,
int>(
571 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;",
static_cast<int>(repo),
572 Uptane::Role::Root().ToInt());
573 int result = statement.step();
575 if (result == SQLITE_DONE) {
576 LOG_TRACE <<
"Root metadata not present";
578 }
else if (result != SQLITE_ROW) {
579 LOG_ERROR <<
"Can't get Root metadata: " << db.errmsg();
582 if (data !=
nullptr) {
583 *data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
587 db.prepareStatement<int, int,
int>(
"SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
588 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
590 int result = statement.step();
592 if (result == SQLITE_DONE) {
593 LOG_TRACE <<
"Root metadata not present";
595 }
else if (result != SQLITE_ROW) {
596 LOG_ERROR <<
"Can't get Root metadata: " << db.errmsg();
600 const auto blob =
reinterpret_cast<const char*
>(sqlite3_column_blob(statement.get(), 0));
601 if (blob ==
nullptr) {
602 LOG_ERROR <<
"Can't get Root metadata: " << db.errmsg();
606 if (data !=
nullptr) {
607 *data = std::string(blob);
617 auto statement = db.prepareStatement<int,
int>(
618 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;",
static_cast<int>(repo),
620 int result = statement.step();
622 if (result == SQLITE_DONE) {
623 LOG_TRACE << role.ToString() <<
" metadata not present";
625 }
else if (result != SQLITE_ROW) {
626 LOG_ERROR <<
"Can't get " << role.ToString() <<
" metadata: " << db.errmsg();
629 if (data !=
nullptr) {
630 *data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
640 db.prepareStatement<
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type != 0);",
static_cast<int>(repo));
642 if (del_statement.step() != SQLITE_DONE) {
643 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
647 void SQLStorage::clearMetadata() {
650 if (db.exec(
"DELETE FROM meta;",
nullptr,
nullptr) != SQLITE_OK) {
651 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
656 void SQLStorage::storeDelegation(
const std::string& data,
const Uptane::Role role) {
659 db.beginTransaction();
661 auto statement = db.prepareStatement<
SQLBlob, std::string>(
"INSERT OR REPLACE INTO delegations VALUES (?, ?);",
662 SQLBlob(data), role.ToString());
664 if (statement.step() != SQLITE_DONE) {
665 LOG_ERROR <<
"Can't add delegation metadata: " << db.errmsg();
669 db.commitTransaction();
672 bool SQLStorage::loadDelegation(std::string* data,
const Uptane::Role role)
const {
676 db.prepareStatement<std::string>(
"SELECT meta FROM delegations WHERE role_name=? LIMIT 1;", role.ToString());
677 int result = statement.step();
679 if (result == SQLITE_DONE) {
680 LOG_TRACE <<
"Delegations metadata not present";
682 }
else if (result != SQLITE_ROW) {
683 LOG_ERROR <<
"Can't get delegations metadata: " << db.errmsg();
686 if (data !=
nullptr) {
687 *data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
693 bool SQLStorage::loadAllDelegations(std::vector<std::pair<Uptane::Role, std::string>>& data)
const {
699 auto statement = db.prepareStatement(
"SELECT meta, role_name FROM delegations;");
700 auto statement_state = statement.step();
702 if (statement_state == SQLITE_DONE) {
703 LOG_TRACE <<
"Delegations metadata are not present";
705 }
else if (statement_state != SQLITE_ROW) {
706 LOG_ERROR <<
"Can't get delegations metadata: " << db.errmsg();
711 data.emplace_back(Uptane::Role::Delegation(statement.get_result_col_str(1).value()),
712 statement.get_result_col_blob(0).value());
713 }
while ((statement_state = statement.step()) == SQLITE_ROW);
716 }
catch (
const std::exception& exc) {
717 LOG_ERROR <<
"Failed to fetch records from `delegations` table: " << exc.what();
723 void SQLStorage::deleteDelegation(
const Uptane::Role role) {
726 auto statement = db.prepareStatement<std::string>(
"DELETE FROM delegations WHERE role_name=?;", role.ToString());
730 void SQLStorage::clearDelegations() {
733 if (db.exec(
"DELETE FROM delegations;",
nullptr,
nullptr) != SQLITE_OK) {
734 LOG_ERROR <<
"Can't clear delegations metadata: " << db.errmsg();
738 void SQLStorage::storeDeviceId(
const std::string& device_id) {
741 auto statement = db.prepareStatement<std::string>(
742 "INSERT OR REPLACE INTO device_info(unique_mark,device_id,is_registered) VALUES(0,?,0);", device_id);
743 if (statement.step() != SQLITE_DONE) {
744 LOG_ERROR <<
"Can't set device ID: " << db.errmsg();
749 bool SQLStorage::loadDeviceId(std::string* device_id)
const {
752 auto statement = db.prepareStatement(
"SELECT device_id FROM device_info LIMIT 1;");
754 int result = statement.step();
755 if (result == SQLITE_DONE) {
756 LOG_TRACE <<
"device_id not present in db";
758 }
else if (result != SQLITE_ROW) {
759 LOG_ERROR <<
"Can't get device ID: " << db.errmsg();
763 auto did = statement.get_result_col_str(0);
764 if (did == boost::none) {
765 LOG_ERROR <<
"Empty device ID" << db.errmsg();
769 if (device_id !=
nullptr) {
770 *device_id = std::move(did.value());
776 void SQLStorage::clearDeviceId() {
779 if (db.exec(
"DELETE FROM device_info;",
nullptr,
nullptr) != SQLITE_OK) {
780 LOG_ERROR <<
"Can't clear device ID: " << db.errmsg();
785 void SQLStorage::storeEcuRegistered() {
788 db.beginTransaction();
790 auto statement = db.prepareStatement(
"SELECT count(*) FROM device_info;");
791 if (statement.step() != SQLITE_ROW) {
792 throw std::runtime_error(
"Could not get device_info count");
794 if (statement.get_result_col_int(0) != 1) {
795 throw std::runtime_error(
"Cannot set ECU registered if no device_info set");
798 std::string req =
"UPDATE device_info SET is_registered = 1";
799 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
800 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
804 db.commitTransaction();
807 bool SQLStorage::loadEcuRegistered()
const {
810 auto statement = db.prepareStatement(
"SELECT is_registered FROM device_info LIMIT 1;");
812 int result = statement.step();
813 if (result == SQLITE_DONE) {
815 }
else if (result != SQLITE_ROW) {
816 LOG_ERROR <<
"Can't get is_registered in device_info " << db.errmsg();
820 return statement.get_result_col_int(0) != 0;
823 void SQLStorage::clearEcuRegistered() {
827 std::string req =
"UPDATE device_info SET is_registered = 0";
828 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
829 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
834 void SQLStorage::storeNeedReboot() {
837 auto statement = db.prepareStatement<
int>(
"INSERT OR REPLACE INTO need_reboot(unique_mark,flag) VALUES(0,?);", 1);
838 if (statement.step() != SQLITE_DONE) {
839 LOG_ERROR <<
"Can't set need_reboot: " << db.errmsg();
844 bool SQLStorage::loadNeedReboot(
bool* need_reboot)
const {
847 auto statement = db.prepareStatement(
"SELECT flag FROM need_reboot LIMIT 1;");
849 int result = statement.step();
850 if (result == SQLITE_DONE) {
851 if (need_reboot !=
nullptr) {
852 *need_reboot =
false;
855 }
else if (result != SQLITE_ROW) {
856 LOG_ERROR <<
"Can't get need_reboot: " << db.errmsg();
860 auto flag =
static_cast<bool>(statement.get_result_col_int(0));
861 if (need_reboot !=
nullptr) {
868 void SQLStorage::clearNeedReboot() {
871 if (db.exec(
"DELETE FROM need_reboot;",
nullptr,
nullptr) != SQLITE_OK) {
872 LOG_ERROR <<
"Can't clear need_reboot: " << db.errmsg();
877 void SQLStorage::storeEcuSerials(
const EcuSerials& serials) {
878 if (serials.size() >= 1) {
881 db.beginTransaction();
883 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
884 LOG_ERROR <<
"Can't clear ecus: " << db.errmsg();
889 std::string serial = serials[0].first.ToString();
890 std::string hwid = serials[0].second.ToString();
892 auto statement = db.prepareStatement<std::string, std::string>(
893 "INSERT INTO ecus(id, serial,hardware_id,is_primary) VALUES (0, ?,?,1);", serial, hwid);
894 if (statement.step() != SQLITE_DONE) {
895 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
900 auto statement_ivupdate = db.prepareStatement<std::string>(
901 "UPDATE installed_versions SET ecu_serial = ? WHERE ecu_serial = '';", serial);
903 if (statement_ivupdate.step() != SQLITE_DONE) {
904 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
909 for (
auto it = serials.cbegin() + 1; it != serials.cend(); it++) {
910 auto statement = db.prepareStatement<int64_t, std::string, std::string>(
911 "INSERT INTO ecus(id,serial,hardware_id) VALUES (?,?,?);", it - serials.cbegin(), it->first.ToString(),
912 it->second.ToString());
914 if (statement.step() != SQLITE_DONE) {
915 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
920 db.commitTransaction();
924 bool SQLStorage::loadEcuSerials(EcuSerials* serials)
const {
928 auto statement = db.prepareStatement(
"SELECT serial, hardware_id FROM ecus ORDER BY id;");
931 EcuSerials new_serials;
933 while ((statement_state = statement.step()) == SQLITE_ROW) {
935 new_serials.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
938 }
catch (
const boost::bad_optional_access&) {
943 if (statement_state != SQLITE_DONE) {
944 LOG_ERROR <<
"Can't get ECU serials: " << db.errmsg();
948 if (serials !=
nullptr) {
949 *serials = std::move(new_serials);
955 void SQLStorage::clearEcuSerials() {
958 db.beginTransaction();
960 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
961 LOG_ERROR <<
"Can't clear ECUs: " << db.errmsg();
965 if (db.exec(
"DELETE FROM secondary_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
966 LOG_ERROR <<
"Can't clear Secondary ECUs: " << db.errmsg();
970 db.commitTransaction();
973 void SQLStorage::storeCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial,
const std::string& manifest) {
976 auto statement = db.prepareStatement<std::string, std::string>(
977 "UPDATE secondary_ecus SET manifest = ? WHERE (serial = ?);", manifest, ecu_serial.ToString());
978 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
979 LOG_ERROR <<
"Can't save Secondary manifest " << db.errmsg();
984 bool SQLStorage::loadCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial, std::string* manifest)
const {
987 std::string stmanifest;
991 auto statement = db.prepareStatement<std::string>(
"SELECT manifest FROM secondary_ecus WHERE (serial = ?);",
992 ecu_serial.ToString());
994 if (statement.step() != SQLITE_ROW) {
995 LOG_WARNING <<
"Could not find manifest for ECU " << ecu_serial;
998 stmanifest = statement.get_result_col_str(0).value_or(
"");
1000 empty = stmanifest ==
"";
1003 if (manifest !=
nullptr) {
1004 *manifest = std::move(stmanifest);
1010 void SQLStorage::storeMisconfiguredEcus(
const std::vector<MisconfiguredEcu>& ecus) {
1011 if (ecus.size() >= 1) {
1014 db.beginTransaction();
1016 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1017 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
1021 std::vector<MisconfiguredEcu>::const_iterator it;
1022 for (it = ecus.begin(); it != ecus.end(); it++) {
1023 auto statement = db.prepareStatement<std::string, std::string,
int>(
1024 "INSERT INTO misconfigured_ecus VALUES (?,?,?);", it->serial.ToString(), it->hardware_id.ToString(),
1025 static_cast<int>(it->state));
1027 if (statement.step() != SQLITE_DONE) {
1028 LOG_ERROR <<
"Can't set misconfigured_ecus: " << db.errmsg();
1033 db.commitTransaction();
1037 bool SQLStorage::loadMisconfiguredEcus(std::vector<MisconfiguredEcu>* ecus)
const {
1040 auto statement = db.prepareStatement(
"SELECT serial, hardware_id, state FROM misconfigured_ecus;");
1041 int statement_state;
1043 std::vector<MisconfiguredEcu> new_ecus;
1045 while ((statement_state = statement.step()) == SQLITE_ROW) {
1047 new_ecus.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
1049 static_cast<EcuState>(statement.get_result_col_int(2)));
1051 }
catch (
const boost::bad_optional_access&) {
1056 if (statement_state != SQLITE_DONE) {
1057 LOG_ERROR <<
"Can't get misconfigured_ecus: " << db.errmsg();
1061 if (ecus !=
nullptr) {
1062 *ecus = std::move(new_ecus);
1068 void SQLStorage::clearMisconfiguredEcus() {
1071 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1072 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
1077 void SQLStorage::saveInstalledVersion(
const std::string& ecu_serial,
const Uptane::Target& target,
1078 InstalledVersionUpdateMode update_mode) {
1081 db.beginTransaction();
1086 std::string ecu_serial_real = ecu_serial;
1087 if (ecu_serial_real.empty()) {
1088 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1089 if (statement.step() == SQLITE_ROW) {
1090 ecu_serial_real = statement.get_result_col_str(0).value();
1092 LOG_WARNING <<
"Could not find Primary ECU serial, set to lazy init mode";
1096 std::string hashes_encoded = Hash::encodeVector(target.hashes());
1099 boost::optional<int64_t> old_id;
1100 bool old_was_installed =
false;
1102 auto statement = db.prepareStatement<std::string>(
1103 "SELECT id, sha256, name, was_installed FROM installed_versions WHERE ecu_serial = ? ORDER BY id DESC " 1107 if (statement.step() == SQLITE_ROW) {
1108 int64_t rid = statement.get_result_col_int(0);
1109 std::string rsha256 = statement.get_result_col_str(1).value_or(
"");
1110 std::string rname = statement.get_result_col_str(2).value_or(
"");
1111 bool rwasi = statement.get_result_col_int(3) == 1;
1113 if (rsha256 == target.sha256Hash() && rname == target.filename()) {
1115 old_was_installed = rwasi;
1120 if (update_mode == InstalledVersionUpdateMode::kCurrent) {
1122 auto statement = db.prepareStatement<std::string>(
1123 "UPDATE installed_versions SET is_current = 0, is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1124 if (statement.step() != SQLITE_DONE) {
1125 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1128 }
else if (update_mode == InstalledVersionUpdateMode::kPending) {
1130 auto statement = db.prepareStatement<std::string>(
1131 "UPDATE installed_versions SET is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1132 if (statement.step() != SQLITE_DONE) {
1133 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1139 auto statement = db.prepareStatement<std::string, int, int, int64_t>(
1140 "UPDATE installed_versions SET correlation_id = ?, is_current = ?, is_pending = ?, was_installed = ? WHERE id " 1142 target.correlation_id(),
static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1143 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1144 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent || old_was_installed), old_id.value());
1146 if (statement.step() != SQLITE_DONE) {
1147 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1151 std::string custom = Utils::jsonToCanonicalStr(target.custom_data());
1152 auto statement = db.prepareStatement<std::string, std::string, std::string, std::string, int64_t, std::string,
1153 std::string, int,
int>(
1154 "INSERT INTO installed_versions(ecu_serial, sha256, name, hashes, length, custom_meta, correlation_id, " 1155 "is_current, is_pending, was_installed) VALUES (?,?,?,?,?,?,?,?,?,?);",
1156 ecu_serial_real, target.sha256Hash(), target.filename(), hashes_encoded,
static_cast<int64_t
>(target.length()),
1157 custom, target.correlation_id(),
static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1158 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1159 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent));
1161 if (statement.step() != SQLITE_DONE) {
1162 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1167 db.commitTransaction();
1170 static void loadEcuMap(
SQLite3Guard& db, std::string& ecu_serial, Uptane::EcuMap& ecu_map) {
1173 if (ecu_serial.empty()) {
1174 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1175 if (statement.step() == SQLITE_ROW) {
1176 ecu_serial = statement.get_result_col_str(0).value();
1177 }
else if (statement.step() == SQLITE_DONE) {
1178 LOG_DEBUG <<
"No serial found in database for this ECU, defaulting to empty serial";
1180 LOG_ERROR <<
"Error getting serial for this ECU, defaulting to empty serial: " << db.errmsg();
1184 if (!ecu_serial.empty()) {
1185 auto statement = db.prepareStatement<std::string>(
"SELECT hardware_id FROM ecus WHERE serial = ?;", ecu_serial);
1186 if (statement.step() == SQLITE_ROW) {
1189 }
else if (statement.step() == SQLITE_DONE) {
1190 LOG_DEBUG <<
"No hardware ID found in database for ECU serial " << ecu_serial;
1192 LOG_ERROR <<
"Error getting hardware ID for ECU serial " << ecu_serial <<
": " << db.errmsg();
1197 bool SQLStorage::loadInstallationLog(
const std::string& ecu_serial, std::vector<Uptane::Target>* log,
1198 bool only_installed)
const {
1201 std::string ecu_serial_real = ecu_serial;
1202 Uptane::EcuMap ecu_map;
1203 loadEcuMap(db, ecu_serial_real, ecu_map);
1206 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE " 1207 "ecu_serial = ? ORDER BY id;";
1208 if (only_installed) {
1210 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE " 1211 "ecu_serial = ? AND was_installed = 1 ORDER BY id;";
1214 auto statement = db.prepareStatement<std::string>(query, ecu_serial_real);
1215 int statement_state;
1217 std::vector<Uptane::Target> new_log;
1218 std::map<int64_t, size_t> ids_map;
1220 while ((statement_state = statement.step()) == SQLITE_ROW) {
1222 auto id = statement.get_result_col_int(0);
1223 auto sha256 = statement.get_result_col_str(1).value();
1224 auto filename = statement.get_result_col_str(2).value();
1225 auto hashes_str = statement.get_result_col_str(3).value();
1226 auto length = statement.get_result_col_int(4);
1227 auto correlation_id = statement.get_result_col_str(5).value();
1228 auto custom_str = statement.get_result_col_str(6).value();
1232 std::vector<Hash> hashes = Hash::decodeVector(hashes_str);
1235 std::find_if(hashes.cbegin(), hashes.cend(), [](
const Hash& h) {
return h.type() == Hash::Type::kSha256; });
1236 if (find_sha256 == hashes.cend()) {
1237 LOG_WARNING <<
"No sha256 in hashes list";
1238 hashes.emplace_back(Hash::Type::kSha256, sha256);
1241 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1242 if (!custom_str.empty()) {
1243 std::istringstream css(custom_str);
1246 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom,
nullptr)) {
1247 t.updateCustom(custom);
1249 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1252 new_log.emplace_back(t);
1256 }
catch (
const boost::bad_optional_access&) {
1257 LOG_ERROR <<
"Incompleted installed version, keeping old one";
1262 if (statement_state != SQLITE_DONE) {
1263 LOG_ERROR <<
"Can't get installed_versions: " << db.errmsg();
1267 if (log ==
nullptr) {
1271 *log = std::move(new_log);
1276 bool SQLStorage::loadInstalledVersions(
const std::string& ecu_serial, boost::optional<Uptane::Target>* current_version,
1277 boost::optional<Uptane::Target>* pending_version)
const {
1280 std::string ecu_serial_real = ecu_serial;
1281 Uptane::EcuMap ecu_map;
1282 loadEcuMap(db, ecu_serial_real, ecu_map);
1285 auto sha256 = statement.get_result_col_str(0).value();
1286 auto filename = statement.get_result_col_str(1).value();
1287 auto hashes_str = statement.get_result_col_str(2).value();
1288 auto length = statement.get_result_col_int(3);
1289 auto correlation_id = statement.get_result_col_str(4).value();
1290 auto custom_str = statement.get_result_col_str(5).value();
1294 std::vector<Hash> hashes = Hash::decodeVector(hashes_str);
1297 std::find_if(hashes.cbegin(), hashes.cend(), [](
const Hash& h) {
return h.type() == Hash::Type::kSha256; });
1298 if (find_sha256 == hashes.cend()) {
1299 LOG_WARNING <<
"No sha256 in hashes list";
1300 hashes.emplace_back(Hash::Type::kSha256, sha256);
1302 Uptane::Target t(filename, ecu_map, hashes, static_cast<uint64_t>(length), correlation_id);
1303 if (!custom_str.empty()) {
1304 std::istringstream css(custom_str);
1307 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom, &errs)) {
1308 t.updateCustom(custom);
1310 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1317 if (current_version !=
nullptr) {
1318 auto statement = db.prepareStatement<std::string>(
1319 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE " 1320 "ecu_serial = ? AND is_current = 1 LIMIT 1;",
1323 if (statement.step() == SQLITE_ROW) {
1325 *current_version = read_target(statement);
1326 }
catch (
const boost::bad_optional_access&) {
1327 LOG_ERROR <<
"Could not read current installed version";
1331 LOG_TRACE <<
"Cannot get current installed version: " << db.errmsg();
1332 *current_version = boost::none;
1336 if (pending_version !=
nullptr) {
1337 auto statement = db.prepareStatement<std::string>(
1338 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE " 1339 "ecu_serial = ? AND is_pending = 1 LIMIT 1;",
1342 if (statement.step() == SQLITE_ROW) {
1344 *pending_version = read_target(statement);
1345 }
catch (
const boost::bad_optional_access&) {
1346 LOG_ERROR <<
"Could not read pending installed version";
1350 LOG_TRACE <<
"Cannot get pending installed version: " << db.errmsg();
1351 *pending_version = boost::none;
1358 bool SQLStorage::hasPendingInstall() {
1361 auto statement = db.prepareStatement(
"SELECT count(*) FROM installed_versions where is_pending = 1");
1362 if (statement.step() != SQLITE_ROW) {
1363 LOG_ERROR <<
"Can't get tables count: " << db.errmsg();
1364 throw std::runtime_error(
"Could not count pending installations");
1367 return statement.get_result_col_int(0) > 0;
1370 void SQLStorage::getPendingEcus(std::vector<std::pair<Uptane::EcuSerial, Hash>>* pendingEcus) {
1373 auto statement = db.prepareStatement(
"SELECT ecu_serial, sha256 FROM installed_versions where is_pending = 1");
1374 int statement_result = statement.step();
1375 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1376 throw std::runtime_error(
"Failed to get ECUs with a pending target installation: " + db.errmsg());
1379 std::vector<std::pair<Uptane::EcuSerial, Hash>> ecu_res;
1381 if (statement_result == SQLITE_DONE) {
1386 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1387 std::string ecu_serial = statement.get_result_col_str(0).value();
1388 std::string hash = statement.get_result_col_str(1).value();
1389 ecu_res.emplace_back(std::make_pair(
Uptane::EcuSerial(ecu_serial),
Hash(Hash::Type::kSha256, hash)));
1392 if (pendingEcus !=
nullptr) {
1393 *pendingEcus = std::move(ecu_res);
1397 void SQLStorage::clearInstalledVersions() {
1400 if (db.exec(
"DELETE FROM installed_versions;",
nullptr,
nullptr) != SQLITE_OK) {
1401 LOG_ERROR <<
"Can't clear installed_versions: " << db.errmsg();
1410 auto statement = db.prepareStatement<std::string, int, std::string, std::string>(
1411 "INSERT OR REPLACE INTO ecu_installation_results (ecu_serial, success, result_code, description) VALUES " 1413 ecu_serial.ToString(),
static_cast<int>(result.success), result.result_code.toRepr(), result.description);
1414 if (statement.step() != SQLITE_DONE) {
1415 LOG_ERROR <<
"Can't set ECU installation result: " << db.errmsg();
1420 bool SQLStorage::loadEcuInstallationResults(
1421 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>>* results)
const {
1424 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_res;
1427 auto statement = db.prepareStatement(
1428 "SELECT ecu_serial, success, result_code, description FROM ecu_installation_results INNER JOIN ecus ON " 1429 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1430 int statement_result = statement.step();
1431 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1432 LOG_ERROR <<
"Can't get ecu_installation_results: " << db.errmsg();
1436 if (statement_result == SQLITE_DONE) {
1441 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1443 std::string ecu_serial = statement.get_result_col_str(0).value();
1444 auto success =
static_cast<bool>(statement.get_result_col_int(1));
1445 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(2).value());
1446 std::string description = statement.get_result_col_str(3).value();
1449 }
catch (
const boost::bad_optional_access&) {
1454 if (results !=
nullptr) {
1455 *results = std::move(ecu_res);
1461 void SQLStorage::storeDeviceInstallationResult(
const data::InstallationResult& result,
const std::string& raw_report,
1462 const std::string& correlation_id) {
1465 auto statement = db.prepareStatement<int, std::string, std::string, std::string, std::string>(
1466 "INSERT OR REPLACE INTO device_installation_result (unique_mark, success, result_code, description, raw_report, " 1468 "VALUES (0,?,?,?,?,?);",
1469 static_cast<int>(result.success), result.result_code.toRepr(), result.description, raw_report, correlation_id);
1470 if (statement.step() != SQLITE_DONE) {
1471 LOG_ERROR <<
"Can't set device installation result: " << db.errmsg();
1477 std::string* correlation_id)
const {
1481 std::string raw_report_res;
1482 std::string corrid_res;
1484 auto statement = db.prepareStatement(
1485 "SELECT success, result_code, description, raw_report, correlation_id FROM device_installation_result;");
1486 int statement_result = statement.step();
1487 if (statement_result == SQLITE_DONE) {
1488 LOG_TRACE <<
"No device installation result in db";
1490 }
else if (statement_result != SQLITE_ROW) {
1491 LOG_ERROR <<
"Can't get device_installation_result: " << db.errmsg();
1496 auto success =
static_cast<bool>(statement.get_result_col_int(0));
1497 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(1).value());
1498 std::string description = statement.get_result_col_str(2).value();
1499 raw_report_res = statement.get_result_col_str(3).value();
1500 corrid_res = statement.get_result_col_str(4).value();
1503 }
catch (
const boost::bad_optional_access&) {
1507 if (result !=
nullptr) {
1508 *result = std::move(dev_res);
1511 if (raw_report !=
nullptr) {
1512 *raw_report = std::move(raw_report_res);
1515 if (correlation_id !=
nullptr) {
1516 *correlation_id = std::move(corrid_res);
1522 void SQLStorage::saveEcuReportCounter(
const Uptane::EcuSerial& ecu_serial,
const int64_t counter) {
1525 auto statement = db.prepareStatement<std::string, int64_t>(
1526 "INSERT OR REPLACE INTO ecu_report_counter (ecu_serial, counter) VALUES " 1528 ecu_serial.ToString(), counter);
1529 if (statement.step() != SQLITE_DONE) {
1530 LOG_ERROR <<
"Can't set ECU counter: " << db.errmsg();
1535 bool SQLStorage::loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results)
const {
1538 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
1541 auto statement = db.prepareStatement(
1542 "SELECT ecu_serial, counter FROM ecu_report_counter INNER JOIN ecus ON " 1543 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1544 int statement_result = statement.step();
1545 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1546 LOG_ERROR <<
"Can't get ecu_report_counter: " << db.errmsg();
1550 if (statement_result == SQLITE_DONE) {
1555 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1557 std::string ecu_serial = statement.get_result_col_str(0).value();
1558 int64_t counter = statement.get_result_col_int(1);
1561 }
catch (
const boost::bad_optional_access&) {
1566 if (results !=
nullptr) {
1567 *results = std::move(ecu_cnt);
1573 void SQLStorage::saveReportEvent(
const Json::Value& json_value) {
1574 std::string json_string = Utils::jsonToCanonicalStr(json_value);
1576 auto statement = db.prepareStatement<std::string>(
1577 "INSERT INTO report_events SELECT MAX(id) + 1, ? FROM report_events", json_string);
1578 if (statement.step() != SQLITE_DONE) {
1579 LOG_ERROR <<
"Can't save report event: " << db.errmsg();
1584 bool SQLStorage::loadReportEvents(Json::Value* report_array, int64_t* id_max)
const {
1586 auto statement = db.prepareStatement(
"SELECT id, json_string FROM report_events;");
1587 int statement_result = statement.step();
1588 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1589 LOG_ERROR <<
"Can't get report_events: " << db.errmsg();
1592 if (statement_result == SQLITE_DONE) {
1597 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1599 int64_t
id = statement.get_result_col_int(0);
1600 std::string json_string = statement.get_result_col_str(1).value();
1601 std::istringstream jss(json_string);
1602 Json::Value event_json;
1604 if (Json::parseFromStream(Json::CharReaderBuilder(), jss, &event_json, &errs)) {
1605 report_array->append(event_json);
1606 *id_max = (*id_max) >
id ? (*id_max) : id;
1608 LOG_ERROR <<
"Unable to parse event data: " << errs;
1610 }
catch (
const boost::bad_optional_access&) {
1618 void SQLStorage::deleteReportEvents(int64_t id_max) {
1621 db.beginTransaction();
1623 auto statement = db.prepareStatement<int64_t>(
"DELETE FROM report_events WHERE id <= ?;", id_max);
1624 if (statement.step() != SQLITE_DONE) {
1625 LOG_ERROR <<
"Can't delete report_events";
1628 db.commitTransaction();
1631 void SQLStorage::clearInstallationResults() {
1634 db.beginTransaction();
1636 if (db.exec(
"DELETE FROM device_installation_result;",
nullptr,
nullptr) != SQLITE_OK) {
1637 LOG_ERROR <<
"Can't clear device_installation_result: " << db.errmsg();
1641 if (db.exec(
"DELETE FROM ecu_installation_results;",
nullptr,
nullptr) != SQLITE_OK) {
1642 LOG_ERROR <<
"Can't clear ecu_installation_results: " << db.errmsg();
1646 db.commitTransaction();
1649 void SQLStorage::storeDeviceDataHash(
const std::string& data_type,
const std::string& hash) {
1652 auto statement = db.prepareStatement<std::string, std::string>(
1653 "INSERT OR REPLACE INTO device_data(data_type,hash) VALUES (?,?);", data_type, hash);
1654 if (statement.step() != SQLITE_DONE) {
1655 LOG_ERROR <<
"Can't set " << data_type <<
" hash: " << db.errmsg();
1656 throw std::runtime_error(
"Can't set " + data_type +
" hash: " + db.errmsg());
1660 bool SQLStorage::loadDeviceDataHash(
const std::string& data_type, std::string* hash)
const {
1664 db.prepareStatement<std::string>(
"SELECT hash FROM device_data WHERE data_type = ? LIMIT 1;", data_type);
1666 int result = statement.step();
1667 if (result == SQLITE_DONE) {
1668 LOG_TRACE << data_type <<
" hash not present in db";
1670 }
else if (result != SQLITE_ROW) {
1671 LOG_ERROR <<
"Can't get " << data_type <<
" hash: " << db.errmsg();
1675 if (hash !=
nullptr) {
1676 *hash = statement.get_result_col_str(0).value();
1682 void SQLStorage::clearDeviceData() {
1685 if (db.exec(
"DELETE FROM device_data;",
nullptr,
nullptr) != SQLITE_OK) {
1686 LOG_ERROR <<
"Can't clear device_data: " << db.errmsg();
1691 bool SQLStorage::checkAvailableDiskSpace(
const uint64_t required_bytes)
const {
1692 struct statvfs stvfsbuf {};
1693 const int stat_res = statvfs(dbPath().c_str(), &stvfsbuf);
1695 LOG_WARNING <<
"Unable to read filesystem statistics: error code " << stat_res;
1698 const uint64_t available_bytes = (
static_cast<uint64_t
>(stvfsbuf.f_bsize) * stvfsbuf.f_bavail);
1699 const uint64_t reserved_bytes = 1 << 20;
1701 if (required_bytes + reserved_bytes < available_bytes) {
1704 LOG_ERROR <<
"Insufficient disk space available to download target! Required: " << required_bytes
1705 <<
", available: " << available_bytes <<
", reserved: " << reserved_bytes;
1710 boost::optional<std::pair<uintmax_t, std::string>> SQLStorage::checkTargetFile(
const Uptane::Target& target)
const {
1713 auto statement = db.prepareStatement<std::string>(
1714 "SELECT sha256, sha512, filename FROM target_images WHERE targetname = ?;", target.filename());
1716 int statement_state;
1717 while ((statement_state = statement.step()) == SQLITE_ROW) {
1718 auto sha256 = statement.get_result_col_str(0);
1719 auto sha512 = statement.get_result_col_str(1);
1720 auto filename = statement.get_result_col_str(2);
1721 if ((*sha256).empty() && (*sha512).empty()) {
1723 LOG_WARNING <<
"Image without checksum: " << target.filename();
1726 bool sha256_match =
false;
1727 bool sha512_match =
false;
1728 if (!(*sha256).empty()) {
1729 if (target.MatchHash(
Hash(Hash::Type::kSha256, *sha256))) {
1730 sha256_match =
true;
1734 if (!(*sha512).empty()) {
1735 if (target.MatchHash(
Hash(Hash::Type::kSha512, *sha512))) {
1736 sha512_match =
true;
1739 if (((*sha256).empty() || sha256_match) && ((*sha512).empty() || sha512_match)) {
1740 if (boost::filesystem::exists(images_path_ / *filename)) {
1741 return {{boost::filesystem::file_size(images_path_ / *filename), *filename}};
1748 if (statement_state == SQLITE_DONE) {
1751 assert(statement_state != SQLITE_ROW);
1752 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1760 : db_path_(storage.dbPath()), target_(std::move(target)), storage_(&storage) {
1763 std::string sha256Hash;
1764 std::string sha512Hash;
1765 for (
const auto& hash : target_.hashes()) {
1766 if (hash.type() == Hash::Type::kSha256) {
1767 sha256Hash = hash.HashString();
1768 }
else if (hash.type() == Hash::Type::kSha512) {
1769 sha512Hash = hash.HashString();
1772 std::string filename = (storage.images_path_ / target_.hashes()[0].HashString()).
string();
1774 auto statement = db.prepareStatement<std::string, std::string, std::string>(
1775 "INSERT OR REPLACE INTO target_images (targetname, sha256, sha512, filename) VALUES ( ?, ?, ?, ?);",
1776 target_.filename(), sha256Hash, sha512Hash, target_.hashes()[0].HashString());
1778 if (statement.step() != SQLITE_DONE) {
1779 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1782 boost::filesystem::create_directories(storage.images_path_);
1783 stream_.open(filename);
1784 if (!stream_.good()) {
1785 LOG_ERROR <<
"Could not open image for write: " << storage.images_path_ / target_.filename();
1792 SQLTargetWHandle::wcommit();
1793 }
catch (std::exception& ex) {
1794 LOG_ERROR <<
"Failed to commit to database: " << ex.what();
1796 LOG_ERROR <<
"Failed to commit to database: unknown error";
1800 size_t wfeed(
const uint8_t* buf,
size_t size)
override {
1801 stream_.write(reinterpret_cast<const char*>(buf), static_cast<std::streamsize>(size));
1802 written_size_ += size;
1807 void wcommit()
override {
1813 void wabort() noexcept
override {
1818 if (storage_ !=
nullptr) {
1821 db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_.filename());
1822 if (statement.step() != SQLITE_DONE) {
1823 LOG_ERROR <<
"could not delete " << target_.filename() <<
" from sql storage";
1832 const boost::filesystem::path& image_path,
const uintmax_t& start_from = 0)
1833 : db_path_(db_path), target_(std::move(target)) {
1834 stream_.open(image_path.string(), std::ofstream::out | std::ofstream::app);
1835 if (!stream_.good()) {
1836 LOG_ERROR <<
"Could not open image for write: " << image_path;
1840 written_size_ = start_from;
1842 boost::filesystem::path db_path_;
1844 std::ofstream stream_;
1848 std::unique_ptr<StorageTargetWHandle> SQLStorage::allocateTargetFile(
const Uptane::Target& target) {
1849 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(*
this, target));
1855 : db_path_(storage.dbPath()), target_(std::move(target)), size_(0) {
1858 auto exists = storage.checkTargetFile(target_);
1860 LOG_ERROR <<
"File " << target_.filename() <<
" with expected hash not found in the database!";
1864 size_ = exists->first;
1865 partial_ = size_ < target_.length();
1866 image_path_ = storage.images_path_ / exists->second;
1867 stream_.open(image_path_.string());
1868 if (!stream_.good()) {
1869 LOG_ERROR <<
"Could not open image: " << storage.images_path_ / target_.filename();
1876 uintmax_t rsize()
const override {
return size_; }
1878 size_t rread(uint8_t* buf,
size_t size)
override {
1879 stream_.read(reinterpret_cast<char*>(buf), static_cast<std::streamsize>(size));
1880 return static_cast<size_t>(stream_.gcount());
1883 void rclose() noexcept
override {
1884 if (stream_.is_open()) {
1889 bool isPartial()
const noexcept
override {
return partial_; }
1890 std::unique_ptr<StorageTargetWHandle> toWriteHandle()
override {
1891 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(db_path_, target_, image_path_, size_));
1895 boost::filesystem::path db_path_;
1898 bool partial_{
false};
1899 boost::filesystem::path image_path_;
1900 std::ifstream stream_;
1903 std::unique_ptr<StorageTargetRHandle> SQLStorage::openTargetFile(
const Uptane::Target& target)
const {
1904 return std_::make_unique<SQLTargetRHandle>(*
this, target);
1907 std::vector<Uptane::Target> SQLStorage::getTargetFiles() {
1910 auto statement = db.prepareStatement<>(
"SELECT targetname, filename, sha256, sha512 FROM target_images;");
1912 std::vector<Uptane::Target> v;
1914 int result = statement.step();
1915 while (result != SQLITE_DONE) {
1916 if (result != SQLITE_ROW) {
1917 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1918 throw std::runtime_error(
"Error getting target files");
1921 auto tname = statement.get_result_col_str(0).value();
1922 auto fname = statement.get_result_col_str(1).value();
1923 auto tsize = boost::filesystem::file_size(images_path_ / fname);
1924 auto sha256 = statement.get_result_col_str(2).value();
1925 auto sha512 = statement.get_result_col_str(3).value();
1927 std::vector<Hash> hashes;
1928 if (!sha256.empty()) {
1929 hashes.emplace_back(Hash::Type::kSha256, sha256);
1931 if (!sha512.empty()) {
1932 hashes.emplace_back(Hash::Type::kSha512, sha512);
1934 v.emplace_back(tname, Uptane::EcuMap{}, hashes, tsize);
1936 result = statement.step();
1942 void SQLStorage::removeTargetFile(
const std::string& target_name) {
1945 db.beginTransaction();
1948 db.prepareStatement<std::string>(
"SELECT filename FROM target_images WHERE targetname = ?;", target_name);
1950 if (statement.step() != SQLITE_ROW) {
1951 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1952 throw std::runtime_error(
"Could not find target file");
1955 std::string filename = statement.get_result_col_str(0).value();
1957 statement = db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", target_name);
1959 if (statement.step() != SQLITE_DONE) {
1960 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1961 throw std::runtime_error(
"Could not remove target file");
1964 boost::filesystem::remove(images_path_ / filename);
1965 }
catch (std::exception& e) {
1966 LOG_ERROR <<
"Could not remove target file";
1970 db.commitTransaction();
1973 void SQLStorage::cleanUp() { boost::filesystem::remove_all(dbPath()); }
Metadata version numbers.
The hash of a file or Uptane metadata.
Results of libaktualizr API calls.