+ fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db));
+ abort();
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW) {
+ bool ok = settings.ParseFromArray(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
+ if (!ok) {
+ fprintf(stderr, "State in database is corrupted!\n");
+ abort();
+ }
+ } else if (ret != SQLITE_DONE) {
+ fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db));
+ abort();
+ }
+
+ ret = sqlite3_finalize(stmt);
+ if (ret != SQLITE_OK) {
+ fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db));
+ abort();
+ }
+
+ return settings;
+}
+
+void DB::store_settings(const SettingsProto &settings)
+{
+ string serialized;
+ settings.SerializeToString(&serialized);
+
+ int ret = sqlite3_exec(db, "BEGIN", nullptr, nullptr, nullptr);
+ if (ret != SQLITE_OK) {
+ fprintf(stderr, "BEGIN: %s\n", sqlite3_errmsg(db));
+ abort();
+ }
+
+ sqlite3_stmt *stmt;
+ ret = sqlite3_prepare_v2(db, "REPLACE INTO settings VALUES (?)", -1, &stmt, 0);
+ if (ret != SQLITE_OK) {
+ fprintf(stderr, "REPLACE prepare: %s\n", sqlite3_errmsg(db));
+ abort();