diff --git a/src/apk_database.h b/src/apk_database.h index 587aefb..ff94762 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -141,6 +141,8 @@ struct apk_database { int performing_self_upgrade : 1; int permanent : 1; int autoupdate : 1; + int write_arch : 1; + int script_dirs_checked : 1; int open_complete : 1; int compat_newfeatures : 1; int compat_notinstallable : 1; diff --git a/src/database.c b/src/database.c index 535df5e..4bb23dd 100644 --- a/src/database.c +++ b/src/database.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include "apk_defines.h" @@ -1161,7 +1160,7 @@ static int apk_db_triggers_read(struct apk_database *db, struct apk_istream *is) static int apk_db_read_state(struct apk_database *db, int flags) { apk_blob_t blob, world; - int r; + int r, ret = 0; /* Read: * 1. /etc/apk/world @@ -1171,26 +1170,29 @@ static int apk_db_read_state(struct apk_database *db, int flags) */ if (!(flags & APK_OPENF_NO_WORLD)) { blob = world = apk_blob_from_file(db->root_fd, apk_world_file); - if (APK_BLOB_IS_NULL(blob)) return -ENOENT; - blob = apk_blob_trim(blob); - apk_blob_pull_deps(&blob, db, &db->world); - free(world.ptr); + if (!APK_BLOB_IS_NULL(blob)) { + blob = apk_blob_trim(blob); + apk_blob_pull_deps(&blob, db, &db->world); + free(world.ptr); + } else { + ret = -ENOENT; + } } 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) return r; + 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) return r; + if (r && r != -ENOENT) ret = r; } if (!(flags & APK_OPENF_NO_SCRIPTS)) { r = apk_tar_parse(apk_istream_from_file(db->root_fd, apk_scripts_file), apk_read_script_archive_entry, db, db->id_cache); - if (r && r != -ENOENT) return r; + if (r && r != -ENOENT) ret = r; } - return 0; + return ret; } struct index_write_ctx { @@ -1330,39 +1332,6 @@ static int add_protected_paths_from_file(void *ctx, int dirfd, const char *file) return 0; } -static int apk_db_create(struct apk_database *db) -{ - int fd; - - mkdirat(db->root_fd, "tmp", 01777); - mkdirat(db->root_fd, "dev", 0755); - mknodat(db->root_fd, "dev/null", S_IFCHR | 0666, makedev(1, 3)); - mknodat(db->root_fd, "dev/zero", S_IFCHR | 0666, makedev(1, 5)); - mknodat(db->root_fd, "dev/random", S_IFCHR | 0666, makedev(1, 8)); - mknodat(db->root_fd, "dev/urandom", S_IFCHR | 0666, makedev(1, 9)); - mknodat(db->root_fd, "dev/console", S_IFCHR | 0600, makedev(5, 1)); - mkdirat(db->root_fd, "etc", 0755); - mkdirat(db->root_fd, "etc/apk", 0755); - mkdirat(db->root_fd, "lib", 0755); - mkdirat(db->root_fd, "lib/apk", 0755); - mkdirat(db->root_fd, "lib/apk/db", 0755); - mkdirat(db->root_fd, "var", 0755); - mkdirat(db->root_fd, "var/cache", 0755); - mkdirat(db->root_fd, "var/cache/apk", 0755); - mkdirat(db->root_fd, "var/cache/misc", 0755); - - fd = openat(db->root_fd, apk_world_file, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644); - if (fd < 0) - return -errno; - close(fd); - fd = openat(db->root_fd, apk_installed_file, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644); - if (fd < 0) - return -errno; - close(fd); - - return 0; -} - static void handle_alarm(int sig) { } @@ -1531,7 +1500,7 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac) const char *msg = NULL; struct statfs stfs; apk_blob_t blob; - int r, fd, write_arch = FALSE; + int r, fd; apk_default_acl_dir = apk_db_acl_atomize(db, 0755, 0, 0); apk_default_acl_file = apk_db_acl_atomize(db, 0644, 0, 0); @@ -1556,7 +1525,7 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac) if (ac->root && ac->arch) { db->arch = apk_atomize(&db->atoms, APK_BLOB_STR(ac->arch)); - write_arch = TRUE; + db->write_arch = 1; } else { apk_blob_t arch; arch = apk_blob_from_file(db->root_fd, apk_arch_file); @@ -1565,48 +1534,37 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac) free(arch.ptr); } else { db->arch = apk_atomize(&db->atoms, APK_BLOB_STR(APK_DEFAULT_ARCH)); - write_arch = TRUE; + db->write_arch = 1; } } db->id_cache = apk_ctx_get_id_cache(ac); if (ac->open_flags & APK_OPENF_WRITE) { + msg = "Unable to lock database"; db->lock_fd = openat(db->root_fd, apk_lock_file, O_CREAT | O_RDWR | O_CLOEXEC, 0600); - if (db->lock_fd < 0 && errno == ENOENT && - (ac->open_flags & APK_OPENF_CREATE)) { - r = apk_db_create(db); - if (r != 0) { - msg = "Unable to create database"; - goto ret_r; - } - db->lock_fd = openat(db->root_fd, apk_lock_file, - O_CREAT | O_RDWR | O_CLOEXEC, 0600); - } - if (db->lock_fd < 0 || - flock(db->lock_fd, LOCK_EX | LOCK_NB) < 0) { - msg = "Unable to lock database"; - if (ac->lock_wait) { - struct sigaction sa, old_sa; - - apk_msg(out, "Waiting for repository lock"); - memset(&sa, 0, sizeof sa); - sa.sa_handler = handle_alarm; - sa.sa_flags = SA_ONESHOT; - sigaction(SIGALRM, &sa, &old_sa); - - alarm(ac->lock_wait); - if (flock(db->lock_fd, LOCK_EX) < 0) - goto ret_errno; - - alarm(0); - sigaction(SIGALRM, &old_sa, NULL); - } else + if (db->lock_fd < 0) { + if (!(ac->open_flags & APK_OPENF_CREATE)) goto ret_errno; + } else if (flock(db->lock_fd, LOCK_EX | LOCK_NB) < 0) { + struct sigaction sa, old_sa; + + if (!ac->lock_wait) goto ret_errno; + + apk_msg(out, "Waiting for repository lock"); + memset(&sa, 0, sizeof sa); + sa.sa_handler = handle_alarm; + sa.sa_flags = SA_ONESHOT; + sigaction(SIGALRM, &sa, &old_sa); + + alarm(ac->lock_wait); + if (flock(db->lock_fd, LOCK_EX) < 0) + goto ret_errno; + + alarm(0); + sigaction(SIGALRM, &old_sa, NULL); } - if (write_arch) - apk_blob_to_file(db->root_fd, apk_arch_file, *db->arch, APK_BTF_ADD_EOL); /* mount /proc */ if (asprintf(&db->root_proc_dir, "%s/proc", db->ctx->root) == -1) @@ -1655,6 +1613,7 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac) db->cache_dir = apk_static_cache_dir; db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC); if (db->cache_fd < 0) { + mkdirat(db->root_fd, "var", 0755); mkdirat(db->root_fd, "var/cache", 0755); mkdirat(db->root_fd, "var/cache/apk", 0755); db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC); @@ -1671,15 +1630,7 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac) } r = apk_db_read_state(db, ac->open_flags); - if (r == -ENOENT && (ac->open_flags & APK_OPENF_CREATE)) { - r = apk_db_create(db); - if (r != 0) { - msg = "Unable to create database"; - goto ret_r; - } - r = apk_db_read_state(db, ac->open_flags); - } - if (r != 0) { + if (r != 0 && !(r == -ENOENT && (ac->open_flags & APK_OPENF_CREATE))) { msg = "Unable to read database state"; goto ret_r; } @@ -1748,11 +1699,24 @@ int apk_db_write_config(struct apk_database *db) if ((db->ctx->flags & APK_SIMULATE) || db->ctx->root == NULL) return 0; - if (db->lock_fd == 0) { + if (db->ctx->open_flags & APK_OPENF_CREATE) { + if (faccessat(db->root_fd, "lib/apk/db", F_OK, 0) != 0) { + mkdirat(db->root_fd, "lib", 0755); + mkdirat(db->root_fd, "lib/apk", 0755); + mkdirat(db->root_fd, "lib/apk/db", 0755); + } + if (faccessat(db->root_fd, "etc/apk", F_OK, 0) != 0) { + mkdirat(db->root_fd, "etc", 0755); + mkdirat(db->root_fd, "etc/apk", 0755); + } + } else if (db->lock_fd == 0) { apk_err(out, "Refusing to write db without write lock!"); return -1; } + 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)); diff --git a/src/package.c b/src/package.c index 0b80b06..0ad0156 100644 --- a/src/package.c +++ b/src/package.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "apk_openssl.h" #include @@ -773,10 +774,28 @@ void apk_ipkg_run_script(struct apk_installed_package *ipkg, if ((db->ctx->flags & (APK_NO_SCRIPTS | APK_SIMULATE)) != 0) return; + if (!db->script_dirs_checked) { + db->script_dirs_checked = 1; + if (faccessat(db->root_fd, "tmp", F_OK, 0) != 0) + mkdirat(db->root_fd, "tmp", 01777); + if (faccessat(db->root_fd, "dev", F_OK, 0) != 0) { + mkdirat(db->root_fd, "dev", 0755); + mknodat(db->root_fd, "dev/null", S_IFCHR | 0666, makedev(1, 3)); + mknodat(db->root_fd, "dev/zero", S_IFCHR | 0666, makedev(1, 5)); + mknodat(db->root_fd, "dev/random", S_IFCHR | 0666, makedev(1, 8)); + mknodat(db->root_fd, "dev/urandom", S_IFCHR | 0666, makedev(1, 9)); + mknodat(db->root_fd, "dev/console", S_IFCHR | 0600, makedev(5, 1)); + } + if (faccessat(db->root_fd, "var/cache/misc", F_OK, 0) != 0) { + mkdirat(root_fd, "var", 0755); + mkdirat(root_fd, "var/cache", 0755); + mkdirat(root_fd, "var/cache/misc", 0755); + } + } + apk_msg(out, "Executing %s", &fn[15]); fd = openat(root_fd, fn, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0755); if (fd < 0) { - mkdirat(root_fd, "var/cache/misc", 0755); fd = openat(root_fd, fn, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0755); if (fd < 0) goto err_log; }