diff options
author | Timo Teräs <timo.teras@iki.fi> | 2021-11-01 15:59:15 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2021-11-03 15:37:10 +0200 |
commit | 5c0c249b7823e8537b9e60108e565b9b9a0bff24 (patch) | |
tree | 632be87d7466dabf09ff26985accba728660d1c9 | |
parent | d8212658653ad7cb1e220635b6dbd92923a60520 (diff) | |
download | apk-tools-5c0c249b7823e8537b9e60108e565b9b9a0bff24.tar.gz apk-tools-5c0c249b7823e8537b9e60108e565b9b9a0bff24.tar.bz2 apk-tools-5c0c249b7823e8537b9e60108e565b9b9a0bff24.tar.xz apk-tools-5c0c249b7823e8537b9e60108e565b9b9a0bff24.zip |
extract: move uvol extraction code to extract
fix also the progress callback on uvol extraction
-rw-r--r-- | src/apk_extract.h | 5 | ||||
-rw-r--r-- | src/app_extract.c | 90 | ||||
-rw-r--r-- | src/database.c | 5 | ||||
-rw-r--r-- | src/extract.c | 96 |
4 files changed, 99 insertions, 97 deletions
diff --git a/src/apk_extract.h b/src/apk_extract.h index 2a25638..ecb39ed 100644 --- a/src/apk_extract.h +++ b/src/apk_extract.h @@ -25,9 +25,8 @@ struct apk_extract_ctx; int apk_extract_file(int atfd, const struct apk_file_info *ae, const char *extract_name, const char *hardlink_name, - struct apk_istream *is, - apk_progress_cb cb, void *cb_ctx, struct apk_digest_ctx *dctx, - unsigned int extract_flags, struct apk_out *out); + struct apk_istream *is, apk_progress_cb cb, void *cb_ctx, + unsigned int extract_flags, struct apk_ctx *ac); struct apk_extract_ops { int (*v2index)(struct apk_extract_ctx *, apk_blob_t *desc, struct apk_istream *is); diff --git a/src/app_extract.c b/src/app_extract.c index 22ef971..2dd310b 100644 --- a/src/app_extract.c +++ b/src/app_extract.c @@ -9,10 +9,8 @@ #include <errno.h> #include <stdio.h> #include <fcntl.h> -#include <spawn.h> #include <unistd.h> #include <sys/stat.h> -#include <sys/wait.h> #include "apk_applet.h" #include "apk_print.h" @@ -56,83 +54,6 @@ static const struct apk_option_group optgroup_applet = { .parse = option_parse_applet, }; -static int uvol_run(struct apk_ctx *ac, char *action, const char *volname, char *arg1, char *arg2) -{ - struct apk_out *out = &ac->out; - pid_t pid; - int r, status; - char *argv[] = { (char*)apk_ctx_get_uvol(ac), action, (char*) volname, arg1, arg2, 0 }; - posix_spawn_file_actions_t act; - - posix_spawn_file_actions_init(&act); - posix_spawn_file_actions_addclose(&act, STDIN_FILENO); - r = posix_spawn(&pid, apk_ctx_get_uvol(ac), &act, 0, argv, environ); - posix_spawn_file_actions_destroy(&act); - if (r != 0) { - apk_err(out, "%s: uvol exec error: %s", volname, apk_error_str(r)); - return r; - } - while (waitpid(pid, &status, 0) < 0 && errno == EINTR); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - apk_err(out, "%s: uvol exited with error %d", volname, WEXITSTATUS(status)); - return -APKE_UVOL; - } - return 0; -} - -static int uvol_extract(struct apk_ctx *ac, const char *volname, char *arg1, off_t sz, struct apk_istream *is) -{ - struct apk_out *out = &ac->out; - struct apk_ostream *os; - pid_t pid; - int r, status, pipefds[2]; - char *argv[] = { (char*)apk_ctx_get_uvol(ac), "write", (char*) volname, arg1, 0 }; - posix_spawn_file_actions_t act; - - if (pipe2(pipefds, O_CLOEXEC) != 0) return -errno; - - posix_spawn_file_actions_init(&act); - posix_spawn_file_actions_adddup2(&act, pipefds[0], STDIN_FILENO); - r = posix_spawn(&pid, apk_ctx_get_uvol(ac), &act, 0, argv, environ); - posix_spawn_file_actions_destroy(&act); - if (r != 0) { - apk_err(out, "%s: uvol exec error: %s", volname, apk_error_str(r)); - return r; - } - close(pipefds[0]); - os = apk_ostream_to_fd(pipefds[1]); - apk_stream_copy(is, os, sz, 0, 0, 0); - r = apk_ostream_close(os); - if (r != 0) { - if (r >= 0) r = -APKE_UVOL; - apk_err(out, "%s: uvol write error: %s", volname, apk_error_str(r)); - return r; - } - - while (waitpid(pid, &status, 0) < 0 && errno == EINTR); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - apk_err(out, "%s: uvol exited with error %d", volname, WEXITSTATUS(status)); - return -APKE_UVOL; - } - - return 0; -} - -static int apk_extract_volume(struct apk_ctx *ac, const struct apk_file_info *fi, struct apk_istream *is) -{ - char size[64]; - int r; - - snprintf(size, sizeof size, "%ju", fi->size); - r = uvol_run(ac, "create", fi->uvol_name, size, "ro"); - if (r != 0) return r; - - r = uvol_extract(ac, fi->uvol_name, size, fi->size, is); - if (r == 0) r = uvol_run(ac, "up", fi->uvol_name, 0, 0); - if (r != 0) uvol_run(ac, "remove", fi->uvol_name, 0, 0); - return r; -} - static int extract_v3_meta(struct apk_extract_ctx *ectx, struct adb_obj *pkg) { return 0; @@ -142,18 +63,11 @@ static int extract_file(struct apk_extract_ctx *ectx, const struct apk_file_info { struct extract_ctx *ctx = container_of(ectx, struct extract_ctx, ectx); struct apk_out *out = &ctx->ac->out; - int r; apk_dbg2(out, "%s", fi->name); - if (fi->uvol_name && is) { - r = apk_extract_volume(ectx->ac, fi, is); - } else { - r = apk_extract_file(ctx->root_fd, fi, 0, 0, is, 0, 0, 0, - ctx->extract_flags, &ectx->ac->out); - } - if (is) r = apk_istream_close_error(is, r); - return r; + return apk_extract_file(ctx->root_fd, fi, 0, 0, is, 0, 0, + ctx->extract_flags, ectx->ac); } static const struct apk_extract_ops extract_ops = { diff --git a/src/database.c b/src/database.c index 3841464..d145425 100644 --- a/src/database.c +++ b/src/database.c @@ -2415,7 +2415,8 @@ static int apk_db_install_file(struct apk_extract_ctx *ectx, const struct apk_fi struct install_ctx *ctx = container_of(ectx, struct install_ctx, ectx); static const char dot1[] = "/./", dot2[] = "/../"; struct apk_database *db = ctx->db; - struct apk_out *out = &db->ctx->out; + struct apk_ctx *ac = db->ctx; + struct apk_out *out = &ac->out; struct apk_package *pkg = ctx->pkg, *opkg; struct apk_dependency *dep; struct apk_installed_package *ipkg = pkg->ipkg; @@ -2566,7 +2567,7 @@ static int apk_db_install_file(struct apk_extract_ctx *ectx, const struct apk_fi db->root_fd, ae, format_tmpname(pkg, file, tmpname_file), format_tmpname(pkg, link_target_file, tmpname_link_target), - is, extract_cb, ctx, 0, db->extract_flags, out); + is, extract_cb, ctx, db->extract_flags, ac); switch (r) { case 0: diff --git a/src/extract.c b/src/extract.c index 1e092c5..00d871f 100644 --- a/src/extract.c +++ b/src/extract.c @@ -7,22 +7,110 @@ * SPDX-License-Identifier: GPL-2.0-only */ +#include <spawn.h> +#include <unistd.h> #include <sys/stat.h> +#include <sys/wait.h> #include <sys/xattr.h> -#include <unistd.h> +#include "apk_context.h" #include "apk_extract.h" +static int uvol_run(struct apk_ctx *ac, char *action, const char *volname, char *arg1, char *arg2) +{ + struct apk_out *out = &ac->out; + pid_t pid; + int r, status; + char *argv[] = { (char*)apk_ctx_get_uvol(ac), action, (char*) volname, arg1, arg2, 0 }; + posix_spawn_file_actions_t act; + + posix_spawn_file_actions_init(&act); + posix_spawn_file_actions_addclose(&act, STDIN_FILENO); + r = posix_spawn(&pid, apk_ctx_get_uvol(ac), &act, 0, argv, environ); + posix_spawn_file_actions_destroy(&act); + if (r != 0) { + apk_err(out, "%s: uvol exec error: %s", volname, apk_error_str(r)); + return r; + } + while (waitpid(pid, &status, 0) < 0 && errno == EINTR); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + apk_err(out, "%s: uvol exited with error %d", volname, WEXITSTATUS(status)); + return -APKE_UVOL; + } + return 0; +} + +static int uvol_extract(struct apk_ctx *ac, const char *volname, char *arg1, off_t sz, + struct apk_istream *is, apk_progress_cb cb, void *cb_ctx) +{ + struct apk_out *out = &ac->out; + struct apk_ostream *os; + pid_t pid; + int r, status, pipefds[2]; + char *argv[] = { (char*)apk_ctx_get_uvol(ac), "write", (char*) volname, arg1, 0 }; + posix_spawn_file_actions_t act; + + if (pipe2(pipefds, O_CLOEXEC) != 0) return -errno; + + posix_spawn_file_actions_init(&act); + posix_spawn_file_actions_adddup2(&act, pipefds[0], STDIN_FILENO); + r = posix_spawn(&pid, apk_ctx_get_uvol(ac), &act, 0, argv, environ); + posix_spawn_file_actions_destroy(&act); + if (r != 0) { + apk_err(out, "%s: uvol exec error: %s", volname, apk_error_str(r)); + return r; + } + close(pipefds[0]); + os = apk_ostream_to_fd(pipefds[1]); + apk_stream_copy(is, os, sz, cb, cb_ctx, 0); + r = apk_ostream_close(os); + if (r != 0) { + if (r >= 0) r = -APKE_UVOL; + apk_err(out, "%s: uvol write error: %s", volname, apk_error_str(r)); + return r; + } + + while (waitpid(pid, &status, 0) < 0 && errno == EINTR); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + apk_err(out, "%s: uvol exited with error %d", volname, WEXITSTATUS(status)); + return -APKE_UVOL; + } + + return 0; +} + +static int apk_extract_volume(struct apk_ctx *ac, const struct apk_file_info *fi, + struct apk_istream *is, apk_progress_cb cb, void *cb_ctx) +{ + char size[64]; + int r; + + snprintf(size, sizeof size, "%ju", fi->size); + r = uvol_run(ac, "create", fi->uvol_name, size, "ro"); + if (r != 0) return r; + + r = uvol_extract(ac, fi->uvol_name, size, fi->size, is, cb, cb_ctx); + if (r == 0) r = uvol_run(ac, "up", fi->uvol_name, 0, 0); + if (r != 0) uvol_run(ac, "remove", fi->uvol_name, 0, 0); + return r; +} + int apk_extract_file(int atfd, const struct apk_file_info *ae, const char *extract_name, const char *link_target, struct apk_istream *is, - apk_progress_cb cb, void *cb_ctx, struct apk_digest_ctx *dctx, - unsigned int extract_flags, struct apk_out *out) + apk_progress_cb cb, void *cb_ctx, + unsigned int extract_flags, struct apk_ctx *ac) { + struct apk_out *out = &ac->out; struct apk_xattr *xattr; const char *fn = extract_name ?: ae->name; int fd, r = -1, atflags = 0, ret = 0; + if (ae->uvol_name && is) { + if (extract_name || link_target) return -APKE_UVOL; + return apk_extract_volume(ac, ae, is, cb, cb_ctx); + } + if (!S_ISDIR(ae->mode) && !(extract_flags & APK_EXTRACTF_NO_OVERWRITE)) { if (unlinkat(atfd, fn, 0) != 0 && errno != ENOENT) return -errno; } @@ -46,7 +134,7 @@ int apk_extract_file(int atfd, const struct apk_file_info *ae, ret = PTR_ERR(os); break; } - apk_stream_copy(is, os, ae->size, cb, cb_ctx, dctx); + apk_stream_copy(is, os, ae->size, cb, cb_ctx, 0); r = apk_ostream_close(os); if (r < 0) { unlinkat(atfd, fn, 0); |