diff --git a/src/apk_io.h b/src/apk_io.h index d04638a..e7ca1f0 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -18,6 +18,7 @@ #include "apk_atom.h" #include "apk_crypto.h" +int apk_make_dirs(int root_fd, const char *dirname, mode_t dirmode, mode_t parentmode); ssize_t apk_write_fully(int fd, const void *ptr, size_t size); struct apk_id_hash { diff --git a/src/context.c b/src/context.c index 400e09b..38b8d18 100644 --- a/src/context.c +++ b/src/context.c @@ -74,8 +74,7 @@ int apk_ctx_prepare(struct apk_ctx *ac) const int lflags = O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC; int fd = openat(ac->root_fd, log_path, lflags, 0644); if (fd < 0 && (ac->open_flags & APK_OPENF_CREATE)) { - mkdirat(ac->root_fd, "var", 0755); - mkdirat(ac->root_fd, "var/log", 0755); + apk_make_dirs(ac->root_fd, "var/log", 0755, 0755); fd = openat(ac->root_fd, log_path, lflags, 0644); } if (fd < 0) { diff --git a/src/database.c b/src/database.c index 727b44f..027cc76 100644 --- a/src/database.c +++ b/src/database.c @@ -1451,9 +1451,7 @@ static inline int setup_static_cache(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); + apk_make_dirs(db->root_fd, db->cache_dir, 0755, 0755); db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC); if (db->cache_fd < 0) { if (ac->open_flags & APK_OPENF_WRITE) return -EROFS; @@ -1884,15 +1882,8 @@ int apk_db_write_config(struct apk_database *db) return 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); - } + apk_make_dirs(db->root_fd, "lib/apk/db", 0755, 0755); + apk_make_dirs(db->root_fd, "etc/apk", 0755, 0755); } else if (db->lock_fd == 0) { apk_err(out, "Refusing to write db without write lock!"); return -1; diff --git a/src/io.c b/src/io.c index f4ae651..c802ed5 100644 --- a/src/io.c +++ b/src/io.c @@ -38,6 +38,21 @@ static inline int atfd_error(int atfd) return atfd < -1 && atfd != AT_FDCWD; } +int apk_make_dirs(int root_fd, const char *dirname, mode_t dirmode, mode_t parentmode) +{ + char parentdir[PATH_MAX], *slash; + + if (faccessat(root_fd, dirname, F_OK, 0) == 0) return 0; + if (mkdirat(root_fd, dirname, dirmode) == 0) return 0; + if (errno != ENOENT || !parentmode) return -1; + + slash = strrchr(dirname, '/'); + if (!slash || slash == dirname || slash-dirname+1 >= sizeof parentdir) return -1; + strlcpy(parentdir, dirname, slash-dirname+1); + if (apk_make_dirs(root_fd, parentdir, parentmode, parentmode) < 0) return -1; + return mkdirat(root_fd, dirname, dirmode); +} + ssize_t apk_write_fully(int fd, const void *ptr, size_t size) { ssize_t i = 0, r; diff --git a/src/package.c b/src/package.c index ee34595..b160176 100644 --- a/src/package.c +++ b/src/package.c @@ -768,21 +768,6 @@ int apk_ipkg_add_script(struct apk_installed_package *ipkg, return apk_ipkg_assign_script(ipkg, type, apk_blob_from_istream(is, size)); } -static inline int make_dirs(int root_fd, const char *dirname, mode_t dirmode, mode_t parentmode) -{ - char parentdir[PATH_MAX], *slash; - - if (faccessat(root_fd, dirname, F_OK, 0) == 0) return 0; - if (mkdirat(root_fd, dirname, dirmode) == 0) return 0; - if (errno != ENOENT || !parentmode) return -1; - - slash = strrchr(dirname, '/'); - if (!slash || slash == dirname || slash-dirname+1 >= sizeof parentdir) return -1; - strlcpy(parentdir, dirname, slash-dirname+1); - if (make_dirs(root_fd, parentdir, parentmode, parentmode) < 0) return -1; - return mkdirat(root_fd, dirname, dirmode); -} - #ifdef __linux__ static inline int make_device_tree(struct apk_database *db) { @@ -834,8 +819,8 @@ void apk_ipkg_run_script(struct apk_installed_package *ipkg, return; if (!db->script_dirs_checked) { - if (make_dirs(root_fd, "tmp", 01777, 0) <0 || - make_dirs(root_fd, script_exec_dir, 0700, 0755) < 0|| + if (apk_make_dirs(root_fd, "tmp", 01777, 0) <0 || + apk_make_dirs(root_fd, script_exec_dir, 0700, 0755) < 0|| make_device_tree(db) < 0) { apk_err(out, "failed to prepare dirs for hook scripts: %s", apk_error_str(errno));