db: lazy create directories with --initdb

fixes #10778
cute-signatures
Timo Teräs 2021-11-15 15:31:56 +02:00
parent 061bd69b80
commit 83b71f0baf
3 changed files with 73 additions and 88 deletions

View File

@ -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;

View File

@ -25,7 +25,6 @@
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/statvfs.h>
#include <sys/sysmacros.h>
#include <linux/magic.h>
#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));

View File

@ -18,6 +18,7 @@
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include "apk_openssl.h"
#include <openssl/pem.h>
@ -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;
}