コード例 #1
0
ファイル: test-process-util.c プロジェクト: karelzak/systemd
static void test_getpid_cached(void) {
        siginfo_t si;
        pid_t a, b, c, d, e, f, child;

        a = raw_getpid();
        b = getpid_cached();
        c = getpid();

        assert_se(a == b && a == c);

        child = fork();
        assert_se(child >= 0);

        if (child == 0) {
                /* In child */
                a = raw_getpid();
                b = getpid_cached();
                c = getpid();

                assert_se(a == b && a == c);
                _exit(EXIT_SUCCESS);
        }

        d = raw_getpid();
        e = getpid_cached();
        f = getpid();

        assert_se(a == d && a == e && a == f);

        assert_se(wait_for_terminate(child, &si) >= 0);
        assert_se(si.si_status == 0);
        assert_se(si.si_code == CLD_EXITED);
}
コード例 #2
0
ファイル: machined.c プロジェクト: atriwidada/systemd
int main(int argc, char *argv[]) {
        Manager *m = NULL;
        int r;

        log_set_target(LOG_TARGET_AUTO);
        log_set_facility(LOG_AUTH);
        log_parse_environment();
        log_open();

        umask(0022);

        if (argc != 1) {
                log_error("This program takes no arguments.");
                r = -EINVAL;
                goto finish;
        }

        /* Always create the directories people can create inotify
         * watches in. Note that some applications might check for the
         * existence of /run/systemd/machines/ to determine whether
         * machined is available, so please always make sure this
         * check stays in. */
        mkdir_label("/run/systemd/machines", 0755);

        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);

        m = manager_new();
        if (!m) {
                r = log_oom();
                goto finish;
        }

        r = manager_startup(m);
        if (r < 0) {
                log_error_errno(r, "Failed to fully start up daemon: %m");
                goto finish;
        }

        log_debug("systemd-machined running as pid "PID_FMT, getpid_cached());

        sd_notify(false,
                  "READY=1\n"
                  "STATUS=Processing requests...");

        r = manager_run(m);

        log_debug("systemd-machined stopped as pid "PID_FMT, getpid_cached());

finish:
        manager_free(m);

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
コード例 #3
0
ファイル: test-tmpfiles.c プロジェクト: Werkov/systemd
int main(int argc, char** argv) {
        _cleanup_free_ char *cmd = NULL, *cmd2 = NULL, *ans = NULL, *ans2 = NULL, *d = NULL, *tmp = NULL, *line = NULL;
        _cleanup_close_ int fd = -1, fd2 = -1;
        const char *p = argv[1] ?: "/tmp";
        char *pattern;

        log_set_max_level(LOG_DEBUG);
        log_parse_environment();

        pattern = strjoina(p, "/systemd-test-XXXXXX");

        fd = open_tmpfile_unlinkable(p, O_RDWR|O_CLOEXEC);
        assert_se(fd >= 0);

        assert_se(asprintf(&cmd, "ls -l /proc/"PID_FMT"/fd/%d", getpid_cached(), fd) > 0);
        (void) system(cmd);
        assert_se(readlink_malloc(cmd + 6, &ans) >= 0);
        log_debug("link1: %s", ans);
        assert_se(endswith(ans, " (deleted)"));

        fd2 = mkostemp_safe(pattern);
        assert_se(fd >= 0);
        assert_se(unlink(pattern) == 0);

        assert_se(asprintf(&cmd2, "ls -l /proc/"PID_FMT"/fd/%d", getpid_cached(), fd2) > 0);
        (void) system(cmd2);
        assert_se(readlink_malloc(cmd2 + 6, &ans2) >= 0);
        log_debug("link2: %s", ans2);
        assert_se(endswith(ans2, " (deleted)"));

        pattern = strjoina(p, "/tmpfiles-test");
        assert_se(tempfn_random(pattern, NULL, &d) >= 0);

        fd = open_tmpfile_linkable(d, O_RDWR|O_CLOEXEC, &tmp);
        assert_se(fd >= 0);
        assert_se(write(fd, "foobar\n", 7) == 7);

        assert_se(touch(d) >= 0);
        assert_se(link_tmpfile(fd, tmp, d) == -EEXIST);
        assert_se(unlink(d) >= 0);
        assert_se(link_tmpfile(fd, tmp, d) >= 0);

        assert_se(read_one_line_file(d, &line) >= 0);
        assert_se(streq(line, "foobar"));
        assert_se(unlink(d) >= 0);

        return 0;
}
コード例 #4
0
ファイル: condition.c プロジェクト: vathpela/systemd
static int condition_test_user(Condition *c) {
        uid_t id;
        int r;
        _cleanup_free_ char *username = NULL;
        const char *u;

        assert(c);
        assert(c->parameter);
        assert(c->type == CONDITION_USER);

        r = parse_uid(c->parameter, &id);
        if (r >= 0)
                return id == getuid() || id == geteuid();

        if (streq("@system", c->parameter))
                return uid_is_system(getuid()) || uid_is_system(geteuid());

        username = getusername_malloc();
        if (!username)
                return -ENOMEM;

        if (streq(username, c->parameter))
                return 1;

        if (getpid_cached() == 1)
                return streq(c->parameter, "root");

        u = c->parameter;
        r = get_user_creds(&u, &id, NULL, NULL, NULL);
        if (r < 0)
                return 0;

        return id == getuid() || id == geteuid();
}
コード例 #5
0
ファイル: bus-creds.c プロジェクト: OpenDZ/systemd
_public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
        sd_bus_creds *c;
        int r;

        assert_return(pid >= 0, -EINVAL);
        assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
        assert_return(ret, -EINVAL);

        if (pid == 0)
                pid = getpid_cached();

        c = bus_creds_new();
        if (!c)
                return -ENOMEM;

        r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
        if (r < 0) {
                sd_bus_creds_unref(c);
                return r;
        }

        /* Check if the process existed at all, in case we haven't
         * figured that out already */
        if (!pid_is_alive(pid)) {
                sd_bus_creds_unref(c);
                return -ESRCH;
        }

        *ret = c;
        return 0;
}
コード例 #6
0
ファイル: journald-kmsg.c プロジェクト: Werkov/systemd
static bool is_us(const char *pid) {
        pid_t t;

        assert(pid);

        if (parse_pid(pid, &t) < 0)
                return false;

        return t == getpid_cached();
}
コード例 #7
0
ファイル: journald-kmsg.c プロジェクト: dankor/systemd
static bool is_us(const char *identifier, const char *pid) {
        pid_t pid_num;

        if (!identifier || !pid)
                return false;

        if (parse_pid(pid, &pid_num) < 0)
                return false;

        return pid_num == getpid_cached() &&
               streq(identifier, program_invocation_short_name);
}
コード例 #8
0
ファイル: test-process-util.c プロジェクト: karelzak/systemd
static void test_pid_is_alive(void) {
        pid_t pid;

        pid = fork();
        assert_se(pid >= 0);
        if (pid == 0) {
                _exit(EXIT_SUCCESS);
        } else {
                int status;

                waitpid(pid, &status, 0);
                assert_se(!pid_is_alive(pid));
        }
        assert_se(pid_is_alive(getpid_cached()));
        assert_se(!pid_is_alive(-1));
}
コード例 #9
0
ファイル: test-process-util.c プロジェクト: karelzak/systemd
static void test_getpid_measure(void) {
        unsigned long long i;
        usec_t t, q;

        t = now(CLOCK_MONOTONIC);
        for (i = 0; i < MEASURE_ITERATIONS; i++)
                (void) getpid();
        q = now(CLOCK_MONOTONIC) - t;

        log_info(" glibc getpid(): %llu/s\n", (unsigned long long) (MEASURE_ITERATIONS*USEC_PER_SEC/q));

        t = now(CLOCK_MONOTONIC);
        for (i = 0; i < MEASURE_ITERATIONS; i++)
                (void) getpid_cached();
        q = now(CLOCK_MONOTONIC) - t;

        log_info("getpid_cached(): %llu/s\n", (unsigned long long) (MEASURE_ITERATIONS*USEC_PER_SEC/q));
}
コード例 #10
0
ファイル: condition.c プロジェクト: vathpela/systemd
static int condition_test_group(Condition *c) {
        gid_t id;
        int r;

        assert(c);
        assert(c->parameter);
        assert(c->type == CONDITION_GROUP);

        r = parse_gid(c->parameter, &id);
        if (r >= 0)
                return in_gid(id);

        /* Avoid any NSS lookups if we are PID1 */
        if (getpid_cached() == 1)
                return streq(c->parameter, "root");

        return in_group(c->parameter) > 0;
}
コード例 #11
0
ファイル: test-process-util.c プロジェクト: karelzak/systemd
static void test_get_process_cmdline_harder(void) {
        char path[] = "/tmp/test-cmdlineXXXXXX";
        _cleanup_close_ int fd = -1;
        _cleanup_free_ char *line = NULL;
        pid_t pid;

        if (geteuid() != 0)
                return;

#if HAVE_VALGRIND_VALGRIND_H
        /* valgrind patches open(/proc//cmdline)
         * so, test_get_process_cmdline_harder fails always
         * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
        if (RUNNING_ON_VALGRIND)
                return;
#endif

        pid = fork();
        if (pid > 0) {
                siginfo_t si;

                (void) wait_for_terminate(pid, &si);

                assert_se(si.si_code == CLD_EXITED);
                assert_se(si.si_status == 0);

                return;
        }

        assert_se(pid == 0);
        assert_se(unshare(CLONE_NEWNS) >= 0);

        assert_se(mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) >= 0);

        fd = mkostemp(path, O_CLOEXEC);
        assert_se(fd >= 0);

        if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
                /* This happens under selinux… Abort the test in this case. */
                log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
                assert(errno == EACCES);
                return;
        }

        assert_se(unlink(path) >= 0);

        assert_se(prctl(PR_SET_NAME, "testa") >= 0);

        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);

        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
        assert_se(streq(line, "[testa]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
        assert_se(streq(line, ""));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
        assert_se(streq(line, "["));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
        assert_se(streq(line, "[."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
        assert_se(streq(line, "[.."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
        assert_se(streq(line, "[..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
        assert_se(streq(line, "[...]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
        assert_se(streq(line, "[t...]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
        assert_se(streq(line, "[testa]"));
        line = mfree(line);

        assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);

        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);

        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
        assert_se(streq(line, "[testa]"));
        line = mfree(line);

        assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);

        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
        assert_se(streq(line, "foo bar"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
        assert_se(streq(line, "foo bar"));
        line = mfree(line);

        assert_se(write(fd, "quux", 4) == 4);
        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
        assert_se(streq(line, ""));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
        assert_se(streq(line, "."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
        assert_se(streq(line, ".."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
        assert_se(streq(line, "..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
        assert_se(streq(line, "f..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
        assert_se(streq(line, "fo..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
        assert_se(streq(line, "foo..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
        assert_se(streq(line, "foo..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 9, true, &line) >= 0);
        assert_se(streq(line, "foo b..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
        assert_se(streq(line, "foo ba..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
        assert_se(streq(line, "foo bar..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
        assert_se(streq(line, "foo bar..."));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 13, true, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 14, true, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 1000, true, &line) >= 0);
        assert_se(streq(line, "foo bar quux"));
        line = mfree(line);

        assert_se(ftruncate(fd, 0) >= 0);
        assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);

        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);

        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
        assert_se(streq(line, "[aaaa bbbb cccc]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
        assert_se(streq(line, "[aaaa...]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
        assert_se(streq(line, "[aaaa...]"));
        line = mfree(line);

        assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
        assert_se(streq(line, "[aaaa b...]"));
        line = mfree(line);

        safe_close(fd);
        _exit(EXIT_SUCCESS);
}
コード例 #12
0
ファイル: test-cgroup.c プロジェクト: Keruspe/systemd
int main(int argc, char *argv[]) {
        char *path;
        char *c, *p;

        assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
        assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
        assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);
        assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-c") == 0);
        assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0) == 0);

        assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0);
        assert_se(streq(path, "/test-b"));
        free(path);

        assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) == 0);

        assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0);
        assert_se(path_equal(path, "/test-a"));
        free(path);

        assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", 0) == 0);

        assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0);
        assert_se(path_equal(path, "/test-b/test-d"));
        free(path);

        assert_se(cg_get_path(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", NULL, &path) == 0);
        assert_se(path_equal(path, "/sys/fs/cgroup/systemd/test-b/test-d"));
        free(path);

        assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
        assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0);
        assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
        assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);

        assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, 0, NULL, NULL, NULL) == 0);
        assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, 0, NULL, NULL, NULL) > 0);

        assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) > 0);

        assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
        assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0);

        assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, 0, NULL, NULL, NULL) > 0);
        assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, 0, NULL, NULL, NULL) == 0);

        cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false);

        assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, "/test-b") < 0);
        assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, "/test-a") >= 0);

        assert_se(cg_split_spec("foobar:/", &c, &p) == 0);
        assert_se(streq(c, "foobar"));
        assert_se(streq(p, "/"));
        free(c);
        free(p);

        assert_se(cg_split_spec("foobar:", &c, &p) < 0);
        assert_se(cg_split_spec("foobar:asdfd", &c, &p) < 0);
        assert_se(cg_split_spec(":///", &c, &p) < 0);
        assert_se(cg_split_spec(":", &c, &p) < 0);
        assert_se(cg_split_spec("", &c, &p) < 0);
        assert_se(cg_split_spec("fo/obar:/", &c, &p) < 0);

        assert_se(cg_split_spec("/", &c, &p) >= 0);
        assert_se(c == NULL);
        assert_se(streq(p, "/"));
        free(p);

        assert_se(cg_split_spec("foo", &c, &p) >= 0);
        assert_se(streq(c, "foo"));
        assert_se(p == NULL);
        free(c);

        return 0;
}
コード例 #13
0
ファイル: shutdown.c プロジェクト: Keruspe/systemd
int main(int argc, char *argv[]) {
        bool need_umount, need_swapoff, need_loop_detach, need_dm_detach;
        bool in_container, use_watchdog = false, can_initrd;
        _cleanup_free_ char *cgroup = NULL;
        char *arguments[3];
        int cmd, r, umount_log_level = LOG_INFO;
        static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL};
        char *watchdog_device;

        /* The log target defaults to console, but the original systemd process will pass its log target in through a
         * command line argument, which will override this default. Also, ensure we'll never log to the journal or
         * syslog, as these logging daemons are either already dead or will die very soon. */

        log_set_target(LOG_TARGET_CONSOLE);
        log_set_prohibit_ipc(true);
        log_parse_environment();

        r = parse_argv(argc, argv);
        if (r < 0)
                goto error;

        log_open();

        umask(0022);

        if (getpid_cached() != 1) {
                log_error("Not executed by init (PID 1).");
                r = -EPERM;
                goto error;
        }

        if (streq(arg_verb, "reboot"))
                cmd = RB_AUTOBOOT;
        else if (streq(arg_verb, "poweroff"))
                cmd = RB_POWER_OFF;
        else if (streq(arg_verb, "halt"))
                cmd = RB_HALT_SYSTEM;
        else if (streq(arg_verb, "kexec"))
                cmd = LINUX_REBOOT_CMD_KEXEC;
        else if (streq(arg_verb, "exit"))
                cmd = 0; /* ignored, just checking that arg_verb is valid */
        else {
                log_error("Unknown action '%s'.", arg_verb);
                r = -EINVAL;
                goto error;
        }

        (void) cg_get_root_path(&cgroup);
        in_container = detect_container() > 0;

        use_watchdog = getenv("WATCHDOG_USEC");
        watchdog_device = getenv("WATCHDOG_DEVICE");
        if (watchdog_device) {
                r = watchdog_set_device(watchdog_device);
                if (r < 0)
                        log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m",
                                          watchdog_device);
        }

        /* Lock us into memory */
        (void) mlockall(MCL_CURRENT|MCL_FUTURE);

        /* Synchronize everything that is not written to disk yet at this point already. This is a good idea so that
         * slow IO is processed here already and the final process killing spree is not impacted by processes
         * desperately trying to sync IO to disk within their timeout. Do not remove this sync, data corruption will
         * result. */
        if (!in_container)
                sync_with_progress();

        disable_coredumps();

        log_info("Sending SIGTERM to remaining processes...");
        broadcast_signal(SIGTERM, true, true, arg_timeout);

        log_info("Sending SIGKILL to remaining processes...");
        broadcast_signal(SIGKILL, true, false, arg_timeout);

        need_umount = !in_container;
        need_swapoff = !in_container;
        need_loop_detach = !in_container;
        need_dm_detach = !in_container;
        can_initrd = !in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0;

        /* Unmount all mountpoints, swaps, and loopback devices */
        for (;;) {
                bool changed = false;

                if (use_watchdog)
                        watchdog_ping();

                /* Let's trim the cgroup tree on each iteration so
                   that we leave an empty cgroup tree around, so that
                   container managers get a nice notify event when we
                   are down */
                if (cgroup)
                        cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);

                if (need_umount) {
                        log_info("Unmounting file systems.");
                        r = umount_all(&changed, umount_log_level);
                        if (r == 0) {
                                need_umount = false;
                                log_info("All filesystems unmounted.");
                        } else if (r > 0)
                                log_info("Not all file systems unmounted, %d left.", r);
                        else
                                log_error_errno(r, "Failed to unmount file systems: %m");
                }

                if (need_swapoff) {
                        log_info("Deactivating swaps.");
                        r = swapoff_all(&changed);
                        if (r == 0) {
                                need_swapoff = false;
                                log_info("All swaps deactivated.");
                        } else if (r > 0)
                                log_info("Not all swaps deactivated, %d left.", r);
                        else
                                log_error_errno(r, "Failed to deactivate swaps: %m");
                }

                if (need_loop_detach) {
                        log_info("Detaching loop devices.");
                        r = loopback_detach_all(&changed, umount_log_level);
                        if (r == 0) {
                                need_loop_detach = false;
                                log_info("All loop devices detached.");
                        } else if (r > 0)
                                log_info("Not all loop devices detached, %d left.", r);
                        else
                                log_error_errno(r, "Failed to detach loop devices: %m");
                }

                if (need_dm_detach) {
                        log_info("Detaching DM devices.");
                        r = dm_detach_all(&changed, umount_log_level);
                        if (r == 0) {
                                need_dm_detach = false;
                                log_info("All DM devices detached.");
                        } else if (r > 0)
                                log_info("Not all DM devices detached, %d left.", r);
                        else
                                log_error_errno(r, "Failed to detach DM devices: %m");
                }

                if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
                        log_info("All filesystems, swaps, loop devices and DM devices detached.");
                        /* Yay, done */
                        break;
                }

                if (!changed && umount_log_level == LOG_INFO && !can_initrd) {
                        /* There are things we cannot get rid of. Loop one more time
                         * with LOG_ERR to inform the user. Note that we don't need
                         * to do this if there is a initrd to switch to, because that
                         * one is likely to get rid of the remounting mounts. If not,
                         * it will log about them. */
                        umount_log_level = LOG_ERR;
                        continue;
                }

                /* If in this iteration we didn't manage to
                 * unmount/deactivate anything, we simply give up */
                if (!changed) {
                        log_info("Cannot finalize remaining%s%s%s%s continuing.",
                                 need_umount ? " file systems," : "",
                                 need_swapoff ? " swap devices," : "",
                                 need_loop_detach ? " loop devices," : "",
                                 need_dm_detach ? " DM devices," : "");
                        break;
                }

                log_debug("Couldn't finalize remaining %s%s%s%s trying again.",
                          need_umount ? " file systems," : "",
                          need_swapoff ? " swap devices," : "",
                          need_loop_detach ? " loop devices," : "",
                          need_dm_detach ? " DM devices," : "");
        }

        /* We're done with the watchdog. */
        watchdog_free_device();

        arguments[0] = NULL;
        arguments[1] = arg_verb;
        arguments[2] = NULL;
        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);

        (void) rlimit_nofile_safe();

        if (can_initrd) {
                r = switch_root_initramfs();
                if (r >= 0) {
                        argv[0] = (char*) "/shutdown";

                        (void) setsid();
                        (void) make_console_stdio();

                        log_info("Successfully changed into root pivot.\n"
                                 "Returning to initrd...");

                        execv("/shutdown", argv);
                        log_error_errno(errno, "Failed to execute shutdown binary: %m");
                } else
                        log_error_errno(r, "Failed to switch root to \"/run/initramfs\": %m");

        }

        if (need_umount || need_swapoff || need_loop_detach || need_dm_detach)
                log_error("Failed to finalize %s%s%s%s ignoring",
                          need_umount ? " file systems," : "",
                          need_swapoff ? " swap devices," : "",
                          need_loop_detach ? " loop devices," : "",
                          need_dm_detach ? " DM devices," : "");

        /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be
         * sync'ed explicitly in advance. So let's do this here, but not needlessly slow down containers. Note that we
         * sync'ed things already once above, but we did some more work since then which might have caused IO, hence
         * let's do it once more. Do not remove this sync, data corruption will result. */
        if (!in_container)
                sync_with_progress();

        if (streq(arg_verb, "exit")) {
                if (in_container)
                        return arg_exit_code;

                cmd = RB_POWER_OFF; /* We cannot exit() on the host, fallback on another method. */
        }

        switch (cmd) {

        case LINUX_REBOOT_CMD_KEXEC:

                if (!in_container) {
                        /* We cheat and exec kexec to avoid doing all its work */
                        log_info("Rebooting with kexec.");

                        r = safe_fork("(sd-kexec)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, NULL);
                        if (r == 0) {
                                const char * const args[] = {
                                        KEXEC, "-e", NULL
                                };

                                /* Child */

                                execv(args[0], (char * const *) args);
                                _exit(EXIT_FAILURE);
                        }

                        /* If we are still running, then the kexec can't have worked, let's fall through */
                }

                cmd = RB_AUTOBOOT;
                _fallthrough_;

        case RB_AUTOBOOT:
                (void) reboot_with_parameter(REBOOT_LOG);
                log_info("Rebooting.");
                break;

        case RB_POWER_OFF:
                log_info("Powering off.");
                break;

        case RB_HALT_SYSTEM:
                log_info("Halting system.");
                break;

        default:
                assert_not_reached("Unknown magic");
        }

        (void) reboot(cmd);
        if (errno == EPERM && in_container) {
                /* If we are in a container, and we lacked
                 * CAP_SYS_BOOT just exit, this will kill our
                 * container for good. */
                log_info("Exiting container.");
                return EXIT_SUCCESS;
        }

        r = log_error_errno(errno, "Failed to invoke reboot(): %m");

  error:
        log_emergency_errno(r, "Critical error while doing system shutdown: %m");
        freeze();
}
コード例 #14
0
ファイル: initctl.c プロジェクト: floppym/systemd
int main(int argc, char *argv[]) {
        Server server;
        int r = EXIT_FAILURE, n;

        if (getppid() != 1) {
                log_error("This program should be invoked by init only.");
                return EXIT_FAILURE;
        }

        if (argc > 1) {
                log_error("This program does not take arguments.");
                return EXIT_FAILURE;
        }

        log_set_target(LOG_TARGET_AUTO);
        log_parse_environment();
        log_open();

        umask(0022);

        n = sd_listen_fds(true);
        if (n < 0) {
                log_error_errno(r, "Failed to read listening file descriptors from environment: %m");
                return EXIT_FAILURE;
        }

        if (n <= 0 || n > SERVER_FD_MAX) {
                log_error("No or too many file descriptors passed.");
                return EXIT_FAILURE;
        }

        if (server_init(&server, (unsigned) n) < 0)
                return EXIT_FAILURE;

        log_debug("systemd-initctl running as pid "PID_FMT, getpid_cached());

        sd_notify(false,
                  "READY=1\n"
                  "STATUS=Processing requests...");

        while (!server.quit) {
                struct epoll_event event;
                int k;

                k = epoll_wait(server.epoll_fd, &event, 1, TIMEOUT_MSEC);
                if (k < 0) {
                        if (errno == EINTR)
                                continue;
                        log_error_errno(errno, "epoll_wait() failed: %m");
                        goto fail;
                }

                if (k <= 0)
                        break;

                if (process_event(&server, &event) < 0)
                        goto fail;
        }

        r = EXIT_SUCCESS;

        log_debug("systemd-initctl stopped as pid "PID_FMT, getpid_cached());

fail:
        sd_notify(false,
                  "STOPPING=1\n"
                  "STATUS=Shutting down...");

        server_done(&server);

        return r;
}
コード例 #15
0
ファイル: shutdown.c プロジェクト: torstehu/systemd
int main(int argc, char *argv[]) {
        bool need_umount, need_swapoff, need_loop_detach, need_dm_detach;
        bool in_container, use_watchdog = false;
        _cleanup_free_ char *cgroup = NULL;
        char *arguments[3];
        unsigned retries;
        int cmd, r;
        static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL};

        log_parse_environment();
        r = parse_argv(argc, argv);
        if (r < 0)
                goto error;

        /* journald will die if not gone yet. The log target defaults
         * to console, but may have been changed by command line options. */

        log_close_console(); /* force reopen of /dev/console */
        log_open();

        umask(0022);

        if (getpid_cached() != 1) {
                log_error("Not executed by init (PID 1).");
                r = -EPERM;
                goto error;
        }

        if (streq(arg_verb, "reboot"))
                cmd = RB_AUTOBOOT;
        else if (streq(arg_verb, "poweroff"))
                cmd = RB_POWER_OFF;
        else if (streq(arg_verb, "halt"))
                cmd = RB_HALT_SYSTEM;
        else if (streq(arg_verb, "kexec"))
                cmd = LINUX_REBOOT_CMD_KEXEC;
        else if (streq(arg_verb, "exit"))
                cmd = 0; /* ignored, just checking that arg_verb is valid */
        else {
                r = -EINVAL;
                log_error("Unknown action '%s'.", arg_verb);
                goto error;
        }

        (void) cg_get_root_path(&cgroup);
        in_container = detect_container() > 0;

        use_watchdog = !!getenv("WATCHDOG_USEC");

        /* Lock us into memory */
        mlockall(MCL_CURRENT|MCL_FUTURE);

        /* Synchronize everything that is not written to disk yet at this point already. This is a good idea so that
         * slow IO is processed here already and the final process killing spree is not impacted by processes
         * desperately trying to sync IO to disk within their timeout. */
        if (!in_container)
                sync();

        log_info("Sending SIGTERM to remaining processes...");
        broadcast_signal(SIGTERM, true, true);

        log_info("Sending SIGKILL to remaining processes...");
        broadcast_signal(SIGKILL, true, false);

        need_umount = !in_container;
        need_swapoff = !in_container;
        need_loop_detach = !in_container;
        need_dm_detach = !in_container;

        /* Unmount all mountpoints, swaps, and loopback devices */
        for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
                bool changed = false;

                if (use_watchdog)
                        watchdog_ping();

                /* Let's trim the cgroup tree on each iteration so
                   that we leave an empty cgroup tree around, so that
                   container managers get a nice notify event when we
                   are down */
                if (cgroup)
                        cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);

                if (need_umount) {
                        log_info("Unmounting file systems.");
                        r = umount_all(&changed);
                        if (r == 0) {
                                need_umount = false;
                                log_info("All filesystems unmounted.");
                        } else if (r > 0)
                                log_info("Not all file systems unmounted, %d left.", r);
                        else
                                log_error_errno(r, "Failed to unmount file systems: %m");
                }

                if (need_swapoff) {
                        log_info("Deactivating swaps.");
                        r = swapoff_all(&changed);
                        if (r == 0) {
                                need_swapoff = false;
                                log_info("All swaps deactivated.");
                        } else if (r > 0)
                                log_info("Not all swaps deactivated, %d left.", r);
                        else
                                log_error_errno(r, "Failed to deactivate swaps: %m");
                }

                if (need_loop_detach) {
                        log_info("Detaching loop devices.");
                        r = loopback_detach_all(&changed);
                        if (r == 0) {
                                need_loop_detach = false;
                                log_info("All loop devices detached.");
                        } else if (r > 0)
                                log_info("Not all loop devices detached, %d left.", r);
                        else
                                log_error_errno(r, "Failed to detach loop devices: %m");
                }

                if (need_dm_detach) {
                        log_info("Detaching DM devices.");
                        r = dm_detach_all(&changed);
                        if (r == 0) {
                                need_dm_detach = false;
                                log_info("All DM devices detached.");
                        } else if (r > 0)
                                log_info("Not all DM devices detached, %d left.", r);
                        else
                                log_error_errno(r, "Failed to detach DM devices: %m");
                }

                if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
                        if (retries > 0)
                                log_info("All filesystems, swaps, loop devices, DM devices detached.");
                        /* Yay, done */
                        goto initrd_jump;
                }

                /* If in this iteration we didn't manage to
                 * unmount/deactivate anything, we simply give up */
                if (!changed) {
                        log_info("Cannot finalize remaining%s%s%s%s continuing.",
                                 need_umount ? " file systems," : "",
                                 need_swapoff ? " swap devices," : "",
                                 need_loop_detach ? " loop devices," : "",
                                 need_dm_detach ? " DM devices," : "");
                        goto initrd_jump;
                }

                log_debug("After %u retries, couldn't finalize remaining %s%s%s%s trying again.",
                          retries + 1,
                          need_umount ? " file systems," : "",
                          need_swapoff ? " swap devices," : "",
                          need_loop_detach ? " loop devices," : "",
                          need_dm_detach ? " DM devices," : "");
        }

        log_error("Too many iterations, giving up.");

 initrd_jump:

        arguments[0] = NULL;
        arguments[1] = arg_verb;
        arguments[2] = NULL;
        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);

        if (!in_container && !in_initrd() &&
            access("/run/initramfs/shutdown", X_OK) == 0) {
                r = switch_root_initramfs();
                if (r >= 0) {
                        argv[0] = (char*) "/shutdown";

                        setsid();
                        make_console_stdio();

                        log_info("Successfully changed into root pivot.\n"
                                 "Returning to initrd...");

                        execv("/shutdown", argv);
                        log_error_errno(errno, "Failed to execute shutdown binary: %m");
                } else
                        log_error_errno(r, "Failed to switch root to \"/run/initramfs\": %m");

        }

        if (need_umount || need_swapoff || need_loop_detach || need_dm_detach)
                log_error("Failed to finalize %s%s%s%s ignoring",
                          need_umount ? " file systems," : "",
                          need_swapoff ? " swap devices," : "",
                          need_loop_detach ? " loop devices," : "",
                          need_dm_detach ? " DM devices," : "");

        /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be
         * sync'ed explicitly in advance. So let's do this here, but not needlessly slow down containers. Note that we
         * sync'ed things already once above, but we did some more work since then which might have caused IO, hence
         * let's doit once more. */
        if (!in_container)
                sync();

        if (streq(arg_verb, "exit")) {
                if (in_container)
                        exit(arg_exit_code);
                else {
                        /* We cannot exit() on the host, fallback on another
                         * method. */
                        cmd = RB_POWER_OFF;
                }
        }

        switch (cmd) {

        case LINUX_REBOOT_CMD_KEXEC:

                if (!in_container) {
                        /* We cheat and exec kexec to avoid doing all its work */
                        pid_t pid;

                        log_info("Rebooting with kexec.");

                        pid = fork();
                        if (pid < 0)
                                log_error_errno(errno, "Failed to fork: %m");
                        else if (pid == 0) {

                                const char * const args[] = {
                                        KEXEC, "-e", NULL
                                };

                                /* Child */

                                execv(args[0], (char * const *) args);
                                _exit(EXIT_FAILURE);
                        } else
                                wait_for_terminate_and_warn("kexec", pid, true);
                }

                cmd = RB_AUTOBOOT;
                _fallthrough_;
        case RB_AUTOBOOT:

                if (!in_container) {
                        _cleanup_free_ char *param = NULL;

                        r = read_one_line_file("/run/systemd/reboot-param", &param);
                        if (r < 0 && r != -ENOENT)
                                log_warning_errno(r, "Failed to read reboot parameter file: %m");

                        if (!isempty(param)) {
                                log_info("Rebooting with argument '%s'.", param);
                                syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param);
                                log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
                        }
                }

                log_info("Rebooting.");
                break;

        case RB_POWER_OFF:
                log_info("Powering off.");
                break;

        case RB_HALT_SYSTEM:
                log_info("Halting system.");
                break;

        default:
                assert_not_reached("Unknown magic");
        }

        reboot(cmd);
        if (errno == EPERM && in_container) {
                /* If we are in a container, and we lacked
                 * CAP_SYS_BOOT just exit, this will kill our
                 * container for good. */
                log_info("Exiting container.");
                exit(0);
        }

        r = log_error_errno(errno, "Failed to invoke reboot(): %m");

  error:
        log_emergency_errno(r, "Critical error while doing system shutdown: %m");
        freeze();
}
コード例 #16
0
ファイル: journald.c プロジェクト: heftig/systemd
int main(int argc, char *argv[]) {
        Server server;
        int r;

        if (argc > 1) {
                log_error("This program does not take arguments.");
                return EXIT_FAILURE;
        }

        log_set_target(LOG_TARGET_SAFE);
        log_set_facility(LOG_SYSLOG);
        log_parse_environment();
        log_open();

        umask(0022);

        sigbus_install();

        r = server_init(&server);
        if (r < 0)
                goto finish;

        server_vacuum(&server, false);
        server_flush_to_var(&server, true);
        server_flush_dev_kmsg(&server);

        log_debug("systemd-journald running as pid "PID_FMT, getpid_cached());
        server_driver_message(&server, 0,
                              "MESSAGE_ID=" SD_MESSAGE_JOURNAL_START_STR,
                              LOG_MESSAGE("Journal started"),
                              NULL);

        /* Make sure to send the usage message *after* flushing the
         * journal so entries from the runtime journals are ordered
         * before this message. See #4190 for some details. */
        server_space_usage_message(&server, NULL);

        for (;;) {
                usec_t t = USEC_INFINITY, n;

                r = sd_event_get_state(server.event);
                if (r < 0)
                        goto finish;
                if (r == SD_EVENT_FINISHED)
                        break;

                n = now(CLOCK_REALTIME);

                if (server.max_retention_usec > 0 && server.oldest_file_usec > 0) {

                        /* The retention time is reached, so let's vacuum! */
                        if (server.oldest_file_usec + server.max_retention_usec < n) {
                                log_info("Retention time reached.");
                                server_rotate(&server);
                                server_vacuum(&server, false);
                                continue;
                        }

                        /* Calculate when to rotate the next time */
                        t = server.oldest_file_usec + server.max_retention_usec - n;
                }

#if HAVE_GCRYPT
                if (server.system_journal) {
                        usec_t u;

                        if (journal_file_next_evolve_usec(server.system_journal, &u)) {
                                if (n >= u)
                                        t = 0;
                                else
                                        t = MIN(t, u - n);
                        }
                }
#endif

                r = sd_event_run(server.event, t);
                if (r < 0) {
                        log_error_errno(r, "Failed to run event loop: %m");
                        goto finish;
                }

                server_maybe_append_tags(&server);
                server_maybe_warn_forward_syslog_missed(&server);
        }

        log_debug("systemd-journald stopped as pid "PID_FMT, getpid_cached());
        server_driver_message(&server, 0,
                              "MESSAGE_ID=" SD_MESSAGE_JOURNAL_STOP_STR,
                              LOG_MESSAGE("Journal stopped"),
                              NULL);

finish:
        server_done(&server);

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
コード例 #17
0
ファイル: automount.c プロジェクト: teg/systemd
static void automount_enter_waiting(Automount *a) {
        _cleanup_close_ int ioctl_fd = -1;
        int p[2] = { -1, -1 };
        char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1];
        char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1
                     + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
        bool mounted = false;
        int r, dev_autofs_fd;
        struct stat st;

        assert(a);
        assert(a->pipe_fd < 0);
        assert(a->where);

        set_clear(a->tokens);

        r = unit_fail_if_symlink(UNIT(a), a->where);
        if (r < 0)
                goto fail;

        (void) mkdir_p_label(a->where, 0555);

        unit_warn_if_dir_nonempty(UNIT(a), a->where);

        dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
        if (dev_autofs_fd < 0) {
                r = dev_autofs_fd;
                goto fail;
        }

        if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
                r = -errno;
                goto fail;
        }

        xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
        xsprintf(name, "systemd-"PID_FMT, getpid_cached());
        if (mount(name, a->where, "autofs", 0, options) < 0) {
                r = -errno;
                goto fail;
        }

        mounted = true;

        p[1] = safe_close(p[1]);

        if (stat(a->where, &st) < 0) {
                r = -errno;
                goto fail;
        }

        ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
        if (ioctl_fd < 0) {
                r = ioctl_fd;
                goto fail;
        }

        r = autofs_protocol(dev_autofs_fd, ioctl_fd);
        if (r < 0)
                goto fail;

        r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec);
        if (r < 0)
                goto fail;

        r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
        if (r < 0)
                goto fail;

        (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");

        a->pipe_fd = p[0];
        a->dev_id = st.st_dev;

        automount_set_state(a, AUTOMOUNT_WAITING);

        return;

fail:
        log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");

        safe_close_pair(p);

        if (mounted) {
                r = repeat_unmount(a->where, MNT_DETACH);
                if (r < 0)
                        log_error_errno(r, "Failed to unmount, ignoring: %m");
        }

        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}