/src/systemd/*.service
/tests/.root
/tests/libpakfire/archive
+/tests/libpakfire/execute
/tests/libpakfire/key
/tests/libpakfire/main
/tests/libpakfire/makefile
libpakfire_la_SOURCES = \
src/libpakfire/archive.c \
src/libpakfire/errno.c \
+ src/libpakfire/execute.c \
src/libpakfire/file.c \
src/libpakfire/filter.c \
src/libpakfire/key.c \
src/libpakfire/include/pakfire/archive.h \
src/libpakfire/include/pakfire/constants.h \
src/libpakfire/include/pakfire/errno.h \
+ src/libpakfire/include/pakfire/execute.h \
src/libpakfire/include/pakfire/file.h \
src/libpakfire/include/pakfire/filter.h \
src/libpakfire/include/pakfire/i18n.h \
check_PROGRAMS += \
tests/libpakfire/main \
tests/libpakfire/archive \
+ tests/libpakfire/execute \
tests/libpakfire/key \
tests/libpakfire/makefile \
tests/libpakfire/parser \
$(TESTSUITE_LDADD) \
$(PAKFIRE_LIBS)
+tests_libpakfire_execute_SOURCES = \
+ tests/libpakfire/execute.c
+
+tests_libpakfire_execute_CPPFLAGS = \
+ $(TESTSUITE_CPPFLAGS)
+
+tests_libpakfire_execute_LDADD = \
+ $(TESTSUITE_LDADD) \
+ $(PAKFIRE_LIBS)
+
tests_libpakfire_key_SOURCES = \
tests/libpakfire/key.c \
tests/libpakfire/key.h
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2019 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <errno.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <pakfire/execute.h>
+#include <pakfire/logging.h>
+#include <pakfire/private.h>
+#include <pakfire/types.h>
+
+#define STACK_SIZE 1024
+
+struct pakfire_execute_env {
+ Pakfire pakfire;
+ const char* root;
+ const char* command;
+ char** argv;
+ char* envp[20];
+};
+
+static int pakfire_execute_fork(Pakfire pakfire, struct pakfire_execute_env* env) {
+ pid_t pid = getpid();
+
+ DEBUG(env->pakfire, "Execution environment has been forked as PID %d\n", pid);
+ DEBUG(env->pakfire, " command = %s, root = %s\n", env->command, env->root);
+
+ // Move /
+ int r = chroot(env->root);
+ if (r) {
+ ERROR(env->pakfire, "chroot() to %s failed: %s\n",
+ env->root, strerror(errno));
+ return errno;
+ }
+
+ // exec() command
+ r = execve(env->command, env->argv, env->envp);
+
+ // We should not get here
+ return errno;
+}
+
+PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* command, char** argv, int flags) {
+ struct pakfire_execute_env env;
+
+ // Setup environment
+ env.pakfire = pakfire;
+ env.root = pakfire_get_path(pakfire);
+
+ env.command = command;
+ env.argv = argv;
+
+ // Reset environnment
+ env.envp[0] = NULL;
+
+ // Fork this process
+ pid_t pid = fork();
+
+ if (pid < 0) {
+ ERROR(pakfire, "Could not fork: %s\n", strerror(errno));
+ return errno;
+
+ // Child process
+ } else if (pid == 0) {
+ int r = pakfire_execute_fork(pakfire, &env);
+
+ ERROR(pakfire, "Forked process returned unexpectedly: %s\n",
+ strerror(r));
+
+ // Exit immediately
+ exit(r);
+
+ // Parent process
+ } else {
+ DEBUG(pakfire, "Waiting for PID %d to finish its work\n", pid);
+
+ int status;
+ waitpid(pid, &status, 0);
+
+ if (WIFEXITED(status)) {
+ int r = WEXITSTATUS(status);
+
+ DEBUG(pakfire, "Child process has exited with code: %d\n", r);
+ return r;
+ }
+
+ ERROR(pakfire, "Could not determine the exit status of process %d\n", pid);
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2019 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef PAKFIRE_EXECUTE_H
+#define PAKFIRE_EXECUTE_H
+
+#include <pakfire/types.h>
+
+int pakfire_execute(Pakfire pakfire, const char* command, char** argv, int flags);
+
+#endif /* PAKFIRE_EXECUTE_H */
char* pakfire_format_date(time_t t);
char* pakfire_path_join(const char* first, const char* second);
+const char* pakfire_path_relpath(const char* root, const char* path);
char* pakfire_basename(const char* path);
char* pakfire_dirname(const char* path);
pakfire_cache_stat;
pakfire_count_packages;
pakfire_create;
+ pakfire_execute;
pakfire_get_arch;
pakfire_get_cache_path;
pakfire_get_installed_repo;
pakfire_get_errno;
pakfire_partition_string;
pakfire_path_join;
+ pakfire_path_relpath;
pakfire_read_file_into_buffer;
pakfire_split_string;
pakfire_string_to_size;
#include <pakfire/archive.h>
#include <pakfire/constants.h>
+#include <pakfire/execute.h>
#include <pakfire/logging.h>
#include <pakfire/package.h>
#include <pakfire/pakfire.h>
}
static int pakfire_step_run_shell_script(PakfireStep step, const char* data, const size_t size) {
- // Write the scriptlet to disk
- char* path = pakfire_path_join(pakfire_get_path(step->pakfire), "/tmp/.pakfire-scriptlet.XXXXXX");
+ const char* root = pakfire_get_path(step->pakfire);
+ // Write the scriptlet to disk
+ char* path = pakfire_path_join(root, "tmp/.pakfire-scriptlet.XXXXXX");
int r;
+ DEBUG(step->pakfire, "Writing script to %s\n", path);
+
// Open a temporary file
int fd = mkstemp(path);
if (fd < 0) {
goto out;
}
+ const char* command = path;
+ if (root)
+ command = pakfire_path_relpath(root, path);
+
// Run the script
- INFO(step->pakfire, "XXX Running %s\n", path);
+ r = pakfire_execute(step->pakfire, command, NULL, 0);
+ if (r) {
+ DEBUG(step->pakfire, "Script return code: %d\n", r);
+ }
out:
// Remove script from disk
return buffer;
}
+PAKFIRE_EXPORT const char* pakfire_path_relpath(const char* root, const char* path) {
+ if (pakfire_string_startswith(path, root) == 0) {
+ return path + strlen(root);
+ }
+
+ return NULL;
+}
+
PAKFIRE_EXPORT char* pakfire_basename(const char* path) {
char* name = pakfire_strdup(path);
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2019 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <string.h>
+
+#include <pakfire/execute.h>
+#include <pakfire/util.h>
+
+#include "../testsuite.h"
+
+int test_does_not_exist(const test_t* t) {
+ const char* cmd = "/usr/bin/does-not-exist";
+
+ int r = pakfire_execute(t->pakfire, cmd, NULL, 0);
+ assert_return(r != 0, EXIT_FAILURE);
+
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char** argv) {
+ testsuite_init();
+
+ testsuite_t* ts = testsuite_create(1);
+
+ testsuite_add_test(ts, "test_does_not_exist", test_does_not_exist);
+
+ return testsuite_run(ts);
+}