]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/util: move execute_directory() to separate file
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 22 Jan 2017 17:35:08 +0000 (12:35 -0500)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 11 Feb 2017 23:21:06 +0000 (18:21 -0500)
It's a fairly specialized function. Let's make new files for it and the tests.

.gitignore
Makefile.am
src/basic/exec-util.c [new file with mode: 0644]
src/basic/exec-util.h [new file with mode: 0644]
src/basic/util.c
src/basic/util.h
src/core/manager.c
src/core/shutdown.c
src/sleep/sleep.c
src/test/test-exec-util.c [new file with mode: 0644]
src/test/test-util.c

index fe7859c265312ec00f1a27ec31453e9798fcfca3..7b5bb412593f5144ab111d83a9bc22391ab342c9 100644 (file)
 /test-env-util
 /test-escape
 /test-event
+/test-exec-util
 /test-execute
 /test-extract-word
 /test-fd-util
index 2d913bd7d716733b6e76f8474da1a2eec7a7ab73..003ec9bfb7cc946ed91008123866f548880e518f 100644 (file)
@@ -873,6 +873,8 @@ libbasic_la_SOURCES = \
        src/basic/bus-label.h \
        src/basic/ratelimit.h \
        src/basic/ratelimit.c \
+       src/basic/exec-util.c \
+       src/basic/exec-util.h \
        src/basic/exit-status.c \
        src/basic/exit-status.h \
        src/basic/virt.c \
@@ -1528,6 +1530,7 @@ tests += \
        test-ellipsize \
        test-util \
        test-mount-util \
+       test-exec-util \
        test-cpu-set-util \
        test-hexdecoct \
        test-escape \
@@ -1912,6 +1915,12 @@ test_mount_util_SOURCES = \
 test_mount_util_LDADD = \
        libsystemd-shared.la
 
+test_exec_util_SOURCES = \
+       src/test/test-exec-util.c
+
+test_exec_util_LDADD = \
+       libsystemd-shared.la
+
 test_hexdecoct_SOURCES = \
        src/test/test-hexdecoct.c
 
diff --git a/src/basic/exec-util.c b/src/basic/exec-util.c
new file mode 100644 (file)
index 0000000..757cd3b
--- /dev/null
@@ -0,0 +1,181 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <dirent.h>
+#include <errno.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "dirent-util.h"
+#include "exec-util.h"
+#include "fd-util.h"
+#include "hashmap.h"
+#include "macro.h"
+#include "process-util.h"
+#include "set.h"
+#include "signal-util.h"
+#include "stat-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
+
+/* Put this test here for a lack of better place */
+assert_cc(EAGAIN == EWOULDBLOCK);
+
+static int do_execute(char **directories, usec_t timeout, char *argv[]) {
+        _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
+        _cleanup_set_free_free_ Set *seen = NULL;
+        char **directory;
+
+        /* We fork this all off from a child process so that we can
+         * somewhat cleanly make use of SIGALRM to set a time limit */
+
+        (void) reset_all_signal_handlers();
+        (void) reset_signal_mask();
+
+        assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
+
+        pids = hashmap_new(NULL);
+        if (!pids)
+                return log_oom();
+
+        seen = set_new(&string_hash_ops);
+        if (!seen)
+                return log_oom();
+
+        STRV_FOREACH(directory, directories) {
+                _cleanup_closedir_ DIR *d;
+                struct dirent *de;
+
+                d = opendir(*directory);
+                if (!d) {
+                        if (errno == ENOENT)
+                                continue;
+
+                        return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
+                }
+
+                FOREACH_DIRENT(de, d, break) {
+                        _cleanup_free_ char *path = NULL;
+                        pid_t pid;
+                        int r;
+
+                        if (!dirent_is_file(de))
+                                continue;
+
+                        if (set_contains(seen, de->d_name)) {
+                                log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
+                                continue;
+                        }
+
+                        r = set_put_strdup(seen, de->d_name);
+                        if (r < 0)
+                                return log_oom();
+
+                        path = strjoin(*directory, "/", de->d_name);
+                        if (!path)
+                                return log_oom();
+
+                        if (null_or_empty_path(path)) {
+                                log_debug("%s is empty (a mask).", path);
+                                continue;
+                        }
+
+                        pid = fork();
+                        if (pid < 0) {
+                                log_error_errno(errno, "Failed to fork: %m");
+                                continue;
+                        } else if (pid == 0) {
+                                char *_argv[2];
+
+                                assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
+
+                                if (!argv) {
+                                        _argv[0] = path;
+                                        _argv[1] = NULL;
+                                        argv = _argv;
+                                } else
+                                        argv[0] = path;
+
+                                execv(path, argv);
+                                return log_error_errno(errno, "Failed to execute %s: %m", path);
+                        }
+
+                        log_debug("Spawned %s as " PID_FMT ".", path, pid);
+
+                        r = hashmap_put(pids, PID_TO_PTR(pid), path);
+                        if (r < 0)
+                                return log_oom();
+                        path = NULL;
+                }
+        }
+
+        /* Abort execution of this process after the timout. We simply
+         * rely on SIGALRM as default action terminating the process,
+         * and turn on alarm(). */
+
+        if (timeout != USEC_INFINITY)
+                alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
+
+        while (!hashmap_isempty(pids)) {
+                _cleanup_free_ char *path = NULL;
+                pid_t pid;
+
+                pid = PTR_TO_PID(hashmap_first_key(pids));
+                assert(pid > 0);
+
+                path = hashmap_remove(pids, PID_TO_PTR(pid));
+                assert(path);
+
+                wait_for_terminate_and_warn(path, pid, true);
+        }
+
+        return 0;
+}
+
+void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
+        pid_t executor_pid;
+        int r;
+        char *name;
+        char **dirs = (char**) directories;
+
+        assert(!strv_isempty(dirs));
+
+        name = basename(dirs[0]);
+        assert(!isempty(name));
+
+        /* Executes all binaries in the directories in parallel and waits
+         * for them to finish. Optionally a timeout is applied. If a file
+         * with the same name exists in more than one directory, the
+         * earliest one wins. */
+
+        executor_pid = fork();
+        if (executor_pid < 0) {
+                log_error_errno(errno, "Failed to fork: %m");
+                return;
+
+        } else if (executor_pid == 0) {
+                r = do_execute(dirs, timeout, argv);
+                _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+        }
+
+        wait_for_terminate_and_warn(name, executor_pid, true);
+}
diff --git a/src/basic/exec-util.h b/src/basic/exec-util.h
new file mode 100644 (file)
index 0000000..9f8daa9
--- /dev/null
@@ -0,0 +1,22 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2017 Zbigniew Jędrzejewski-Szmek
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "time-util.h"
+
+void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
index 6204906f37079e2a8824e975c05a9377d8721e80..3dce0ea92eb79044a7b3ee39f88ccd0e9ee1c67c 100644 (file)
@@ -59,9 +59,6 @@
 #include "user-util.h"
 #include "util.h"
 
-/* Put this test here for a lack of better place */
-assert_cc(EAGAIN == EWOULDBLOCK);
-
 int saved_argc = 0;
 char **saved_argv = NULL;
 static int saved_in_initrd = -1;
@@ -80,146 +77,6 @@ size_t page_size(void) {
         return pgsz;
 }
 
-static int do_execute(char **directories, usec_t timeout, char *argv[]) {
-        _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
-        _cleanup_set_free_free_ Set *seen = NULL;
-        char **directory;
-
-        /* We fork this all off from a child process so that we can
-         * somewhat cleanly make use of SIGALRM to set a time limit */
-
-        (void) reset_all_signal_handlers();
-        (void) reset_signal_mask();
-
-        assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
-
-        pids = hashmap_new(NULL);
-        if (!pids)
-                return log_oom();
-
-        seen = set_new(&string_hash_ops);
-        if (!seen)
-                return log_oom();
-
-        STRV_FOREACH(directory, directories) {
-                _cleanup_closedir_ DIR *d;
-                struct dirent *de;
-
-                d = opendir(*directory);
-                if (!d) {
-                        if (errno == ENOENT)
-                                continue;
-
-                        return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
-                }
-
-                FOREACH_DIRENT(de, d, break) {
-                        _cleanup_free_ char *path = NULL;
-                        pid_t pid;
-                        int r;
-
-                        if (!dirent_is_file(de))
-                                continue;
-
-                        if (set_contains(seen, de->d_name)) {
-                                log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
-                                continue;
-                        }
-
-                        r = set_put_strdup(seen, de->d_name);
-                        if (r < 0)
-                                return log_oom();
-
-                        path = strjoin(*directory, "/", de->d_name);
-                        if (!path)
-                                return log_oom();
-
-                        if (null_or_empty_path(path)) {
-                                log_debug("%s is empty (a mask).", path);
-                                continue;
-                        }
-
-                        pid = fork();
-                        if (pid < 0) {
-                                log_error_errno(errno, "Failed to fork: %m");
-                                continue;
-                        } else if (pid == 0) {
-                                char *_argv[2];
-
-                                assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
-
-                                if (!argv) {
-                                        _argv[0] = path;
-                                        _argv[1] = NULL;
-                                        argv = _argv;
-                                } else
-                                        argv[0] = path;
-
-                                execv(path, argv);
-                                return log_error_errno(errno, "Failed to execute %s: %m", path);
-                        }
-
-                        log_debug("Spawned %s as " PID_FMT ".", path, pid);
-
-                        r = hashmap_put(pids, PID_TO_PTR(pid), path);
-                        if (r < 0)
-                                return log_oom();
-                        path = NULL;
-                }
-        }
-
-        /* Abort execution of this process after the timout. We simply
-         * rely on SIGALRM as default action terminating the process,
-         * and turn on alarm(). */
-
-        if (timeout != USEC_INFINITY)
-                alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
-
-        while (!hashmap_isempty(pids)) {
-                _cleanup_free_ char *path = NULL;
-                pid_t pid;
-
-                pid = PTR_TO_PID(hashmap_first_key(pids));
-                assert(pid > 0);
-
-                path = hashmap_remove(pids, PID_TO_PTR(pid));
-                assert(path);
-
-                wait_for_terminate_and_warn(path, pid, true);
-        }
-
-        return 0;
-}
-
-void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
-        pid_t executor_pid;
-        int r;
-        char *name;
-        char **dirs = (char**) directories;
-
-        assert(!strv_isempty(dirs));
-
-        name = basename(dirs[0]);
-        assert(!isempty(name));
-
-        /* Executes all binaries in the directories in parallel and waits
-         * for them to finish. Optionally a timeout is applied. If a file
-         * with the same name exists in more than one directory, the
-         * earliest one wins. */
-
-        executor_pid = fork();
-        if (executor_pid < 0) {
-                log_error_errno(errno, "Failed to fork: %m");
-                return;
-
-        } else if (executor_pid == 0) {
-                r = do_execute(dirs, timeout, argv);
-                _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
-        }
-
-        wait_for_terminate_and_warn(name, executor_pid, true);
-}
-
 bool plymouth_running(void) {
         return access("/run/plymouth/pid", F_OK) >= 0;
 }
index c3802a811cdfcc2c7c97724e50adee054c5468cf..c7da6c39bf6426fa25126bd6f5b7420ec1272645 100644 (file)
@@ -65,8 +65,6 @@ static inline const char* enable_disable(bool b) {
         return b ? "enable" : "disable";
 }
 
-void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
-
 bool plymouth_running(void);
 
 bool display_is_local(const char *display) _pure_;
index e4da945777b006e28304f56bd3d2a76587319c23..0884534cc49567b946117edb11bcb9e295c3a128 100644 (file)
@@ -52,6 +52,7 @@
 #include "dirent-util.h"
 #include "env-util.h"
 #include "escape.h"
+#include "exec-util.h"
 #include "exit-status.h"
 #include "fd-util.h"
 #include "fileio.h"
index a795d875bb6225938b9a3d1ae80f93bf709a6a40..56a035e23454f91868f7d0647dd4d827adb948a8 100644 (file)
@@ -32,6 +32,7 @@
 #include "alloc-util.h"
 #include "cgroup-util.h"
 #include "def.h"
+#include "exec-util.h"
 #include "fileio.h"
 #include "killall.h"
 #include "log.h"
index c8f0742183febdc3053b62b511bc63460571e61d..b0f992fc9cd5f357fe9d4605c4d7b4c48f531241 100644 (file)
@@ -25,6 +25,7 @@
 #include "sd-messages.h"
 
 #include "def.h"
+#include "exec-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "log.h"
diff --git a/src/test/test-exec-util.c b/src/test/test-exec-util.c
new file mode 100644 (file)
index 0000000..26533f0
--- /dev/null
@@ -0,0 +1,87 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+  Copyright 2013 Thomas H.P. Andersen
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "def.h"
+#include "exec-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "log.h"
+#include "macro.h"
+#include "rm-rf.h"
+#include "string-util.h"
+
+static void test_execute_directory(void) {
+        char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
+        char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
+        const char * dirs[] = {template_hi, template_lo, NULL};
+        const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
+
+        assert_se(mkdtemp(template_lo));
+        assert_se(mkdtemp(template_hi));
+
+        name = strjoina(template_lo, "/script");
+        name2 = strjoina(template_hi, "/script2");
+        name3 = strjoina(template_lo, "/useless");
+        overridden = strjoina(template_lo, "/overridden");
+        override = strjoina(template_hi, "/overridden");
+        masked = strjoina(template_lo, "/masked");
+        mask = strjoina(template_hi, "/masked");
+
+        assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", WRITE_STRING_FILE_CREATE) == 0);
+        assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", WRITE_STRING_FILE_CREATE) == 0);
+        assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
+        assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0", WRITE_STRING_FILE_CREATE) == 0);
+        assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
+        assert_se(symlink("/dev/null", mask) == 0);
+        assert_se(chmod(name, 0755) == 0);
+        assert_se(chmod(name2, 0755) == 0);
+        assert_se(chmod(overridden, 0755) == 0);
+        assert_se(chmod(override, 0755) == 0);
+        assert_se(chmod(masked, 0755) == 0);
+        assert_se(touch(name3) >= 0);
+
+        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL);
+
+        assert_se(chdir(template_lo) == 0);
+        assert_se(access("it_works", F_OK) >= 0);
+        assert_se(access("failed", F_OK) < 0);
+
+        assert_se(chdir(template_hi) == 0);
+        assert_se(access("it_works2", F_OK) >= 0);
+        assert_se(access("failed", F_OK) < 0);
+
+        (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
+        (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
+}
+
+int main(int argc, char *argv[]) {
+        log_parse_environment();
+        log_open();
+
+        test_execute_directory();
+
+        return 0;
+}
index 1b5cba86c154b87ffd93e805fc945de46b8ac381..f8bf0cb87598b4df1e64db1cb5f22babb46f1bac 100644 (file)
@@ -195,50 +195,6 @@ static void test_log2i(void) {
         assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
 }
 
-static void test_execute_directory(void) {
-        char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
-        char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
-        const char * dirs[] = {template_hi, template_lo, NULL};
-        const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
-
-        assert_se(mkdtemp(template_lo));
-        assert_se(mkdtemp(template_hi));
-
-        name = strjoina(template_lo, "/script");
-        name2 = strjoina(template_hi, "/script2");
-        name3 = strjoina(template_lo, "/useless");
-        overridden = strjoina(template_lo, "/overridden");
-        override = strjoina(template_hi, "/overridden");
-        masked = strjoina(template_lo, "/masked");
-        mask = strjoina(template_hi, "/masked");
-
-        assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", WRITE_STRING_FILE_CREATE) == 0);
-        assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", WRITE_STRING_FILE_CREATE) == 0);
-        assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
-        assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0", WRITE_STRING_FILE_CREATE) == 0);
-        assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
-        assert_se(symlink("/dev/null", mask) == 0);
-        assert_se(chmod(name, 0755) == 0);
-        assert_se(chmod(name2, 0755) == 0);
-        assert_se(chmod(overridden, 0755) == 0);
-        assert_se(chmod(override, 0755) == 0);
-        assert_se(chmod(masked, 0755) == 0);
-        assert_se(touch(name3) >= 0);
-
-        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL);
-
-        assert_se(chdir(template_lo) == 0);
-        assert_se(access("it_works", F_OK) >= 0);
-        assert_se(access("failed", F_OK) < 0);
-
-        assert_se(chdir(template_hi) == 0);
-        assert_se(access("it_works2", F_OK) >= 0);
-        assert_se(access("failed", F_OK) < 0);
-
-        (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
-        (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
-}
-
 static void test_raw_clone(void) {
         pid_t parent, pid, pid2;
 
@@ -359,7 +315,6 @@ int main(int argc, char *argv[]) {
         test_protect_errno();
         test_in_set();
         test_log2i();
-        test_execute_directory();
         test_raw_clone();
         test_physical_memory();
         test_physical_memory_scale();