db: add some error checking to database state write

Make errors more observable. Unfortunately full rollback is
non-trivial to implement. This is something to be fixed with
the v3 database format.
cute-signatures
Timo Teräs 2021-07-26 14:01:05 +03:00
parent d212aca070
commit 083ea5a13b
2 changed files with 51 additions and 40 deletions

View File

@ -351,7 +351,7 @@ int apk_solver_commit_changeset(struct apk_database *db,
all_done: all_done:
apk_dependency_array_copy(&db->world, world); apk_dependency_array_copy(&db->world, world);
apk_db_write_config(db); if (apk_db_write_config(db) != 0) errors++;
run_commit_hooks(db, POST_COMMIT_HOOK); run_commit_hooks(db, POST_COMMIT_HOOK);
if (!db->performing_self_upgrade) { if (!db->performing_self_upgrade) {

View File

@ -930,14 +930,14 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
struct hlist_node *c1, *c2; struct hlist_node *c1, *c2;
char buf[1024+PATH_MAX]; char buf[1024+PATH_MAX];
apk_blob_t bbuf = APK_BLOB_BUF(buf); apk_blob_t bbuf = APK_BLOB_BUF(buf);
int r; int r = 0;
if (IS_ERR(os)) return PTR_ERR(os);
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) { list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
pkg = ipkg->pkg; pkg = ipkg->pkg;
r = apk_pkg_write_index_entry(pkg, os); r = apk_pkg_write_index_entry(pkg, os);
if (r < 0) { if (r < 0) goto err;
return r;
}
if (ipkg->replaces->num) { if (ipkg->replaces->num) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("r:")); apk_blob_push_blob(&bbuf, APK_BLOB_STR("r:"));
@ -973,9 +973,12 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
apk_blob_push_db_acl(&bbuf, 'M', diri->acl); apk_blob_push_db_acl(&bbuf, 'M', diri->acl);
bbuf = apk_blob_pushed(APK_BLOB_BUF(buf), bbuf); bbuf = apk_blob_pushed(APK_BLOB_BUF(buf), bbuf);
if (APK_BLOB_IS_NULL(bbuf)) return -ENOBUFS; if (APK_BLOB_IS_NULL(bbuf)) {
r = -ENOBUFS;
goto err;
}
r = apk_ostream_write(os, bbuf.ptr, bbuf.len); r = apk_ostream_write(os, bbuf.ptr, bbuf.len);
if (r < 0) return r; if (r < 0) goto err;
bbuf = APK_BLOB_BUF(buf); bbuf = APK_BLOB_BUF(buf);
hlist_for_each_entry(file, c2, &diri->owned_files, diri_files_list) { hlist_for_each_entry(file, c2, &diri->owned_files, diri_files_list) {
@ -993,17 +996,21 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
} }
bbuf = apk_blob_pushed(APK_BLOB_BUF(buf), bbuf); bbuf = apk_blob_pushed(APK_BLOB_BUF(buf), bbuf);
if (APK_BLOB_IS_NULL(bbuf)) return -ENOBUFS; if (APK_BLOB_IS_NULL(bbuf)) {
r = -ENOBUFS;
goto err;
}
r = apk_ostream_write(os, bbuf.ptr, bbuf.len); r = apk_ostream_write(os, bbuf.ptr, bbuf.len);
if (r < 0) return r; if (r < 0) goto err;
bbuf = APK_BLOB_BUF(buf); bbuf = APK_BLOB_BUF(buf);
} }
} }
r = apk_ostream_write(os, "\n", 1); r = apk_ostream_write(os, "\n", 1);
if (r < 0) return r; if (r < 0) goto err;
} }
err:
return 0; if (r < 0) apk_ostream_cancel(os, r);
return apk_ostream_close(os);
} }
static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os) static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os)
@ -1016,6 +1023,8 @@ static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os
int r, i; int r, i;
time_t now = time(NULL); time_t now = time(NULL);
if (IS_ERR(os)) return PTR_ERR(os);
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) { list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
pkg = ipkg->pkg; pkg = ipkg->pkg;
@ -1042,12 +1051,15 @@ static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os
apk_blob_push_blob(&bfn, APK_BLOB_PTR_LEN("", 1)); apk_blob_push_blob(&bfn, APK_BLOB_PTR_LEN("", 1));
r = apk_tar_write_entry(os, &fi, ipkg->script[i].ptr); r = apk_tar_write_entry(os, &fi, ipkg->script[i].ptr);
if (r < 0) if (r < 0) {
return r; apk_ostream_cancel(os, -APKE_V2DB_FORMAT);
break;
}
} }
} }
return apk_tar_write_entry(os, NULL, NULL); apk_tar_write_entry(os, NULL, NULL);
return apk_ostream_close(os);
} }
static int apk_read_script_archive_entry(void *ctx, static int apk_read_script_archive_entry(void *ctx,
@ -1101,13 +1113,15 @@ static int parse_triggers(void *ctx, apk_blob_t blob)
return 0; return 0;
} }
static void apk_db_triggers_write(struct apk_database *db, struct apk_ostream *os) static int apk_db_triggers_write(struct apk_database *db, struct apk_ostream *os)
{ {
struct apk_installed_package *ipkg; struct apk_installed_package *ipkg;
char buf[APK_BLOB_CHECKSUM_BUF]; char buf[APK_BLOB_CHECKSUM_BUF];
apk_blob_t bfn; apk_blob_t bfn;
char **trigger; char **trigger;
if (IS_ERR(os)) return PTR_ERR(os);
list_for_each_entry(ipkg, &db->installed.triggers, trigger_pkgs_list) { list_for_each_entry(ipkg, &db->installed.triggers, trigger_pkgs_list) {
bfn = APK_BLOB_BUF(buf); bfn = APK_BLOB_BUF(buf);
apk_blob_push_csum(&bfn, &ipkg->pkg->csum); apk_blob_push_csum(&bfn, &ipkg->pkg->csum);
@ -1120,6 +1134,7 @@ static void apk_db_triggers_write(struct apk_database *db, struct apk_ostream *o
} }
apk_ostream_write(os, "\n", 1); apk_ostream_write(os, "\n", 1);
} }
return apk_ostream_close(os);
} }
static int apk_db_triggers_read(struct apk_database *db, struct apk_istream *is) static int apk_db_triggers_read(struct apk_database *db, struct apk_istream *is)
@ -1737,7 +1752,7 @@ int apk_db_write_config(struct apk_database *db)
{ {
struct apk_out *out = &db->ctx->out; struct apk_out *out = &db->ctx->out;
struct apk_ostream *os; struct apk_ostream *os;
int r; int r, rr = 0;
if ((db->ctx->flags & APK_SIMULATE) || db->ctx->root == NULL) if ((db->ctx->flags & APK_SIMULATE) || db->ctx->root == NULL)
return 0; return 0;
@ -1748,33 +1763,30 @@ int apk_db_write_config(struct apk_database *db)
} }
os = apk_ostream_to_file(db->root_fd, apk_world_file, 0644); os = apk_ostream_to_file(db->root_fd, apk_world_file, 0644);
if (IS_ERR_OR_NULL(os)) return PTR_ERR(os); if (!IS_ERR(os)) {
apk_deps_write(db, db->world, os, APK_BLOB_PTR_LEN("\n", 1)); apk_deps_write(db, db->world, os, APK_BLOB_PTR_LEN("\n", 1));
apk_ostream_write(os, "\n", 1); apk_ostream_write(os, "\n", 1);
r = apk_ostream_close(os); r = apk_ostream_close(os);
if (r < 0) return r; if (r && !rr) rr = r;
}
os = apk_ostream_to_file(db->root_fd, apk_installed_file, 0644); r = apk_db_write_fdb(db, apk_ostream_to_file(db->root_fd, apk_installed_file, 0644));
if (IS_ERR_OR_NULL(os)) return PTR_ERR(os); if (r < 0 && !rr) rr = r;
apk_db_write_fdb(db, os);
r = apk_ostream_close(os);
if (r < 0) return r;
os = apk_ostream_to_file(db->root_fd, apk_scripts_file, 0644); r = apk_db_scriptdb_write(db, apk_ostream_to_file(db->root_fd, apk_scripts_file, 0644));
if (IS_ERR_OR_NULL(os)) return PTR_ERR(os); if (r < 0 && !rr) rr = r;
apk_db_scriptdb_write(db, os);
r = apk_ostream_close(os);
if (r < 0) return r;
apk_db_index_write_nr_cache(db); r = apk_db_index_write_nr_cache(db);
if (r < 0 && !rr) rr = r;
os = apk_ostream_to_file(db->root_fd, apk_triggers_file, 0644); r = apk_db_triggers_write(db, apk_ostream_to_file(db->root_fd, apk_triggers_file, 0644));
if (IS_ERR_OR_NULL(os)) return PTR_ERR(os); if (r < 0 && !rr) rr = r;
apk_db_triggers_write(db, os);
r = apk_ostream_close(os);
if (r < 0) return r;
return 0; if (rr) {
apk_err(out, "System state may be inconsistent: failed to write database: %s",
apk_error_str(rr));
}
return rr;
} }
void apk_db_close(struct apk_database *db) void apk_db_close(struct apk_database *db)
@ -2289,7 +2301,6 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t _repository)
apk_url_parse(&urlp, repo->url); apk_url_parse(&urlp, repo->url);
apk_warn(out, "Ignoring " URL_FMT ": %s", URL_PRINTF(urlp), apk_error_str(r)); apk_warn(out, "Ignoring " URL_FMT ": %s", URL_PRINTF(urlp), apk_error_str(r));
db->available_repos &= ~BIT(repo_num); db->available_repos &= ~BIT(repo_num);
r = 0;
} else { } else {
db->repo_tags[tag_id].allowed_repos |= BIT(repo_num); db->repo_tags[tag_id].allowed_repos |= BIT(repo_num);
} }