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:
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);
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;
char buf[1024+PATH_MAX];
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) {
pkg = ipkg->pkg;
r = apk_pkg_write_index_entry(pkg, os);
if (r < 0) {
return r;
}
if (r < 0) goto err;
if (ipkg->replaces->num) {
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);
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);
if (r < 0) return r;
if (r < 0) goto err;
bbuf = APK_BLOB_BUF(buf);
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);
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);
if (r < 0) return r;
if (r < 0) goto err;
bbuf = APK_BLOB_BUF(buf);
}
}
r = apk_ostream_write(os, "\n", 1);
if (r < 0) return r;
if (r < 0) goto err;
}
return 0;
err:
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)
@ -1016,6 +1023,8 @@ static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os
int r, i;
time_t now = time(NULL);
if (IS_ERR(os)) return PTR_ERR(os);
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
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));
r = apk_tar_write_entry(os, &fi, ipkg->script[i].ptr);
if (r < 0)
return r;
if (r < 0) {
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,
@ -1101,13 +1113,15 @@ static int parse_triggers(void *ctx, apk_blob_t blob)
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;
char buf[APK_BLOB_CHECKSUM_BUF];
apk_blob_t bfn;
char **trigger;
if (IS_ERR(os)) return PTR_ERR(os);
list_for_each_entry(ipkg, &db->installed.triggers, trigger_pkgs_list) {
bfn = APK_BLOB_BUF(buf);
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);
}
return apk_ostream_close(os);
}
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_ostream *os;
int r;
int r, rr = 0;
if ((db->ctx->flags & APK_SIMULATE) || db->ctx->root == NULL)
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);
if (IS_ERR_OR_NULL(os)) return PTR_ERR(os);
apk_deps_write(db, db->world, os, APK_BLOB_PTR_LEN("\n", 1));
apk_ostream_write(os, "\n", 1);
r = apk_ostream_close(os);
if (r < 0) return r;
if (!IS_ERR(os)) {
apk_deps_write(db, db->world, os, APK_BLOB_PTR_LEN("\n", 1));
apk_ostream_write(os, "\n", 1);
r = apk_ostream_close(os);
if (r && !rr) rr = r;
}
os = apk_ostream_to_file(db->root_fd, apk_installed_file, 0644);
if (IS_ERR_OR_NULL(os)) return PTR_ERR(os);
apk_db_write_fdb(db, os);
r = apk_ostream_close(os);
if (r < 0) return r;
r = apk_db_write_fdb(db, apk_ostream_to_file(db->root_fd, apk_installed_file, 0644));
if (r < 0 && !rr) rr = r;
os = apk_ostream_to_file(db->root_fd, apk_scripts_file, 0644);
if (IS_ERR_OR_NULL(os)) return PTR_ERR(os);
apk_db_scriptdb_write(db, os);
r = apk_ostream_close(os);
if (r < 0) return r;
r = apk_db_scriptdb_write(db, apk_ostream_to_file(db->root_fd, apk_scripts_file, 0644));
if (r < 0 && !rr) rr = 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);
if (IS_ERR_OR_NULL(os)) return PTR_ERR(os);
apk_db_triggers_write(db, os);
r = apk_ostream_close(os);
if (r < 0) return r;
r = apk_db_triggers_write(db, apk_ostream_to_file(db->root_fd, apk_triggers_file, 0644));
if (r < 0 && !rr) rr = 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)
@ -2289,7 +2301,6 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t _repository)
apk_url_parse(&urlp, repo->url);
apk_warn(out, "Ignoring " URL_FMT ": %s", URL_PRINTF(urlp), apk_error_str(r));
db->available_repos &= ~BIT(repo_num);
r = 0;
} else {
db->repo_tags[tag_id].allowed_repos |= BIT(repo_num);
}