Skip to content
Snippets Groups Projects
Commit 3c459496 authored by Timo Teräs's avatar Timo Teräs
Browse files

db: log uvol output using apk_process api and add tests

parent ccfd7ac5
No related branches found
No related tags found
No related merge requests found
......@@ -70,6 +70,7 @@ static void version(struct apk_out *out, const char *prefix)
OPT(OPT_GLOBAL_root, APK_OPT_ARG APK_OPT_SH("p") "root") \
OPT(OPT_GLOBAL_timeout, APK_OPT_ARG "timeout") \
OPT(OPT_GLOBAL_update_cache, APK_OPT_SH("U") "update-cache") \
OPT(OPT_GLOBAL_uvol_manager, APK_OPT_ARG "uvol-manager") \
OPT(OPT_GLOBAL_verbose, APK_OPT_SH("v") "verbose") \
OPT(OPT_GLOBAL_version, APK_OPT_SH("V") "version") \
OPT(OPT_GLOBAL_wait, APK_OPT_ARG "wait") \
......@@ -180,6 +181,9 @@ static int optgroup_global_parse(struct apk_ctx *ac, int opt, const char *optarg
* when doing self-upgrade's re-exec */
ac->cache_max_age = 60;
break;
case OPT_GLOBAL_uvol_manager:
ac->uvol = optarg;
break;
case OPT_GLOBAL_cache_max_age:
ac->cache_max_age = atoi(optarg) * 60;
break;
......
......@@ -32,6 +32,7 @@ struct apk_process {
int apk_process_init(struct apk_process *p, const char *argv0, struct apk_out *out, struct apk_istream *is);
pid_t apk_process_fork(struct apk_process *p);
int apk_process_spawn(struct apk_process *p, const char *path, char * const* argv, char * const* env);
int apk_process_run(struct apk_process *p);
int apk_process_cleanup(struct apk_process *p);
......
......@@ -61,13 +61,13 @@ int apk_ctx_prepare(struct apk_ctx *ac)
ac->flags |= APK_NO_CHROOT;
// Check uvol availability
ac->uvol = "/usr/sbin/uvol";
if (access(ac->uvol, X_OK) != 0)
ac->uvol = ERR_PTR(-APKE_UVOL_NOT_AVAILABLE);
if (!ac->uvol) ac->uvol = "/usr/sbin/uvol";
} else {
ac->root_set = 1;
ac->uvol = ERR_PTR(-APKE_UVOL_ROOT);
if (!ac->uvol) ac->uvol = ERR_PTR(-APKE_UVOL_ROOT);
}
if (!IS_ERR(ac->uvol) && access(ac->uvol, X_OK) != 0)
ac->uvol = ERR_PTR(-APKE_UVOL_NOT_AVAILABLE);
ac->root_fd = openat(AT_FDCWD, ac->root, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (ac->root_fd < 0 && (ac->open_flags & APK_OPENF_CREATE)) {
......
......@@ -7,77 +7,38 @@
* SPDX-License-Identifier: GPL-2.0-only
*/
#include <spawn.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "apk_context.h"
#include "apk_process.h"
#include "apk_fs.h"
static int uvol_run(struct apk_ctx *ac, char *action, const char *volname, char *arg1, char *arg2)
static int _uvol_run(struct apk_ctx *ac, char *action, const char *volname, char *arg1, char *arg2, struct apk_istream *is)
{
char buf[APK_EXIT_STATUS_MAX_SIZE];
struct apk_out *out = &ac->out;
pid_t pid;
int r, status;
struct apk_process p;
char *argv[] = { (char*)apk_ctx_get_uvol(ac), action, (char*) volname, arg1, arg2, 0 };
posix_spawn_file_actions_t act;
char argv0[256];
int r;
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 (apk_process_init(&p, apk_fmts(argv0, sizeof argv0, "uvol(%s)", action), out, is) != 0)
return -APKE_UVOL_ERROR;
r = apk_process_spawn(&p, apk_ctx_get_uvol(ac), argv, NULL);
if (r != 0) {
apk_err(out, "%s: uvol run exec error: %s", volname, apk_error_str(r));
return r;
}
while (waitpid(pid, &status, 0) < 0 && errno == EINTR);
if (apk_exit_status_str(status, buf, sizeof buf)) {
apk_err(out, "%s: uvol run %s", volname, buf);
return -APKE_UVOL_ERROR;
}
if (apk_process_run(&p) != 0) return -APKE_UVOL_ERROR;
return 0;
}
static int uvol_extract(struct apk_ctx *ac, const char *volname, char *arg1, off_t sz, struct apk_istream *is)
static int uvol_run(struct apk_ctx *ac, char *action, const char *volname, char *arg1, char *arg2)
{
char buf[APK_EXIT_STATUS_MAX_SIZE];
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);
r = apk_ostream_close(os);
if (r != 0) {
if (r >= 0) r = -APKE_UVOL_ERROR;
apk_err(out, "%s: uvol write error: %s", volname, apk_error_str(r));
return r;
}
while (waitpid(pid, &status, 0) < 0 && errno == EINTR);
return _uvol_run(ac, action, volname, arg1, arg2, NULL);
}
if (apk_exit_status_str(status, buf, sizeof buf)) {
apk_err(out, "%s: uvol extract %s", volname, buf);
return -APKE_UVOL_ERROR;
}
return 0;
static int uvol_extract(struct apk_ctx *ac, const char *volname, char *arg1, off_t sz, struct apk_istream *is)
{
return _uvol_run(ac, "write", volname, arg1, 0, is);
}
static int uvol_dir_create(struct apk_fsdir *d, mode_t mode, uid_t uid, gid_t gid)
......
......@@ -9,6 +9,7 @@
#include <poll.h>
#include <errno.h>
#include <fcntl.h>
#include <spawn.h>
#include <unistd.h>
#include <sys/wait.h>
......@@ -97,6 +98,24 @@ pid_t apk_process_fork(struct apk_process *p)
return pid;
}
int apk_process_spawn(struct apk_process *p, const char *path, char * const* argv, char * const* env)
{
posix_spawn_file_actions_t act;
int r;
posix_spawn_file_actions_init(&act);
posix_spawn_file_actions_adddup2(&act, p->pipe_stdin[0], STDIN_FILENO);
posix_spawn_file_actions_adddup2(&act, p->pipe_stdout[1], STDOUT_FILENO);
posix_spawn_file_actions_adddup2(&act, p->pipe_stderr[1], STDERR_FILENO);
r = posix_spawn(&p->pid, path, &act, 0, argv, env ?: environ);
posix_spawn_file_actions_destroy(&act);
close_fd(&p->pipe_stdin[0]);
close_fd(&p->pipe_stdout[1]);
close_fd(&p->pipe_stderr[1]);
return -r;
}
int apk_process_run(struct apk_process *p)
{
struct pollfd fds[3] = {
......
#!/bin/sh
TESTDIR=$(realpath "${TESTDIR:-"$(dirname "$0")"/..}")
. "$TESTDIR"/testlib.sh
create_uvol() {
rm -rf files/uvol/
mkdir -p files/uvol/
cat <<EOF > files/uvol/"$1"
$2
EOF
$APK mkpkg -I name:uvol-"$1" -I version:1.0 -I layer:1 -F files -o uvol-"$1"-1.0.apk
}
reset_uvol_db() {
rm -rf "$TEST_ROOT/lib/apk/db-uvol"
mkdir -p "$TEST_ROOT/lib/apk/db-uvol"
touch "$TEST_ROOT/lib/apk/db-uvol/world"
}
setup_apkroot
create_uvol data "Hello world!"
create_uvol scriptfail "Data for testing failing script!"
APK="$APK --allow-untrusted --no-interactive --force-no-chroot --uvol-manager $TESTDIR/uvol-test-manager.sh"
$APK add --initdb $TEST_USERMODE
reset_uvol_db
$APK add uvol-data-1.0.apk > apk.log 2>&1 || assert "uvol-data shuld have succeeded"
diff -u - apk.log <<EOF || assert "wrong scripts result"
(1/1) Installing uvol-data (1.0)
uvol(create): uvol-test: create data 13 ro
uvol(write): uvol-test: write data 13
uvol(write): uvol-test: drained input
uvol(up): uvol-test: up data
OK: 0 MiB in 1 packages
EOF
reset_uvol_db
$APK add uvol-scriptfail-1.0.apk > apk.log 2>&1 && assert "uvol-scriptail should have failed"
diff -u - apk.log <<EOF || assert "wrong scripts result"
(1/1) Installing uvol-scriptfail (1.0)
uvol(create): uvol-test: create scriptfail 33 ro
uvol(write): uvol-test: write scriptfail 33
ERROR: uvol(write): exited with error 2
uvol(remove): uvol-test: remove scriptfail
ERROR: uvol-scriptfail-1.0: failed to extract uvol/scriptfail: uvol error
1 error; 0 MiB in 1 packages
EOF
exit 0
#!/bin/sh
echo "uvol-test: $*"
case "$1:$2" in
write:data)
read -r DATA
[ "$DATA" = "Hello world!" ] || echo "uvol-test incorrect data!"
echo "uvol-test: drained input"
;;
write:scriptfail)
exit 2
esac
exit 0
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment