diff --git a/src/apk_database.h b/src/apk_database.h index 5958d6f..88107d3 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -115,6 +115,10 @@ struct apk_repository { apk_blob_t description; }; +#define APK_DB_LAYER_ROOT 0 +#define APK_DB_LAYER_UVOL 1 +#define APK_DB_LAYER_NUM 2 + #define APK_REPOSITORY_CACHED 0 #define APK_REPOSITORY_FIRST_CONFIGURED 1 @@ -138,6 +142,7 @@ struct apk_database { unsigned int repo_update_errors, repo_update_counter; unsigned int pending_triggers; unsigned int extract_flags; + unsigned int active_layers; int performing_self_upgrade : 1; int permanent : 1; int autoupdate : 1; @@ -189,6 +194,7 @@ struct apk_db_dir *apk_db_dir_query(struct apk_database *db, apk_blob_t name); struct apk_db_file *apk_db_file_query(struct apk_database *db, apk_blob_t dir, apk_blob_t name); +const char *apk_db_layer_name(int layer); void apk_db_init(struct apk_database *db); int apk_db_open(struct apk_database *db, struct apk_ctx *ctx); void apk_db_close(struct apk_database *db); diff --git a/src/apk_package.h b/src/apk_package.h index 1d9ca6e..e7e0a53 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -93,6 +93,7 @@ struct apk_package { unsigned marked : 1; unsigned uninstallable : 1; unsigned cached_non_repository : 1; + unsigned layer : 4; struct apk_checksum csum; }; APK_ARRAY(apk_package_array, struct apk_package *); diff --git a/src/app_policy.c b/src/app_policy.c index c026337..a927a5f 100644 --- a/src/app_policy.c +++ b/src/app_policy.c @@ -13,8 +13,6 @@ #include "apk_version.h" #include "apk_print.h" -extern const char * const apk_installed_file; - static void print_policy(struct apk_database *db, const char *match, struct apk_name *name, void *ctx) { struct apk_out *out = &db->ctx->out; @@ -44,8 +42,8 @@ zlib1g policy: if (num++ == 0) apk_out(out, "%s policy:", name->name); apk_out(out, " " BLOB_FMT ":", BLOB_PRINTF(*p->version)); - if (p->pkg->ipkg != NULL) - apk_out(out, " %s", apk_installed_file); + if (p->pkg->ipkg) + apk_out(out, " %s/installed", apk_db_layer_name(p->pkg->layer)); for (i = 0; i < db->num_repos; i++) { repo = &db->repos[i]; if (!(BIT(i) & p->pkg->repos)) diff --git a/src/database.c b/src/database.c index 72fd482..a979a71 100644 --- a/src/database.c +++ b/src/database.c @@ -56,9 +56,6 @@ static const char * const apk_static_cache_dir = "var/cache/apk"; static const char * const apk_world_file = "etc/apk/world"; static const char * const apk_arch_file = "etc/apk/arch"; static const char * const apk_lock_file = "lib/apk/db/lock"; -static const char * const apk_scripts_file = "lib/apk/db/scripts.tar"; -static const char * const apk_triggers_file = "lib/apk/db/triggers"; -const char * const apk_installed_file = "lib/apk/db/installed"; static struct apk_db_acl *apk_default_acl_dir, *apk_default_acl_file; @@ -759,7 +756,7 @@ err: return apk_istream_close(is); } -int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) +static int apk_db_fdb_read(struct apk_database *db, struct apk_istream *is, int repo, unsigned layer) { struct apk_out *out = &db->ctx->out; struct apk_package *pkg = NULL; @@ -812,6 +809,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) /* If no package, create new */ if (pkg == NULL) { pkg = apk_pkg_new(); + pkg->layer = layer; ipkg = NULL; diri = NULL; file_diri_node = NULL; @@ -911,6 +909,11 @@ err_fmt: return apk_istream_close(is); } +int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) +{ + return apk_db_fdb_read(db, is, repo, 0); +} + static void apk_blob_push_db_acl(apk_blob_t *b, char field, struct apk_db_acl *acl) { char hdr[2] = { field, ':' }; @@ -1171,21 +1174,29 @@ static int apk_db_triggers_read(struct apk_database *db, struct apk_istream *is) return apk_istream_close(is); } -static int apk_db_read_state(struct apk_database *db, int flags) +static int apk_db_read_layer(struct apk_database *db, unsigned layer) { apk_blob_t blob, world; - int r, ret = 0; + int r, fd, ret = 0, flags = db->ctx->open_flags; /* Read: - * 1. /etc/apk/world + * 1. world * 2. installed packages db * 3. triggers db * 4. scripts db */ + + fd = openat(db->root_fd, apk_db_layer_name(layer), O_RDONLY | O_CLOEXEC); + if (fd < 0) return -errno; + if (!(flags & APK_OPENF_NO_WORLD)) { - blob = world = apk_blob_from_file(db->root_fd, apk_world_file); - if (!APK_BLOB_IS_NULL(blob)) { - blob = apk_blob_trim(blob); + if (layer == APK_DB_LAYER_ROOT) + world = apk_blob_from_file(db->root_fd, apk_world_file); + else + world = apk_blob_from_file(fd, "world"); + + if (!APK_BLOB_IS_NULL(world)) { + blob = apk_blob_trim(world); apk_blob_pull_deps(&blob, db, &db->world); free(world.ptr); } else { @@ -1194,18 +1205,19 @@ static int apk_db_read_state(struct apk_database *db, int flags) } if (!(flags & APK_OPENF_NO_INSTALLED)) { - r = apk_db_index_read(db, apk_istream_from_file(db->root_fd, apk_installed_file), -1); - if (r && r != -ENOENT) ret = r; - r = apk_db_triggers_read(db, apk_istream_from_file(db->root_fd, apk_triggers_file)); - if (r && r != -ENOENT) ret = r; + r = apk_db_fdb_read(db, apk_istream_from_file(fd, "installed"), -1, layer); + if (!ret && r != -ENOENT) ret = r; + r = apk_db_triggers_read(db, apk_istream_from_file(fd, "triggers")); + if (!ret && r != -ENOENT) ret = r; } if (!(flags & APK_OPENF_NO_SCRIPTS)) { - r = apk_tar_parse(apk_istream_from_file(db->root_fd, apk_scripts_file), + r = apk_tar_parse(apk_istream_from_file(fd, "scripts.tar"), apk_read_script_archive_entry, db, db->id_cache); - if (r && r != -ENOENT) ret = r; + if (!ret && r != -ENOENT) ret = r; } + close(fd); return ret; } @@ -1616,6 +1628,17 @@ static void unmount_proc(struct apk_database *db) } #endif +const char *apk_db_layer_name(int layer) +{ + switch (layer) { + case APK_DB_LAYER_ROOT: return "lib/apk/db"; + case APK_DB_LAYER_UVOL: return "lib/apk/db-uvol"; + default: + assert("invalid layer"); + return 0; + } +} + void apk_db_init(struct apk_database *db) { memset(db, 0, sizeof(*db)); @@ -1637,7 +1660,7 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac) struct apk_out *out = &ac->out; const char *msg = NULL; apk_blob_t blob; - int r; + int r, i; apk_default_acl_dir = apk_db_acl_atomize(db, 0755, 0, 0); apk_default_acl_file = apk_db_acl_atomize(db, 0644, 0, 0); @@ -1721,10 +1744,15 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac) apk_db_read_overlay(db, apk_istream_from_fd(STDIN_FILENO)); } - r = apk_db_read_state(db, ac->open_flags); - if (r != 0 && !(r == -ENOENT && (ac->open_flags & APK_OPENF_CREATE))) { - msg = "Unable to read database state"; - goto ret_r; + 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; + } + db->active_layers |= BIT(i); } if (!(ac->open_flags & APK_OPENF_NO_INSTALLED_REPO)) {