db: prepare database writing for layers

cute-signatures
Timo Teräs 2022-02-01 17:44:49 +02:00
parent 9e4dd29f54
commit 9089edcc44
1 changed files with 169 additions and 132 deletions

View File

@ -931,10 +931,9 @@ static void apk_blob_push_db_acl(apk_blob_t *b, char field, struct apk_db_acl *a
apk_blob_push_blob(b, APK_BLOB_STR("\n")); apk_blob_push_blob(b, APK_BLOB_STR("\n"));
} }
static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) static int apk_db_fdb_write(struct apk_database *db, struct apk_installed_package *ipkg, struct apk_ostream *os)
{ {
struct apk_installed_package *ipkg; struct apk_package *pkg = ipkg->pkg;
struct apk_package *pkg;
struct apk_db_dir_instance *diri; struct apk_db_dir_instance *diri;
struct apk_db_file *file; struct apk_db_file *file;
struct hlist_node *c1, *c2; struct hlist_node *c1, *c2;
@ -944,45 +943,66 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
if (IS_ERR(os)) return PTR_ERR(os); if (IS_ERR(os)) return PTR_ERR(os);
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) { r = apk_pkg_write_index_entry(pkg, os);
pkg = ipkg->pkg; if (r < 0) goto err;
r = apk_pkg_write_index_entry(pkg, os);
if (ipkg->replaces->num) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("r:"));
apk_blob_push_deps(&bbuf, db, ipkg->replaces);
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
if (ipkg->replaces_priority) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("q:"));
apk_blob_push_uint(&bbuf, ipkg->replaces_priority, 10);
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
if (ipkg->repository_tag) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("s:"));
apk_blob_push_blob(&bbuf, db->repo_tags[ipkg->repository_tag].plain_name);
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
if (ipkg->broken_files || ipkg->broken_script || ipkg->broken_xattr || ipkg->sha256_160) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("f:"));
if (ipkg->broken_files)
apk_blob_push_blob(&bbuf, APK_BLOB_STR("f"));
if (ipkg->broken_script)
apk_blob_push_blob(&bbuf, APK_BLOB_STR("s"));
if (ipkg->broken_xattr)
apk_blob_push_blob(&bbuf, APK_BLOB_STR("x"));
if (ipkg->sha256_160)
apk_blob_push_blob(&bbuf, APK_BLOB_STR("S"));
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
hlist_for_each_entry(diri, c1, &ipkg->owned_dirs, pkg_dirs_list) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("F:"));
apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(diri->dir->name, diri->dir->namelen));
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
if (diri->acl != apk_default_acl_dir)
apk_blob_push_db_acl(&bbuf, 'M', diri->acl);
bbuf = apk_blob_pushed(APK_BLOB_BUF(buf), bbuf);
if (APK_BLOB_IS_NULL(bbuf)) {
r = -ENOBUFS;
goto err;
}
r = apk_ostream_write(os, bbuf.ptr, bbuf.len);
if (r < 0) goto err; if (r < 0) goto err;
bbuf = APK_BLOB_BUF(buf);
if (ipkg->replaces->num) { hlist_for_each_entry(file, c2, &diri->owned_files, diri_files_list) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("r:")); apk_blob_push_blob(&bbuf, APK_BLOB_STR("R:"));
apk_blob_push_deps(&bbuf, db, ipkg->replaces); apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(file->name, file->namelen));
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
if (ipkg->replaces_priority) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("q:"));
apk_blob_push_uint(&bbuf, ipkg->replaces_priority, 10);
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
if (ipkg->repository_tag) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("s:"));
apk_blob_push_blob(&bbuf, db->repo_tags[ipkg->repository_tag].plain_name);
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
if (ipkg->broken_files || ipkg->broken_script || ipkg->broken_xattr || ipkg->sha256_160) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("f:"));
if (ipkg->broken_files)
apk_blob_push_blob(&bbuf, APK_BLOB_STR("f"));
if (ipkg->broken_script)
apk_blob_push_blob(&bbuf, APK_BLOB_STR("s"));
if (ipkg->broken_xattr)
apk_blob_push_blob(&bbuf, APK_BLOB_STR("x"));
if (ipkg->sha256_160)
apk_blob_push_blob(&bbuf, APK_BLOB_STR("S"));
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
hlist_for_each_entry(diri, c1, &ipkg->owned_dirs, pkg_dirs_list) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("F:"));
apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(diri->dir->name, diri->dir->namelen));
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
if (diri->acl != apk_default_acl_dir) if (file->acl != apk_default_acl_file)
apk_blob_push_db_acl(&bbuf, 'M', diri->acl); apk_blob_push_db_acl(&bbuf, 'a', file->acl);
if (file->csum.type != APK_CHECKSUM_NONE) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("Z:"));
apk_blob_push_csum(&bbuf, &file->csum);
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
bbuf = apk_blob_pushed(APK_BLOB_BUF(buf), bbuf); bbuf = apk_blob_pushed(APK_BLOB_BUF(buf), bbuf);
if (APK_BLOB_IS_NULL(bbuf)) { if (APK_BLOB_IS_NULL(bbuf)) {
@ -992,43 +1012,17 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
r = apk_ostream_write(os, bbuf.ptr, bbuf.len); r = apk_ostream_write(os, bbuf.ptr, bbuf.len);
if (r < 0) goto err; 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) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("R:"));
apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(file->name, file->namelen));
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
if (file->acl != apk_default_acl_file)
apk_blob_push_db_acl(&bbuf, 'a', file->acl);
if (file->csum.type != APK_CHECKSUM_NONE) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("Z:"));
apk_blob_push_csum(&bbuf, &file->csum);
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
bbuf = apk_blob_pushed(APK_BLOB_BUF(buf), bbuf);
if (APK_BLOB_IS_NULL(bbuf)) {
r = -ENOBUFS;
goto err;
}
r = apk_ostream_write(os, bbuf.ptr, bbuf.len);
if (r < 0) goto err;
bbuf = APK_BLOB_BUF(buf);
}
} }
r = apk_ostream_write(os, "\n", 1);
if (r < 0) goto err;
} }
r = apk_ostream_write(os, "\n", 1);
err: err:
if (r < 0) apk_ostream_cancel(os, r); if (r < 0) apk_ostream_cancel(os, r);
return apk_ostream_close(os); return r;
} }
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_installed_package *ipkg, struct apk_ostream *os)
{ {
struct apk_installed_package *ipkg; struct apk_package *pkg = ipkg->pkg;
struct apk_package *pkg;
struct apk_file_info fi; struct apk_file_info fi;
char filename[256]; char filename[256];
apk_blob_t bfn; apk_blob_t bfn;
@ -1036,40 +1030,34 @@ static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os
if (IS_ERR(os)) return PTR_ERR(os); if (IS_ERR(os)) return PTR_ERR(os);
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) { for (i = 0; i < APK_SCRIPT_MAX; i++) {
pkg = ipkg->pkg; if (!ipkg->script[i].ptr) continue;
for (i = 0; i < APK_SCRIPT_MAX; i++) { fi = (struct apk_file_info) {
if (ipkg->script[i].ptr == NULL) .name = filename,
continue; .size = ipkg->script[i].len,
.mode = 0755 | S_IFREG,
};
/* The scripts db expects file names in format:
* pkg-version.<hexdump of package checksum>.action */
bfn = APK_BLOB_BUF(filename);
apk_blob_push_blob(&bfn, APK_BLOB_STR(pkg->name->name));
apk_blob_push_blob(&bfn, APK_BLOB_STR("-"));
apk_blob_push_blob(&bfn, *pkg->version);
apk_blob_push_blob(&bfn, APK_BLOB_STR("."));
apk_blob_push_csum(&bfn, &pkg->csum);
apk_blob_push_blob(&bfn, APK_BLOB_STR("."));
apk_blob_push_blob(&bfn, APK_BLOB_STR(apk_script_types[i]));
apk_blob_push_blob(&bfn, APK_BLOB_PTR_LEN("", 1));
fi = (struct apk_file_info) { r = apk_tar_write_entry(os, &fi, ipkg->script[i].ptr);
.name = filename, if (r < 0) {
.size = ipkg->script[i].len, apk_ostream_cancel(os, -APKE_V2DB_FORMAT);
.mode = 0755 | S_IFREG, break;
};
/* The scripts db expects file names in format:
* pkg-version.<hexdump of package checksum>.action */
bfn = APK_BLOB_BUF(filename);
apk_blob_push_blob(&bfn, APK_BLOB_STR(pkg->name->name));
apk_blob_push_blob(&bfn, APK_BLOB_STR("-"));
apk_blob_push_blob(&bfn, *pkg->version);
apk_blob_push_blob(&bfn, APK_BLOB_STR("."));
apk_blob_push_csum(&bfn, &pkg->csum);
apk_blob_push_blob(&bfn, APK_BLOB_STR("."));
apk_blob_push_blob(&bfn, APK_BLOB_STR(apk_script_types[i]));
apk_blob_push_blob(&bfn, APK_BLOB_PTR_LEN("", 1));
r = apk_tar_write_entry(os, &fi, ipkg->script[i].ptr);
if (r < 0) {
apk_ostream_cancel(os, -APKE_V2DB_FORMAT);
break;
}
} }
} }
apk_tar_write_entry(os, NULL, NULL); return r;
return apk_ostream_close(os);
} }
static int apk_read_script_archive_entry(void *ctx, static int apk_read_script_archive_entry(void *ctx,
@ -1123,28 +1111,26 @@ static int parse_triggers(void *ctx, apk_blob_t blob)
return 0; return 0;
} }
static int apk_db_triggers_write(struct apk_database *db, struct apk_ostream *os) static int apk_db_triggers_write(struct apk_database *db, struct apk_installed_package *ipkg, struct apk_ostream *os)
{ {
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); if (IS_ERR(os)) return PTR_ERR(os);
if (!ipkg->triggers || ipkg->triggers->num == 0) return 0;
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); bfn = apk_blob_pushed(APK_BLOB_BUF(buf), bfn);
bfn = apk_blob_pushed(APK_BLOB_BUF(buf), bfn); apk_ostream_write(os, bfn.ptr, bfn.len);
apk_ostream_write(os, bfn.ptr, bfn.len);
foreach_array_item(trigger, ipkg->triggers) { foreach_array_item(trigger, ipkg->triggers) {
apk_ostream_write(os, " ", 1); apk_ostream_write(os, " ", 1);
apk_ostream_write_string(os, *trigger); apk_ostream_write_string(os, *trigger);
}
apk_ostream_write(os, "\n", 1);
} }
return apk_ostream_close(os); apk_ostream_write(os, "\n", 1);
return 0;
} }
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)
@ -1199,7 +1185,7 @@ static int apk_db_read_layer(struct apk_database *db, unsigned layer)
blob = apk_blob_trim(world); blob = apk_blob_trim(world);
apk_blob_pull_deps(&blob, db, &db->world); apk_blob_pull_deps(&blob, db, &db->world);
free(world.ptr); free(world.ptr);
} else { } else if (layer == APK_DB_LAYER_ROOT) {
ret = -ENOENT; ret = -ENOENT;
} }
} }
@ -1747,10 +1733,11 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac)
for (i = 0; i < APK_DB_LAYER_NUM; i++) { for (i = 0; i < APK_DB_LAYER_NUM; i++) {
r = apk_db_read_layer(db, i); r = apk_db_read_layer(db, i);
if (r) { if (r) {
if (i != 0) continue; if (i != APK_DB_LAYER_ROOT) continue;
if (r == -ENOENT && (ac->open_flags & APK_OPENF_CREATE)) continue; if (!(r == -ENOENT && (ac->open_flags & APK_OPENF_CREATE))) {
msg = "Unable to read database"; msg = "Unable to read database";
goto ret_r; goto ret_r;
}
} }
db->active_layers |= BIT(i); db->active_layers |= BIT(i);
} }
@ -1810,10 +1797,74 @@ struct write_ctx {
int fd; int fd;
}; };
static int apk_db_write_layers(struct apk_database *db)
{
struct layer_data {
int fd;
struct apk_ostream *installed, *scripts, *triggers;
} layers[APK_DB_LAYER_NUM] = {0};
struct apk_installed_package *ipkg;
struct apk_ostream *os;
int i, r, rr = 0;
for (i = 0; i < APK_DB_LAYER_NUM; i++) {
struct layer_data *ld = &layers[i];
if (!(db->active_layers & BIT(i))) continue;
ld->fd = openat(db->root_fd, apk_db_layer_name(i), O_RDONLY | O_CLOEXEC);
if (ld->fd < 0) {
if (i == 0) return -errno;
continue;
}
ld->installed = apk_ostream_to_file(ld->fd, "installed", 0644);
ld->scripts = apk_ostream_to_file(ld->fd, "scripts.tar", 0644);
ld->triggers = apk_ostream_to_file(ld->fd, "triggers", 0644);
}
os = apk_ostream_to_file(db->root_fd, apk_world_file, 0644);
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 (!rr) rr = r;
}
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
struct layer_data *ld = &layers[ipkg->pkg->layer];
if (!ld->fd) continue;
apk_db_fdb_write(db, ipkg, ld->installed);
apk_db_scriptdb_write(db, ipkg, ld->scripts);
apk_db_triggers_write(db, ipkg, ld->triggers);
}
for (i = 0; i < APK_DB_LAYER_NUM; i++) {
struct layer_data *ld = &layers[i];
if (!(db->active_layers & BIT(i))) continue;
if (!IS_ERR(ld->installed))
r = apk_ostream_close(ld->installed);
else r = PTR_ERR(ld->installed);
if (!rr) rr = r;
if (!IS_ERR(ld->scripts)) {
apk_tar_write_entry(ld->scripts, NULL, NULL);
r = apk_ostream_close(ld->scripts);
} else r = PTR_ERR(ld->scripts);
if (!rr) rr = r;
if (!IS_ERR(ld->triggers))
r = apk_ostream_close(ld->triggers);
else r = PTR_ERR(ld->triggers);
if (!rr) rr = r;
close(ld->fd);
}
return rr;
}
int apk_db_write_config(struct apk_database *db) 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;
int r, rr = 0; int r, rr = 0;
if ((db->ctx->flags & APK_SIMULATE) || db->ctx->root == NULL) if ((db->ctx->flags & APK_SIMULATE) || db->ctx->root == NULL)
@ -1837,26 +1888,12 @@ int apk_db_write_config(struct apk_database *db)
if (db->write_arch) if (db->write_arch)
apk_blob_to_file(db->root_fd, apk_arch_file, *db->arch, APK_BTF_ADD_EOL); apk_blob_to_file(db->root_fd, apk_arch_file, *db->arch, APK_BTF_ADD_EOL);
os = apk_ostream_to_file(db->root_fd, apk_world_file, 0644); r = apk_db_write_layers(db);
if (!IS_ERR(os)) { if (!rr ) rr = r;
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;
}
r = apk_db_write_fdb(db, apk_ostream_to_file(db->root_fd, apk_installed_file, 0644));
if (r < 0 && !rr) rr = r;
r = apk_db_scriptdb_write(db, apk_ostream_to_file(db->root_fd, apk_scripts_file, 0644));
if (r < 0 && !rr) rr = r;
r = apk_db_index_write_nr_cache(db); r = apk_db_index_write_nr_cache(db);
if (r < 0 && !rr) rr = r; if (r < 0 && !rr) rr = r;
r = apk_db_triggers_write(db, apk_ostream_to_file(db->root_fd, apk_triggers_file, 0644));
if (r < 0 && !rr) rr = r;
if (rr) { if (rr) {
apk_err(out, "System state may be inconsistent: failed to write database: %s", apk_err(out, "System state may be inconsistent: failed to write database: %s",
apk_error_str(rr)); apk_error_str(rr));