Esempio n. 1
0
int cg_install_release_agent(const char *controller, const char *agent) {
        char *fs = NULL, *contents = NULL, *line = NULL, *sc;
        int r;

        assert(controller);
        assert(agent);

        if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
                return r;

        if ((r = read_one_line_file(fs, &contents)) < 0)
                goto finish;

        sc = strstrip(contents);
        if (sc[0] == 0) {

                if (asprintf(&line, "%s\n", agent) < 0) {
                        r = -ENOMEM;
                        goto finish;
                }

                if ((r = write_one_line_file(fs, line)) < 0)
                        goto finish;

        } else if (!streq(sc, agent)) {
                r = -EEXIST;
                goto finish;
        }

        free(fs);
        fs = NULL;
        if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
                goto finish;

        free(contents);
        contents = NULL;
        if ((r = read_one_line_file(fs, &contents)) < 0)
                goto finish;

        sc = strstrip(contents);

        if (streq(sc, "0")) {
                if ((r = write_one_line_file(fs, "1\n")) < 0)
                        goto finish;

                r = 1;
        } else if (!streq(sc, "1")) {
                r = -EIO;
                goto finish;
        } else
                r = 0;

finish:
        free(fs);
        free(contents);
        free(line);

        return r;
}
Esempio n. 2
0
int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b) {
        int r;
        _cleanup_free_ char *path = NULL, *v = NULL;

        assert(a);

        b = cgroup_bonding_find_list(b, a->controller);
        if (!b)
                return 0;

        if (a->map_callback) {
                r = a->map_callback(a->controller, a->name, a->value, &v);
                if (r < 0)
                        return r;
        }

        r = cg_get_path(a->controller, b->path, a->name, &path);
        if (r < 0)
                return r;

        r = write_one_line_file(path, v ? v : a->value);
        if (r < 0)
                log_warning("Failed to write '%s' to %s: %s", v ? v : a->value, path, strerror(-r));

        return r;
}
int block_bump_request_nr(const char *p) {
        struct stat st;
        uint64_t u;
        char *ap = NULL, *line = NULL;
        int r;
        dev_t d;

        assert(p);

        if (stat(p, &st) < 0)
                return -errno;

        if (major(st.st_dev) == 0)
                return 0;

        d = st.st_dev;
        block_get_whole_disk(d, &d);

        if (asprintf(&ap, "/sys/dev/block/%u:%u/queue/nr_requests", major(d), minor(d)) < 0) {
                r= -ENOMEM;
                goto finish;
        }

        r = read_one_line_file(ap, &line);
        if (r < 0) {
                if (r == -ENOENT)
                        r = 0;
                goto finish;
        }

        r = safe_atou64(line, &u);
        if (r >= 0 && u >= BUMP_REQUEST_NR) {
                r = 0;
                goto finish;
        }

        free(line);
        line = NULL;

        if (asprintf(&line, "%lu", (unsigned long) BUMP_REQUEST_NR) < 0) {
                r = -ENOMEM;
                goto finish;
        }

        r = write_one_line_file(ap, line);
        if (r < 0)
                goto finish;

        log_info("Bumped block_nr parameter of %u:%u to %lu. This is a temporary hack and should be removed one day.", major(d), minor(d), (unsigned long) BUMP_REQUEST_NR);
        r = 1;

finish:
        free(ap);
        free(line);

        return r;
}
Esempio n. 4
0
static int apply_rule(const char *rule) {
        int r;

        delete_rule(rule);

        if ((r = write_one_line_file("/proc/sys/fs/binfmt_misc/register", rule)) < 0) {
                log_error("Failed to add binary format: %s", strerror(-r));
                return r;
        }

        return 0;
}
Esempio n. 5
0
int main(int argc, char *argv[]) {
        int r = 0;

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

        umask(0022);

        if (argc > 1) {
                int i;

                for (i = 1; i < argc; i++) {
                        int k;

                        k = apply_file(argv[i], false);
                        if (k < 0 && r == 0)
                                r = k;
                }
        } else {
                char **files, **f;

                r = conf_files_list(&files, ".conf",
                                    "/etc/binfmt.d",
                                    "/run/binfmt.d",
                                    "/usr/local/lib/binfmt.d",
                                    "/usr/lib/binfmt.d",
#ifdef HAVE_SPLIT_USR
                                    "/lib/binfmt.d",
#endif
                                    NULL);
                if (r < 0) {
                        log_error("Failed to enumerate binfmt.d files: %s", strerror(-r));
                        goto finish;
                }

                /* Flush out all rules */
                write_one_line_file("/proc/sys/fs/binfmt_misc/status", "-1");

                STRV_FOREACH(f, files) {
                        int k;

                        k = apply_file(*f, true);
                        if (k < 0 && r == 0)
                                r = k;
                }

                strv_free(files);
        }
Esempio n. 6
0
static int enable_utf8(int fd) {
        int r = 0, k;

        if (ioctl(fd, KDSKBMODE, K_UNICODE) < 0)
                r = -errno;

        if (loop_write(fd, "\033%G", 3, false) < 0)
                r = -errno;

        k = write_one_line_file("/sys/module/vt/parameters/default_utf8", "1");
        if (k < 0)
                r = k;

        if (r < 0)
                log_warning("Failed to enable UTF-8: %s", strerror(-r));

        return r;
}
Esempio n. 7
0
int main(int argc, char *argv[]) {
        int r = 0;

        if (argc > 2) {
                log_error("This program expects one or no arguments.");
                return EXIT_FAILURE;
        }

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

        umask(0022);

        if (argc > 1) {
                r = apply_file(argv[1], false);
        } else {
                char **files, **f;

                /* Flush out all rules */
                write_one_line_file("/proc/sys/fs/binfmt_misc/status", "-1");

                r = conf_files_list(&files, ".conf",
                                    "/run/binfmt.d",
                                    "/etc/binfmt.d",
                                    "/usr/local/lib/binfmt.d",
                                    "/usr/lib/binfmt.d",
                                    NULL);

                if (r < 0) {
                        log_error("Failed to enumerate binfmt.d files: %s", strerror(-r));
                        goto finish;
                }

                STRV_FOREACH(f, files) {
                        int k;

                        k = apply_file(*f, true);
                        if (k < 0 && r == 0)
                                r = k;
                }

                strv_free(files);
        }
int block_set_readahead(const char *p, uint64_t bytes) {
        struct stat st;
        char *ap = NULL, *line = NULL;
        int r;
        dev_t d;

        assert(p);
        assert(bytes);

        if (stat(p, &st) < 0)
                return -errno;

        if (major(st.st_dev) == 0)
                return 0;

        d = st.st_dev;
        block_get_whole_disk(d, &d);

        if (asprintf(&ap, "/sys/dev/block/%u:%u/bdi/read_ahead_kb", major(d), minor(d)) < 0) {
                r = -ENOMEM;
                goto finish;
        }

        if (asprintf(&line, "%llu", (unsigned long long) bytes / 1024ULL) < 0) {
                r = -ENOMEM;
                goto finish;
        }

        r = write_one_line_file(ap, line);
        if (r < 0)
                goto finish;

finish:
        free(ap);
        free(line);

        return r;
}
Esempio n. 9
0
int cg_attach(const char *controller, const char *path, pid_t pid) {
        char *fs;
        int r;
        char c[32];

        assert(controller);
        assert(path);
        assert(pid >= 0);

        if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
                return r;

        if (pid == 0)
                pid = getpid();

        snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
        char_array_0(c);

        r = write_one_line_file(fs, c);
        free(fs);

        return r;
}
Esempio n. 10
0
static int delete_rule(const char *rule) {
        char *x, *fn = NULL, *e;
        int r;

        assert(rule[0]);

        if (!(x = strdup(rule)))
                return log_oom();

        e = strchrnul(x+1, x[0]);
        *e = 0;

        asprintf(&fn, "/proc/sys/fs/binfmt_misc/%s", x+1);
        free(x);

        if (!fn)
                return log_oom();

        r = write_one_line_file(fn, "-1");
        free(fn);

        return r;
}
Esempio n. 11
0
int main(int argc, char *argv[]) {
        enum {
                FD_SOCKET,
                FD_WALL_TIMER,
                FD_NOLOGIN_TIMER,
                FD_SHUTDOWN_TIMER,
                _FD_MAX
        };

        int r = EXIT_FAILURE, n_fds;
        int one = 1;
        struct shutdownd_command c;
        struct pollfd pollfd[_FD_MAX];
        bool exec_shutdown = false, unlink_nologin = false, failed = false;
        unsigned i;

        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_SYSLOG_OR_KMSG);
        log_parse_environment();
        log_open();

        if ((n_fds = sd_listen_fds(true)) < 0) {
                log_error("Failed to read listening file descriptors from environment: %s", strerror(-r));
                return EXIT_FAILURE;
        }

        if (n_fds != 1) {
                log_error("Need exactly one file descriptor.");
                return EXIT_FAILURE;
        }

        if (setsockopt(SD_LISTEN_FDS_START, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
                log_error("SO_PASSCRED failed: %m");
                return EXIT_FAILURE;
        }

        zero(c);
        zero(pollfd);

        pollfd[FD_SOCKET].fd = SD_LISTEN_FDS_START;
        pollfd[FD_SOCKET].events = POLLIN;

        for (i = 0; i < _FD_MAX; i++) {

                if (i == FD_SOCKET)
                        continue;

                pollfd[i].events = POLLIN;

                if ((pollfd[i].fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
                        log_error("timerfd_create(): %m");
                        failed = true;
                }
        }

        if (failed)
                goto finish;

        log_debug("systemd-shutdownd running as pid %lu", (unsigned long) getpid());

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

        do {
                int k;
                usec_t n;

                if (poll(pollfd, _FD_MAX, -1) < 0) {

                        if (errno == EAGAIN || errno == EINTR)
                                continue;

                        log_error("poll(): %m");
                        goto finish;
                }

                n = now(CLOCK_REALTIME);

                if (pollfd[FD_SOCKET].revents) {

                        if ((k = read_packet(pollfd[FD_SOCKET].fd, &c)) < 0)
                                goto finish;
                        else if (k > 0 && c.elapse > 0) {
                                struct itimerspec its;
                                char date[FORMAT_TIMESTAMP_MAX];

                                if (c.warn_wall) {
                                        /* Send wall messages every so often */
                                        zero(its);
                                        timespec_store(&its.it_value, when_wall(n, c.elapse));
                                        if (timerfd_settime(pollfd[FD_WALL_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
                                                log_error("timerfd_settime(): %m");
                                                goto finish;
                                        }

                                        /* Warn immediately if less than 15 minutes are left */
                                        if (n < c.elapse &&
                                            n + 15*USEC_PER_MINUTE >= c.elapse)
                                                warn_wall(n, &c);
                                }

                                /* Disallow logins 5 minutes prior to shutdown */
                                zero(its);
                                timespec_store(&its.it_value, when_nologin(c.elapse));
                                if (timerfd_settime(pollfd[FD_NOLOGIN_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
                                        log_error("timerfd_settime(): %m");
                                        goto finish;
                                }

                                /* Shutdown after the specified time is reached */
                                zero(its);
                                timespec_store(&its.it_value, c.elapse);
                                if (timerfd_settime(pollfd[FD_SHUTDOWN_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
                                        log_error("timerfd_settime(): %m");
                                        goto finish;
                                }

                                sd_notifyf(false,
                                           "STATUS=Shutting down at %s...",
                                           format_timestamp(date, sizeof(date), c.elapse));
                        }
                }

                if (pollfd[FD_WALL_TIMER].revents) {
                        struct itimerspec its;

                        warn_wall(n, &c);
                        flush_fd(pollfd[FD_WALL_TIMER].fd);

                        /* Restart timer */
                        zero(its);
                        timespec_store(&its.it_value, when_wall(n, c.elapse));
                        if (timerfd_settime(pollfd[FD_WALL_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
                                log_error("timerfd_settime(): %m");
                                goto finish;
                        }
                }

                if (pollfd[FD_NOLOGIN_TIMER].revents) {
                        int e;

                        log_info("Creating /run/nologin, blocking further logins...");

                        if ((e = write_one_line_file("/run/nologin", "System is going down.")) < 0)
                                log_error("Failed to create /run/nologin: %s", strerror(-e));
                        else
                                unlink_nologin = true;

                        flush_fd(pollfd[FD_NOLOGIN_TIMER].fd);
                }

                if (pollfd[FD_SHUTDOWN_TIMER].revents) {
                        exec_shutdown = true;
                        goto finish;
                }

        } while (c.elapse > 0);

        r = EXIT_SUCCESS;

        log_debug("systemd-shutdownd stopped as pid %lu", (unsigned long) getpid());

finish:

        for (i = 0; i < _FD_MAX; i++)
                if (pollfd[i].fd >= 0)
                        close_nointr_nofail(pollfd[i].fd);

        if (unlink_nologin)
                unlink("/run/nologin");

        if (exec_shutdown) {
                char sw[3];

                sw[0] = '-';
                sw[1] = c.mode;
                sw[2] = 0;

                execl(SYSTEMCTL_BINARY_PATH,
                      "shutdown",
                      sw,
                      "now",
                      (c.warn_wall && c.wall_message[0]) ? c.wall_message :
                      (c.warn_wall ? NULL : "--no-wall"),
                      NULL);

                log_error("Failed to execute /sbin/shutdown: %m");
        }

        sd_notify(false,
                  "STATUS=Exiting...");

        return r;
}
Esempio n. 12
0
int machine_id_setup(void) {
        int fd, r;
        bool writable;
        struct stat st;
        char id[34]; /* 32 + \n + \0 */
        mode_t m;

        m = umask(0000);

        /* We create this 0444, to indicate that this isn't really
         * something you should ever modify. Of course, since the file
         * will be owned by root it doesn't matter much, but maybe
         * people look. */

        if ((fd = open("/etc/machine-id", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444)) >= 0)
                writable = true;
        else {
                if ((fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0) {
                        umask(m);
                        log_error("Cannot open /etc/machine-id: %m");
                        return -errno;
                }

                writable = false;
        }

        umask(m);

        if (fstat(fd, &st) < 0) {
                log_error("fstat() failed: %m");
                r = -errno;
                goto finish;
        }

        if (S_ISREG(st.st_mode)) {
                if (loop_read(fd, id, 32, false) >= 32) {
                        r = 0;
                        goto finish;
                }
        }

        /* Hmm, so, the id currently stored is not useful, then let's
         * generate one */

        if ((r = generate(id)) < 0)
                goto finish;

        if (S_ISREG(st.st_mode) && writable) {
                lseek(fd, 0, SEEK_SET);

                if (loop_write(fd, id, 33, false) == 33) {
                        r = 0;
                        goto finish;
                }
        }

        close_nointr_nofail(fd);
        fd = -1;

        /* Hmm, we couldn't write it? So let's write it to
         * /run/systemd/machine-id as a replacement */

        mkdir_p("/run/systemd", 0755);

        if ((r = write_one_line_file("/run/systemd/machine-id", id)) < 0) {
                log_error("Cannot write /run/systemd/machine-id: %s", strerror(-r));

                unlink("/run/systemd/machine-id");
                goto finish;
        }

        /* And now, let's mount it over */
        r = mount("/run/systemd/machine-id", "/etc/machine-id", "bind", MS_BIND|MS_RDONLY, NULL) < 0 ? -errno : 0;
        unlink("/run/systemd/machine-id");

        if (r < 0)
                log_error("Failed to mount /etc/machine-id: %s", strerror(-r));
        else
                log_info("Installed transient /etc/machine-id file.");

finish:

        if (fd >= 0)
                close_nointr_nofail(fd);

        return r;
}