summaryrefslogtreecommitdiff
path: root/src/database.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2022-02-01 17:44:49 +0200
committerTimo Teräs <timo.teras@iki.fi>2022-02-21 10:24:05 +0200
commit9089edcc44fe12003f9d13d5868fa26b2e980a18 (patch)
tree918a6ebd381655ed196dfd6f3977753c59fd41cd /src/database.c
parent9e4dd29f547c67eb6b5723f8b9e1093cd5ef9b60 (diff)
downloadapk-tools-9089edcc44fe12003f9d13d5868fa26b2e980a18.tar.gz
apk-tools-9089edcc44fe12003f9d13d5868fa26b2e980a18.tar.bz2
apk-tools-9089edcc44fe12003f9d13d5868fa26b2e980a18.tar.xz
apk-tools-9089edcc44fe12003f9d13d5868fa26b2e980a18.zip
db: prepare database writing for layers
Diffstat (limited to 'src/database.c')
-rw-r--r--src/database.c307
1 files changed, 172 insertions, 135 deletions
diff --git a/src/database.c b/src/database.c
index a979a71..781cf99 100644
--- a/src/database.c
+++ b/src/database.c
@@ -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"));
}
-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;
+ struct apk_package *pkg = ipkg->pkg;
struct apk_db_dir_instance *diri;
struct apk_db_file *file;
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);
- list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
- pkg = ipkg->pkg;
- r = apk_pkg_write_index_entry(pkg, os);
+ r = apk_pkg_write_index_entry(pkg, os);
+ if (r < 0) goto err;
+
+ 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;
+ bbuf = APK_BLOB_BUF(buf);
- 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));
+ 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 (diri->acl != apk_default_acl_dir)
- apk_blob_push_db_acl(&bbuf, 'M', diri->acl);
+ 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)) {
@@ -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);
if (r < 0) goto err;
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:
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;
+ struct apk_package *pkg = ipkg->pkg;
struct apk_file_info fi;
char filename[256];
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);
- list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
- pkg = ipkg->pkg;
-
- for (i = 0; i < APK_SCRIPT_MAX; i++) {
- if (ipkg->script[i].ptr == NULL)
- continue;
-
- fi = (struct apk_file_info) {
- .name = filename,
- .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));
-
- r = apk_tar_write_entry(os, &fi, ipkg->script[i].ptr);
- if (r < 0) {
- apk_ostream_cancel(os, -APKE_V2DB_FORMAT);
- break;
- }
+ for (i = 0; i < APK_SCRIPT_MAX; i++) {
+ if (!ipkg->script[i].ptr) continue;
+
+ fi = (struct apk_file_info) {
+ .name = filename,
+ .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));
+
+ 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 apk_ostream_close(os);
+ return r;
}
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;
}
-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];
apk_blob_t bfn;
char **trigger;
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);
- apk_blob_push_csum(&bfn, &ipkg->pkg->csum);
- bfn = apk_blob_pushed(APK_BLOB_BUF(buf), bfn);
- apk_ostream_write(os, bfn.ptr, bfn.len);
-
- foreach_array_item(trigger, ipkg->triggers) {
- apk_ostream_write(os, " ", 1);
- apk_ostream_write_string(os, *trigger);
- }
- apk_ostream_write(os, "\n", 1);
+ bfn = APK_BLOB_BUF(buf);
+ apk_blob_push_csum(&bfn, &ipkg->pkg->csum);
+ bfn = apk_blob_pushed(APK_BLOB_BUF(buf), bfn);
+ apk_ostream_write(os, bfn.ptr, bfn.len);
+
+ foreach_array_item(trigger, ipkg->triggers) {
+ apk_ostream_write(os, " ", 1);
+ apk_ostream_write_string(os, *trigger);
}
- 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)
@@ -1199,7 +1185,7 @@ static int apk_db_read_layer(struct apk_database *db, unsigned layer)
blob = apk_blob_trim(world);
apk_blob_pull_deps(&blob, db, &db->world);
free(world.ptr);
- } else {
+ } else if (layer == APK_DB_LAYER_ROOT) {
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++) {
r = apk_db_read_layer(db, i);
if (r) {
- if (i != 0) continue;
- if (r == -ENOENT && (ac->open_flags & APK_OPENF_CREATE)) continue;
- msg = "Unable to read database";
- goto ret_r;
+ if (i != APK_DB_LAYER_ROOT) continue;
+ if (!(r == -ENOENT && (ac->open_flags & APK_OPENF_CREATE))) {
+ msg = "Unable to read database";
+ goto ret_r;
+ }
}
db->active_layers |= BIT(i);
}
@@ -1810,10 +1797,74 @@ struct write_ctx {
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)
{
struct apk_out *out = &db->ctx->out;
- struct apk_ostream *os;
int r, rr = 0;
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)
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);
- 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;
- }
-
- 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_write_layers(db);
+ if (!rr ) rr = r;
r = apk_db_index_write_nr_cache(db);
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) {
apk_err(out, "System state may be inconsistent: failed to write database: %s",
apk_error_str(rr));