コード例 #1
0
void server_forward_kmsg(
        Server *s,
        int priority,
        const char *identifier,
        const char *message,
        struct ucred *ucred) {

        struct iovec iovec[5];
        char header_priority[6], header_pid[16];
        int n = 0;
        char *ident_buf = NULL;

        assert(s);
        assert(priority >= 0);
        assert(priority <= 999);
        assert(message);

        if (_unlikely_(LOG_PRI(priority) > s->max_level_kmsg))
                return;

        if (_unlikely_(s->dev_kmsg_fd < 0))
                return;

        /* Never allow messages with kernel facility to be written to
         * kmsg, regardless where the data comes from. */
        priority = syslog_fixup_facility(priority);

        /* First: priority field */
        snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
        char_array_0(header_priority);
        IOVEC_SET_STRING(iovec[n++], header_priority);

        /* Second: identifier and PID */
        if (ucred) {
                if (!identifier) {
                        get_process_comm(ucred->pid, &ident_buf);
                        identifier = ident_buf;
                }

                snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
                char_array_0(header_pid);

                if (identifier)
                        IOVEC_SET_STRING(iovec[n++], identifier);

                IOVEC_SET_STRING(iovec[n++], header_pid);
        } else if (identifier) {
                IOVEC_SET_STRING(iovec[n++], identifier);
                IOVEC_SET_STRING(iovec[n++], ": ");
        }

        /* Fourth: message */
        IOVEC_SET_STRING(iovec[n++], message);
        IOVEC_SET_STRING(iovec[n++], "\n");

        if (writev(s->dev_kmsg_fd, iovec, n) < 0)
                log_debug("Failed to write to /dev/kmsg for logging: %m");

        free(ident_buf);
}
コード例 #2
0
ファイル: localed.c プロジェクト: vlajos/systemd
static int x11_read_data(Context *c) {
        _cleanup_fclose_ FILE *f;
        char line[LINE_MAX];
        bool in_section = false;
        int r;

        context_free_x11(c);

        f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
        if (!f)
                return errno == ENOENT ? 0 : -errno;

        while (fgets(line, sizeof(line), f)) {
                char *l;

                char_array_0(line);
                l = strstrip(line);

                if (l[0] == 0 || l[0] == '#')
                        continue;

                if (in_section && first_word(l, "Option")) {
                        _cleanup_strv_free_ char **a = NULL;

                        r = strv_split_quoted(&a, l, false);
                        if (r < 0)
                                return r;

                        if (strv_length(a) == 3) {
                                if (streq(a[1], "XkbLayout")) {
                                        free_and_replace(&c->x11_layout, a[2]);
                                        a[2] = NULL;
                                } else if (streq(a[1], "XkbModel")) {
                                        free_and_replace(&c->x11_model, a[2]);
                                        a[2] = NULL;
                                } else if (streq(a[1], "XkbVariant")) {
                                        free_and_replace(&c->x11_variant, a[2]);
                                        a[2] = NULL;
                                } else if (streq(a[1], "XkbOptions")) {
                                        free_and_replace(&c->x11_options, a[2]);
                                        a[2] = NULL;
                                }
                        }

                } else if (!in_section && first_word(l, "Section")) {
                        _cleanup_strv_free_ char **a = NULL;

                        r = strv_split_quoted(&a, l, false);
                        if (r < 0)
                                return -ENOMEM;

                        if (strv_length(a) == 2 && streq(a[1], "InputClass"))
                                in_section = true;

                } else if (in_section && first_word(l, "EndSection"))
                        in_section = false;
        }

        return 0;
}
コード例 #3
0
ファイル: log.c プロジェクト: AdamWill/dracut
_noreturn_ static void log_assert(const char *text, const char *file, int line, const char *func, const char *format) {
        static char buffer[LINE_MAX];

        snprintf(buffer, sizeof(buffer), format, text, file, line, func);

        char_array_0(buffer);
        log_abort_msg = buffer;

        log_dispatch(LOG_CRIT, file, line, func, buffer);
        abort();
}
コード例 #4
0
ファイル: journal-send.c プロジェクト: vitalikp/journal
_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {

        /* FIXME: Instead of limiting things to LINE_MAX we could do a
           C99 variable-length array on the stack here in a loop. */

        char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];

        assert_return(priority >= 0, -EINVAL);
        assert_return(priority <= 7, -EINVAL);
        assert_return(format, -EINVAL);

        snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
        char_array_0(p);

        memcpy(buffer, "MESSAGE=", 8);
        vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
        char_array_0(buffer);

        zero(iov);
        IOVEC_SET_STRING(iov[0], buffer);
        IOVEC_SET_STRING(iov[1], p);

        return sd_journal_sendv(iov, 2);
}
コード例 #5
0
ファイル: log.c プロジェクト: AdamWill/dracut
int log_metav(
        int level,
        const char*file,
        int line,
        const char *func,
        const char *format,
        va_list ap) {

        char buffer[LINE_MAX];
        int saved_errno, r;

        if (_likely_(LOG_PRI(level) > log_max_level))
                return 0;

        saved_errno = errno;
        vsnprintf(buffer, sizeof(buffer), format, ap);
        char_array_0(buffer);

        r = log_dispatch(level, file, line, func, buffer);
        errno = saved_errno;

        return r;
}
コード例 #6
0
ファイル: resolved-link.c プロジェクト: nmartensen/systemd
int link_update_rtnl(Link *l, sd_netlink_message *m) {
        const char *n = NULL;
        int r;

        assert(l);
        assert(m);

        r = sd_rtnl_message_link_get_flags(m, &l->flags);
        if (r < 0)
                return r;

        sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);

        if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
                strncpy(l->name, n, sizeof(l->name)-1);
                char_array_0(l->name);
        }

        link_allocate_scopes(l);
        link_add_rrs(l, false);

        return 0;
}
コード例 #7
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;
}
コード例 #8
0
ファイル: keymap-util.c プロジェクト: halfline/systemd
int x11_read_data(Context *c, sd_bus_message *m) {
        _cleanup_fclose_ FILE *f = NULL;
        bool in_section = false;
        char line[LINE_MAX];
        struct stat st;
        usec_t t;
        int r;

        /* Do not try to re-read the file within single bus operation. */
        if (m) {
                if (m == c->x11_cache)
                        return 0;

                sd_bus_message_unref(c->x11_cache);
                c->x11_cache = sd_bus_message_ref(m);
        }

        if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) < 0) {
                if (errno != ENOENT)
                        return -errno;

                c->x11_mtime = USEC_INFINITY;
                context_free_x11(c);
                return 0;
        }

        /* If mtime is not changed, then we do not need to re-read */
        t = timespec_load(&st.st_mtim);
        if (c->x11_mtime != USEC_INFINITY && t == c->x11_mtime)
                return 0;

        c->x11_mtime = t;
        context_free_x11(c);

        f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
        if (!f)
                return -errno;

        while (fgets(line, sizeof(line), f)) {
                char *l;

                char_array_0(line);
                l = strstrip(line);

                if (IN_SET(l[0], 0, '#'))
                        continue;

                if (in_section && first_word(l, "Option")) {
                        _cleanup_strv_free_ char **a = NULL;

                        r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES);
                        if (r < 0)
                                return r;

                        if (strv_length(a) == 3) {
                                char **p = NULL;

                                if (streq(a[1], "XkbLayout"))
                                        p = &c->x11_layout;
                                else if (streq(a[1], "XkbModel"))
                                        p = &c->x11_model;
                                else if (streq(a[1], "XkbVariant"))
                                        p = &c->x11_variant;
                                else if (streq(a[1], "XkbOptions"))
                                        p = &c->x11_options;

                                if (p) {
                                        free_and_replace(*p, a[2]);
                                }
                        }

                } else if (!in_section && first_word(l, "Section")) {
                        _cleanup_strv_free_ char **a = NULL;

                        r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES);
                        if (r < 0)
                                return -ENOMEM;

                        if (strv_length(a) == 2 && streq(a[1], "InputClass"))
                                in_section = true;

                } else if (in_section && first_word(l, "EndSection"))
                        in_section = false;
        }

        return 0;
}
コード例 #9
0
ファイル: localed.c プロジェクト: mariux/systemd
static int read_data_x11(void) {
        FILE *f;
        char line[LINE_MAX];
        bool in_section = false;

        free_data_x11();

        f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
        if (!f) {
                if (errno == ENOENT) {

#ifdef TARGET_FEDORA
                        f = fopen("/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf", "re");
                        if (!f) {
                                if (errno == ENOENT)
                                        return 0;
                                else
                                        return -errno;
                        }
#else
                        return 0;
#endif

                } else
                          return -errno;
        }

        while (fgets(line, sizeof(line), f)) {
                char *l;

                char_array_0(line);
                l = strstrip(line);

                if (l[0] == 0 || l[0] == '#')
                        continue;

                if (in_section && first_word(l, "Option")) {
                        char **a;

                        a = strv_split_quoted(l);
                        if (!a) {
                                fclose(f);
                                return -ENOMEM;
                        }

                        if (strv_length(a) == 3) {

                                if (streq(a[1], "XkbLayout")) {
                                        free(state.x11_layout);
                                        state.x11_layout = a[2];
                                        a[2] = NULL;
                                } else if (streq(a[1], "XkbModel")) {
                                        free(state.x11_model);
                                        state.x11_model = a[2];
                                        a[2] = NULL;
                                } else if (streq(a[1], "XkbVariant")) {
                                        free(state.x11_variant);
                                        state.x11_variant = a[2];
                                        a[2] = NULL;
                                } else if (streq(a[1], "XkbOptions")) {
                                        free(state.x11_options);
                                        state.x11_options = a[2];
                                        a[2] = NULL;
                                }
                        }

                        strv_free(a);

                } else if (!in_section && first_word(l, "Section")) {
                        char **a;

                        a = strv_split_quoted(l);
                        if (!a) {
                                fclose(f);
                                return -ENOMEM;
                        }

                        if (strv_length(a) == 2 && streq(a[1], "InputClass"))
                                in_section = true;

                        strv_free(a);
                } else if (in_section && first_word(l, "EndSection"))
                        in_section = false;
        }

        fclose(f);

        return 0;
}
コード例 #10
0
static int unpack_file(FILE *pack) {
        _cleanup_close_ int fd = -1;
        char fn[PATH_MAX];
        bool any = false;
        struct stat st;
        uint64_t inode;

        assert(pack);

        if (!fgets(fn, sizeof(fn), pack))
                return 0;

        char_array_0(fn);
        truncate_nl(fn);

        fd = open(fn, O_RDONLY|O_CLOEXEC|O_NOATIME|O_NOCTTY|O_NOFOLLOW);
        if (fd < 0) {
                if (errno != ENOENT && errno != EPERM && errno != EACCES && errno != ELOOP)
                        log_warning("open(%s) failed: %m", fn);

        } else if (file_verify(fd, fn, arg_file_size_max, &st) <= 0)
                fd = safe_close(fd);

        if (fread(&inode, sizeof(inode), 1, pack) != 1) {
                log_error("Premature end of pack file.");
                return -EIO;
        }

        if (fd >= 0) {
                /* If the inode changed the file got deleted, so just
                 * ignore this entry */
                if (st.st_ino != (uint64_t) inode)
                        fd = safe_close(fd);
        }

        for (;;) {
                uint32_t b, c;

                if (fread(&b, sizeof(b), 1, pack) != 1 ||
                    fread(&c, sizeof(c), 1, pack) != 1) {
                        log_error("Premature end of pack file.");
                        return -EIO;
                }

                if (b == 0 && c == 0)
                        break;

                if (c <= b) {
                        log_error("Invalid pack file.");
                        return -EIO;
                }

                log_debug("%s: page %u to %u", fn, b, c);

                any = true;

                if (fd >= 0) {
                        if (posix_fadvise(fd, b * page_size(), (c - b) * page_size(), POSIX_FADV_WILLNEED) < 0) {
                                log_warning("posix_fadvise() failed: %m");
                                return -errno;
                        }
                }
        }

        if (!any && fd >= 0) {
                /* if no range is encoded in the pack file this is
                 * intended to mean that the whole file shall be
                 * read */

                if (posix_fadvise(fd, 0, st.st_size, POSIX_FADV_WILLNEED) < 0) {
                        log_warning("posix_fadvise() failed: %m");
                        return -errno;
                }
        }

        return 0;
}
コード例 #11
0
ファイル: timedatectl.c プロジェクト: chenyf/systemd
static void print_status_info(const StatusInfo *i) {
        char a[FORMAT_TIMESTAMP_MAX];
        char b[FORMAT_TIMESTAMP_MAX];
        char s[32];
        struct tm tm;
        time_t sec;
        bool have_time = false;
        _cleanup_free_ char *zc = NULL, *zn = NULL;
        time_t t, tc, tn;
        int dn = 0;
        bool is_dstc = false, is_dstn = false;
        int r;

        assert(i);

        /* Enforce the values of /etc/localtime */
        if (getenv("TZ")) {
                fprintf(stderr, "Warning: Ignoring the TZ variable. Reading the system's time zone setting only.\n\n");
                unsetenv("TZ");
        }

        if (i->time != 0) {
                sec = (time_t) (i->time / USEC_PER_SEC);
                have_time = true;
        } else if (arg_transport == BUS_TRANSPORT_LOCAL) {
                sec = time(NULL);
                have_time = true;
        } else
                fprintf(stderr, "Warning: Could not get time from timedated and not operating locally.\n\n");

        if (have_time) {
                zero(tm);
                assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) > 0);
                char_array_0(a);
                printf("      Local time: %s\n", a);

                zero(tm);
                assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)) > 0);
                char_array_0(a);
                printf("  Universal time: %s\n", a);
        } else {
                printf("      Local time: %s\n", "n/a");
                printf("  Universal time: %s\n", "n/a");
        }

        if (i->rtc_time > 0) {
                time_t rtc_sec;

                rtc_sec = (time_t)(i->rtc_time / USEC_PER_SEC);
                zero(tm);
                assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm)) > 0);
                char_array_0(a);
                printf("        RTC time: %s\n", a);
        } else
                printf("        RTC time: %s\n", "n/a");

        if (have_time) {
                zero(tm);
                assert_se(strftime(a, sizeof(a), "%Z, %z", localtime_r(&sec, &tm)) > 0);
                char_array_0(a);
        }

        printf("       Time zone: %s (%s)\n"
               "     NTP enabled: %s\n"
               "NTP synchronized: %s\n"
               " RTC in local TZ: %s\n",
               strna(i->timezone), have_time ? a : "n/a",
               i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
               yes_no(i->ntp_synced),
               yes_no(i->rtc_local));

        if (have_time) {
                r = time_get_dst(sec, "/etc/localtime",
                                 &tc, &zc, &is_dstc,
                                 &tn, &dn, &zn, &is_dstn);
                if (r < 0)
                        printf("      DST active: %s\n", "n/a");
                else {
                        printf("      DST active: %s\n", yes_no(is_dstc));

                        t = tc - 1;
                        zero(tm);
                        assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
                        char_array_0(a);

                        zero(tm);
                        assert_se(strftime(b, sizeof(b), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm)) > 0);
                        char_array_0(b);
                        printf(" Last DST change: DST %s at\n"
                               "                  %s\n"
                               "                  %s\n",
                               is_dstc ? "began" : "ended", a, b);

                        t = tn - 1;
                        zero(tm);
                        assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
                        char_array_0(a);

                        zero(tm);
                        assert_se(strftime(b, sizeof(b), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm)) > 0);
                        char_array_0(b);
                        printf(" Next DST change: DST %s (the clock jumps %s) at\n"
                               "                  %s\n"
                               "                  %s\n",
                               is_dstn ? "begins" : "ends", jump_str(dn, s, sizeof(s)), a, b);
                }
        } else
                printf("      DST active: %s\n", yes_no(is_dstc));

        if (i->rtc_local)
                fputs("\n" ANSI_HIGHLIGHT_ON
                      "Warning: The system is configured to read the RTC time in the local time zone. This\n"
                      "         mode can not be fully supported. It will create various problems with time\n"
                      "         zone changes and daylight saving time adjustments. The RTC time is never updated,\n"
                      "         it relies on external facilities to maintain it. If at all possible, use\n"
                      "         RTC in UTC by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
}
コード例 #12
0
static int replay(const char *root) {
        _cleanup_close_ int inotify_fd = -1;
        _cleanup_free_ char *pack_fn = NULL;
        _cleanup_fclose_ FILE *pack = NULL;
        bool on_ssd, ready = false;
        char line[LINE_MAX];
        int prio, c;

        assert(root);

        if (asprintf(&pack_fn, "%s/.readahead", root) < 0)
                return log_oom();

        pack = fopen(pack_fn, "re");
        if (!pack) {
                if (errno == ENOENT) {
                        log_debug("No pack file found.");
                        return 0;
                }

                log_error("Failed to open pack file: %m");
                return -errno;
        }

        posix_fadvise(fileno(pack), 0, 0, POSIX_FADV_WILLNEED);

        inotify_fd = open_inotify();
        if (inotify_fd < 0)
                return inotify_fd;

        if (!fgets(line, sizeof(line), pack)) {
                log_error("Premature end of pack file.");
                return -EIO;
        }

        char_array_0(line);

        if (!streq(line, CANONICAL_HOST READAHEAD_PACK_FILE_VERSION)) {
                log_debug("Pack file host or version type mismatch.");
                goto done;
        }

        c = getc(pack);
        if (c == EOF) {
                log_debug("Premature end of pack file.");
                return -EIO;
        }

        /* We do not retest SSD here, so that we can start replaying
         * before udev is up.*/
        on_ssd = c == 'S';
        log_debug("On SSD: %s", yes_no(on_ssd));

        if (on_ssd)
                prio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0);
        else
                /* We are not using RT here, since we'd starve IO that
                we didn't record (which is for example blkid, since
                its disk accesses go directly to the block device and
                are thus not visible in fallocate) to death. However,
                we do ask for an IO prio that is slightly higher than
                the default (which is BE. 4) */
                prio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 2);

        if (ioprio_set(IOPRIO_WHO_PROCESS, getpid(), prio) < 0)
                log_warning("Failed to set IDLE IO priority class: %m");

        sd_notify(0, "STATUS=Replaying readahead data");

        log_debug("Replaying...");

        if (access("/run/systemd/readahead/noreplay", F_OK) >= 0) {
                log_debug("Got termination request");
                goto done;
        }

        while (!feof(pack) && !ferror(pack)) {
                uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
                int k;
                ssize_t n;

                n = read(inotify_fd, &inotify_buffer, sizeof(inotify_buffer));
                if (n < 0) {
                        if (errno != EINTR && errno != EAGAIN) {
                                log_error("Failed to read inotify event: %m");
                                return -errno;
                        }
                } else {
                        struct inotify_event *e = (struct inotify_event*) inotify_buffer;

                        while (n > 0) {
                                size_t step;

                                if ((e->mask & IN_CREATE) && streq(e->name, "noreplay")) {
                                        log_debug("Got termination request");
                                        goto done;
                                }

                                step = sizeof(struct inotify_event) + e->len;
                                assert(step <= (size_t) n);

                                e = (struct inotify_event*) ((uint8_t*) e + step);
                                n -= step;
                        }
                }

                k = unpack_file(pack);
                if (k < 0)
                        return k;

                if (!ready) {
                        /* We delay the ready notification until we
                         * queued at least one read */
                        sd_notify(0, "READY=1");
                        ready = true;
                }
        }

done:
        if (ferror(pack)) {
                log_error("Failed to read pack file.");
                return -EIO;
        }

        if (!ready)
                sd_notify(0, "READY=1");

        log_debug("Done.");
        return 0;
}
コード例 #13
0
ファイル: journal-send.c プロジェクト: vitalikp/journal
_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
        PROTECT_ERRNO;
        int fd;
        struct iovec *w;
        uint64_t *l;
        int i, j = 0;
        struct sockaddr_un sa = {
                .sun_family = AF_UNIX,
                .sun_path = JOURNAL_RUNDIR "/socket",
        };
        struct msghdr mh = {
                .msg_name = &sa,
                .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path),
        };
        ssize_t k;
        union {
                struct cmsghdr cmsghdr;
                uint8_t buf[CMSG_SPACE(sizeof(int))];
        } control;
        bool have_syslog_identifier = false;

        assert_return(iov, -EINVAL);
        assert_return(n > 0, -EINVAL);

        w = alloca(sizeof(struct iovec) * n * 5 + 3);
        l = alloca(sizeof(uint64_t) * n);

        for (i = 0; i < n; i++) {
                char *c, *nl;

                if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1))
                        return -EINVAL;

                c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
                if (_unlikely_(!c || c == iov[i].iov_base))
                        return -EINVAL;

                have_syslog_identifier = have_syslog_identifier ||
                        (c == (char *) iov[i].iov_base + 17 &&
                         startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER"));

                nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
                if (nl) {
                        if (_unlikely_(nl < c))
                                return -EINVAL;

                        /* Already includes a newline? Bummer, then
                         * let's write the variable name, then a
                         * newline, then the size (64bit LE), followed
                         * by the data and a final newline */

                        w[j].iov_base = iov[i].iov_base;
                        w[j].iov_len = c - (char*) iov[i].iov_base;
                        j++;

                        IOVEC_SET_STRING(w[j++], "\n");

                        l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
                        w[j].iov_base = &l[i];
                        w[j].iov_len = sizeof(uint64_t);
                        j++;

                        w[j].iov_base = c + 1;
                        w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
                        j++;

                } else
                        /* Nothing special? Then just add the line and
                         * append a newline */
                        w[j++] = iov[i];

                IOVEC_SET_STRING(w[j++], "\n");
        }

        if (!have_syslog_identifier) {

                /* Implicitly add program_invocation_short_name, if it
                 * is not set explicitly. We only do this for
                 * program_invocation_short_name, and nothing else
                 * since everything else is much nicer to retrieve
                 * from the outside. */

                IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
                IOVEC_SET_STRING(w[j++], program_invocation_short_name);
                IOVEC_SET_STRING(w[j++], "\n");
        }

        fd = journal_fd();
        if (_unlikely_(fd < 0))
                return fd;

        mh.msg_iov = w;
        mh.msg_iovlen = j;

        k = sendmsg(fd, &mh, MSG_NOSIGNAL);
        if (k >= 0)
                return 0;

        /* Fail silently if the journal is not available */
        if (errno == ENOENT)
                return 0;

        if (errno != EMSGSIZE && errno != ENOBUFS)
                return -errno;

        return 0;
}

static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
        PROTECT_ERRNO;
        size_t n, k;

        k = isempty(message) ? 0 : strlen(message) + 2;
        n = 8 + k + 256 + 1;

        for (;;) {
                char buffer[n];
                char* j;

                errno = 0;
                j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
                if (errno == 0) {
                        char error[6 + 10 + 1]; /* for a 32bit value */

                        if (j != buffer + 8 + k)
                                memmove(buffer + 8 + k, j, strlen(j)+1);

                        memcpy(buffer, "MESSAGE=", 8);

                        if (k > 0) {
                                memcpy(buffer + 8, message, k - 2);
                                memcpy(buffer + 8 + k - 2, ": ", 2);
                        }

                        snprintf(error, sizeof(error), "ERRNO=%u", _saved_errno_);
                        char_array_0(error);

                        IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
                        IOVEC_SET_STRING(iov[skip+1], buffer);
                        IOVEC_SET_STRING(iov[skip+2], error);

                        return sd_journal_sendv(iov, skip + 3);
                }

                if (errno != ERANGE)
                        return -errno;

                n *= 2;
        }
}

_public_ int sd_journal_perror(const char *message) {
        struct iovec iovec[3];

        return fill_iovec_perror_and_send(message, 0, iovec);
}
コード例 #14
0
ファイル: shutdownd.c プロジェクト: terralinux/systemd
static int read_packet(int fd, struct shutdownd_command *_c) {
        struct msghdr msghdr;
        struct iovec iovec;
        struct ucred *ucred;
        union {
                struct cmsghdr cmsghdr;
                uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
        } control;
        struct shutdownd_command c;
        ssize_t n;

        assert(fd >= 0);
        assert(_c);

        zero(iovec);
        iovec.iov_base = &c;
        iovec.iov_len = sizeof(c);

        zero(control);
        zero(msghdr);
        msghdr.msg_iov = &iovec;
        msghdr.msg_iovlen = 1;
        msghdr.msg_control = &control;
        msghdr.msg_controllen = sizeof(control);

        if ((n = recvmsg(fd, &msghdr, MSG_DONTWAIT)) <= 0) {
                if (n >= 0) {
                        log_error("Short read");
                        return -EIO;
                }

                if (errno == EAGAIN || errno == EINTR)
                        return 0;

                log_error("recvmsg(): %m");
                return -errno;
        }

        if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
            control.cmsghdr.cmsg_level != SOL_SOCKET ||
            control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
            control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
                log_warning("Received message without credentials. Ignoring.");
                return 0;
        }

        ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
        if (ucred->uid != 0) {
                log_warning("Got request from unprivileged user. Ignoring.");
                return 0;
        }

        if (n != sizeof(c)) {
                log_warning("Message has invalid size. Ignoring");
                return 0;
        }

        char_array_0(c.wall_message);

        *_c = c;
        return 1;
}
コード例 #15
0
ファイル: fsck.c プロジェクト: RoadRunnr/systemd
int main(int argc, char *argv[]) {
        const char *cmdline[9];
        int i = 0, r = EXIT_FAILURE, q;
        pid_t pid;
        siginfo_t status;
        struct udev *udev = NULL;
        struct udev_device *udev_device = NULL;
        const char *device;
        bool root_directory;
        int progress_pipe[2] = { -1, -1 };
        char dash_c[2+10+1];

        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);

        parse_proc_cmdline();
        test_files();

        if (!arg_force && arg_skip)
                return 0;

        if (argc > 1) {
                device = argv[1];
                root_directory = false;
        } else {
                struct stat st;
                struct timespec times[2];

                /* Find root device */

                if (stat("/", &st) < 0) {
                        log_error("Failed to stat() the root directory: %m");
                        goto finish;
                }

                /* Virtual root devices don't need an fsck */
                if (major(st.st_dev) == 0)
                        return 0;

                /* check if we are already writable */
                times[0] = st.st_atim;
                times[1] = st.st_mtim;
                if (utimensat(AT_FDCWD, "/", times, 0) == 0) {
                        log_info("Root directory is writable, skipping check.");
                        return 0;
                }

                if (!(udev = udev_new())) {
                        log_oom();
                        goto finish;
                }

                if (!(udev_device = udev_device_new_from_devnum(udev, 'b', st.st_dev))) {
                        log_error("Failed to detect root device.");
                        goto finish;
                }

                if (!(device = udev_device_get_devnode(udev_device))) {
                        log_error("Failed to detect device node of root directory.");
                        goto finish;
                }

                root_directory = true;
        }

        if (arg_show_progress)
                if (pipe(progress_pipe) < 0) {
                        log_error("pipe(): %m");
                        goto finish;
                }

        cmdline[i++] = "/sbin/fsck";
        cmdline[i++] = "-a";
        cmdline[i++] = "-T";
        cmdline[i++] = "-l";

        if (!root_directory)
                cmdline[i++] = "-M";

        if (arg_force)
                cmdline[i++] = "-f";

        if (progress_pipe[1] >= 0) {
                snprintf(dash_c, sizeof(dash_c), "-C%i", progress_pipe[1]);
                char_array_0(dash_c);
                cmdline[i++] = dash_c;
        }

        cmdline[i++] = device;
        cmdline[i++] = NULL;

        pid = fork();
        if (pid < 0) {
                log_error("fork(): %m");
                goto finish;
        } else if (pid == 0) {
                /* Child */
                if (progress_pipe[0] >= 0)
                        close_nointr_nofail(progress_pipe[0]);
                execv(cmdline[0], (char**) cmdline);
                _exit(8); /* Operational error */
        }

        if (progress_pipe[1] >= 0) {
                close_nointr_nofail(progress_pipe[1]);
                progress_pipe[1] = -1;
        }

        if (progress_pipe[0] >= 0) {
                process_progress(progress_pipe[0]);
                progress_pipe[0] = -1;
        }

        q = wait_for_terminate(pid, &status);
        if (q < 0) {
                log_error("waitid(): %s", strerror(-q));
                goto finish;
        }

        if (status.si_code != CLD_EXITED || (status.si_status & ~1)) {

                if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED)
                        log_error("fsck terminated by signal %s.", signal_to_string(status.si_status));
                else if (status.si_code == CLD_EXITED)
                        log_error("fsck failed with error code %i.", status.si_status);
                else
                        log_error("fsck failed due to unknown reason.");

                if (status.si_code == CLD_EXITED && (status.si_status & 2) && root_directory)
                        /* System should be rebooted. */
                        start_target(SPECIAL_REBOOT_TARGET, false);
                else if (status.si_code == CLD_EXITED && (status.si_status & 6))
                        /* Some other problem */
                        start_target(SPECIAL_EMERGENCY_TARGET, true);
                else {
                        r = EXIT_SUCCESS;
                        log_warning("Ignoring error.");
                }

        } else
                r = EXIT_SUCCESS;

        if (status.si_code == CLD_EXITED && (status.si_status & 1))
                touch("/run/systemd/quotacheck");

finish:
        if (udev_device)
                udev_device_unref(udev_device);

        if (udev)
                udev_unref(udev);

        close_pipe(progress_pipe);

        return r;
}
コード例 #16
0
int switch_root(const char *new_root) {

    /*  Don't try to unmount/move the old "/", there's no way to do it. */
    static const char move_mounts[] =
        "/dev\0"
        "/proc\0"
        "/sys\0"
        "/run\0";

    int r, old_root_fd = -1;
    struct stat new_root_stat;
    bool old_root_remove;
    const char *i;
    _cleanup_free_ char *temporary_old_root = NULL;

    if (path_equal(new_root, "/"))
        return 0;

    /* When using pivot_root() we assume that /mnt exists as place
     * we can temporarily move the old root to. As we immediately
     * unmount it from there it doesn't matter much which
     * directory we choose for this, but it should be more likely
     * than not that /mnt exists and is suitable as mount point
     * and is on the same fs as the old root dir */
    temporary_old_root = strappend(new_root, "/mnt");
    if (!temporary_old_root)
        return -ENOMEM;

    old_root_remove = in_initrd();

    if (stat(new_root, &new_root_stat) < 0) {
        r = -errno;
        log_error("Failed to stat directory %s: %m", new_root);
        goto fail;
    }

    /* Work-around for a kernel bug: for some reason the kernel
     * refuses switching root if any file systems are mounted
     * MS_SHARED. Hence remount them MS_PRIVATE here as a
     * work-around.
     *
     * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
    if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
        log_warning("Failed to make \"/\" private mount: %m");

    NULSTR_FOREACH(i, move_mounts) {
        char new_mount[PATH_MAX];
        struct stat sb;

        snprintf(new_mount, sizeof(new_mount), "%s%s", new_root, i);
        char_array_0(new_mount);

        if ((stat(new_mount, &sb) < 0) ||
                sb.st_dev != new_root_stat.st_dev) {

            /* Mount point seems to be mounted already or
             * stat failed. Unmount the old mount
             * point. */
            if (umount2(i, MNT_DETACH) < 0)
                log_warning("Failed to unmount %s: %m", i);
            continue;
        }

        if (mount(i, new_mount, NULL, MS_MOVE, NULL) < 0) {
            log_error("Failed to move mount %s to %s, forcing unmount: %m", i, new_mount);

            if (umount2(i, MNT_FORCE) < 0)
                log_warning("Failed to unmount %s: %m", i);
        }
    }
コード例 #17
0
ファイル: automount.c プロジェクト: ariscop/systemd
static void automount_enter_waiting(Automount *a) {
        int p[2] = { -1, -1 };
        char name[32], options[128];
        bool mounted = false;
        int r, ioctl_fd = -1, dev_autofs_fd;
        struct stat st;

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

        if (a->tokens)
                set_clear(a->tokens);

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

        /* We knowingly ignore the results of this call */
        mkdir_p_label(a->where, 0555);

        warn_if_dir_nonempty(a->meta.id, a->where);

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

        snprintf(options, sizeof(options), "fd=%i,pgrp=%u,minproto=5,maxproto=5,direct", p[1], (unsigned) getpgrp());
        char_array_0(options);

        snprintf(name, sizeof(name), "systemd-%u", (unsigned) getpid());
        char_array_0(name);

        if (mount(name, a->where, "autofs", 0, options) < 0) {
                r = -errno;
                goto fail;
        }

        mounted = true;

        close_nointr_nofail(p[1]);
        p[1] = -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, 300);
        if (r < 0)
                goto fail;

        /* Autofs fun fact:
         *
         * Unless we close the ioctl fd here, for some weird reason
         * the direct mount will not receive events from the
         * kernel. */

        close_nointr_nofail(ioctl_fd);
        ioctl_fd = -1;

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

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

        automount_set_state(a, AUTOMOUNT_WAITING);

        return;

fail:
        assert_se(close_pipe(p) == 0);

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

        if (mounted)
                repeat_unmount(a->where);

        log_error_unit(UNIT(a)->id,
                       "Failed to initialize automounter: %s", strerror(-r));
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}
コード例 #18
0
ファイル: kmsg-syslogd.c プロジェクト: terralinux/systemd
static int write_message(Server *s, const char *buf, struct ucred *ucred) {
        ssize_t k;
        char priority[6], pid[16];
        struct iovec iovec[5];
        unsigned i = 0;
        char *process = NULL;
        int r = 0;
        int prio = LOG_USER | LOG_INFO;

        assert(s);
        assert(buf);

        parse_syslog_priority((char**) &buf, &prio);

        if (*buf == 0)
                return 0;

        if ((prio & LOG_FACMASK) == 0)
                prio = LOG_USER | LOG_PRI(prio);

        /* First, set priority field */
        snprintf(priority, sizeof(priority), "<%i>", prio);
        char_array_0(priority);
        IOVEC_SET_STRING(iovec[i++], priority);

        /* Second, skip date */
        skip_date(&buf);

        /* Then, add process if set */
        if (read_process(&buf, &iovec[i]) > 0)
                i++;
        else if (ucred &&
                 ucred->pid > 0 &&
                 get_process_name(ucred->pid, &process) >= 0)
                IOVEC_SET_STRING(iovec[i++], process);

        /* Skip the stored PID if we have a better one */
        if (ucred) {
                snprintf(pid, sizeof(pid), "[%lu]: ", (unsigned long) ucred->pid);
                char_array_0(pid);
                IOVEC_SET_STRING(iovec[i++], pid);

                skip_pid(&buf);

                if (*buf == ':')
                        buf++;

                buf += strspn(buf, WHITESPACE);
        }

        /* Is the remaining message empty? */
        if (*buf) {

                /* And the rest is the message */
                IOVEC_SET_STRING(iovec[i++], buf);
                IOVEC_SET_STRING(iovec[i++], "\n");

                if ((k = writev(s->kmsg_fd, iovec, i)) <= 0) {
                        log_error("Failed to write log message to kmsg: %s", k < 0 ? strerror(errno) : "short write");
                        r = k < 0 ? -errno : -EIO;
                }
        }

        free(process);

        return r;
}
コード例 #19
0
ファイル: switch-root.c プロジェクト: faizalpribadi/systemd
int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot,  unsigned long mountflags) {

        /*  Don't try to unmount/move the old "/", there's no way to do it. */
        static const char move_mounts[] =
                "/dev\0"
                "/proc\0"
                "/sys\0"
                "/run\0";

        _cleanup_close_ int old_root_fd = -1;
        struct stat new_root_stat;
        bool old_root_remove;
        const char *i, *temporary_old_root;

        if (path_equal(new_root, "/"))
                return 0;

        temporary_old_root = strappenda(new_root, oldroot);
        mkdir_p_label(temporary_old_root, 0755);

        old_root_remove = in_initrd();

        if (stat(new_root, &new_root_stat) < 0) {
                log_error("Failed to stat directory %s: %m", new_root);
                return -errno;
        }

        /* Work-around for kernel design: the kernel refuses switching
         * root if any file systems are mounted MS_SHARED. Hence
         * remount them MS_PRIVATE here as a work-around.
         *
         * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
        if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
                log_warning("Failed to make \"/\" private mount: %m");

        NULSTR_FOREACH(i, move_mounts) {
                char new_mount[PATH_MAX];
                struct stat sb;

                snprintf(new_mount, sizeof(new_mount), "%s%s", new_root, i);
                char_array_0(new_mount);

                mkdir_p_label(new_mount, 0755);

                if ((stat(new_mount, &sb) < 0) ||
                    sb.st_dev != new_root_stat.st_dev) {

                        /* Mount point seems to be mounted already or
                         * stat failed. Unmount the old mount
                         * point. */
                        if (umount2(i, MNT_DETACH) < 0)
                                log_warning("Failed to unmount %s: %m", i);
                        continue;
                }

                if (mount(i, new_mount, NULL, mountflags, NULL) < 0) {
                        if (mountflags & MS_MOVE) {
                                log_error("Failed to move mount %s to %s, forcing unmount: %m", i, new_mount);

                                if (umount2(i, MNT_FORCE) < 0)
                                        log_warning("Failed to unmount %s: %m", i);
                        }
                        if (mountflags & MS_BIND)
                                log_error("Failed to bind mount %s to %s: %m", i, new_mount);

                }
        }
コード例 #20
0
ファイル: timedatectl.c プロジェクト: felipec/udev-fc
static void print_status_info(StatusInfo *i) {
        usec_t n;
        char a[FORMAT_TIMESTAMP_MAX];
        char b[FORMAT_TIMESTAMP_MAX];
        char s[32];
        struct tm tm;
        time_t sec;
        char *zc, *zn;
        time_t t, tc, tn;
        int dn;
        bool is_dstc, is_dstn;
        int r;

        assert(i);

        /* enforce the values of /etc/localtime */
        if (getenv("TZ")) {
                fprintf(stderr, "Warning: ignoring the TZ variable, reading the system's timezone setting only.\n\n");
                unsetenv("TZ");
        }

        n = now(CLOCK_REALTIME);
        sec = (time_t) (n / USEC_PER_SEC);

        zero(tm);
        assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) > 0);
        char_array_0(a);
        printf("      Local time: %s\n", a);

        zero(tm);
        assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)) > 0);
        char_array_0(a);
        printf("  Universal time: %s\n", a);

        zero(tm);
        r = hwclock_get_time(&tm);
        if (r >= 0) {
                /* Calculcate the week-day */
                mktime(&tm);

                assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S", &tm) > 0);
                char_array_0(a);
                printf("        RTC time: %s\n", a);
        }

        zero(tm);
        assert_se(strftime(a, sizeof(a), "%z", localtime_r(&sec, &tm)) > 0);
        char_array_0(a);
        printf("        Timezone: %s\n"
               "      UTC offset: %s\n"
               "     NTP enabled: %s\n"
               "NTP synchronized: %s\n"
               " RTC in local TZ: %s\n",
               strna(i->timezone),
               a,
               yes_no(i->ntp),
               yes_no(ntp_synced()),
               yes_no(i->local_rtc));

        r = time_get_dst(sec, "/etc/localtime",
                         &tc, &zc, &is_dstc,
                         &tn, &dn, &zn, &is_dstn);
        if (r < 0)
                printf("      DST active: n/a\n");
        else {
                printf("      DST active: %s\n", yes_no(is_dstc));

                t = tc - 1;
                zero(tm);
                assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
                char_array_0(a);

                zero(tm);
                assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm)) > 0);
                char_array_0(b);
                printf(" Last DST change: %s → %s, DST became %s\n"
                       "                  %s\n"
                       "                  %s\n",
                       strna(zn), strna(zc), is_dstc ? "active" : "inactive", a, b);

                t = tn - 1;
                zero(tm);
                assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
                char_array_0(a);

                zero(tm);
                assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm)) > 0);
                char_array_0(b);
                printf(" Next DST change: %s → %s, DST will become %s\n"
                       "                  the clock will jump %s\n"
                       "                  %s\n"
                       "                  %s\n",
                       strna(zc), strna(zn), is_dstn ? "active" : "inactive", jump_str(dn, s, sizeof(s)), a, b);

                free(zc);
                free(zn);
        }

        if (i->local_rtc)
                fputs("\n" ANSI_HIGHLIGHT_ON
                      "Warning: The RTC is configured to maintain time in the local time zone. This\n"
                      "         mode is not fully supported and will create various problems with time\n"
                      "         zone changes and daylight saving adjustments. If at all possible use\n"
                      "         RTC in UTC, by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
}
コード例 #21
0
ファイル: fsck.c プロジェクト: pwaller/systemd
int main(int argc, char *argv[]) {
        const char *cmdline[9];
        int i = 0, r = EXIT_FAILURE, q;
        pid_t pid;
        siginfo_t status;
        _cleanup_udev_unref_ struct udev *udev = NULL;
        _cleanup_udev_device_unref_ struct udev_device *udev_device = NULL;
        const char *device, *type;
        bool root_directory;
        int progress_pipe[2] = { -1, -1 };
        char dash_c[2+10+1];
        struct stat st;

        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);

        q = parse_proc_cmdline(parse_proc_cmdline_item);
        if (q < 0)
                log_warning_errno(q, "Failed to parse kernel command line, ignoring: %m");

        test_files();

        if (!arg_force && arg_skip)
                return 0;

        udev = udev_new();
        if (!udev) {
                log_oom();
                return EXIT_FAILURE;
        }

        if (argc > 1) {
                device = argv[1];
                root_directory = false;

                if (stat(device, &st) < 0) {
                        log_error_errno(errno, "Failed to stat '%s': %m", device);
                        return EXIT_FAILURE;
                }

                udev_device = udev_device_new_from_devnum(udev, 'b', st.st_rdev);
                if (!udev_device) {
                        log_error("Failed to detect device %s", device);
                        return EXIT_FAILURE;
                }
        } else {
                struct timespec times[2];

                /* Find root device */

                if (stat("/", &st) < 0) {
                        log_error_errno(errno, "Failed to stat() the root directory: %m");
                        return EXIT_FAILURE;
                }

                /* Virtual root devices don't need an fsck */
                if (major(st.st_dev) == 0)
                        return EXIT_SUCCESS;

                /* check if we are already writable */
                times[0] = st.st_atim;
                times[1] = st.st_mtim;
                if (utimensat(AT_FDCWD, "/", times, 0) == 0) {
                        log_info("Root directory is writable, skipping check.");
                        return EXIT_SUCCESS;
                }

                udev_device = udev_device_new_from_devnum(udev, 'b', st.st_dev);
                if (!udev_device) {
                        log_error("Failed to detect root device.");
                        return EXIT_FAILURE;
                }

                device = udev_device_get_devnode(udev_device);
                if (!device) {
                        log_error("Failed to detect device node of root directory.");
                        return EXIT_FAILURE;
                }

                root_directory = true;
        }

        type = udev_device_get_property_value(udev_device, "ID_FS_TYPE");
        if (type) {
                r = fsck_exists(type);
                if (r == -ENOENT) {
                        log_info("fsck.%s doesn't exist, not checking file system on %s", type, device);
                        return EXIT_SUCCESS;
                } else if (r < 0)
                        log_warning_errno(r, "fsck.%s cannot be used for %s: %m", type, device);
        }

        if (arg_show_progress)
                if (pipe(progress_pipe) < 0) {
                        log_error_errno(errno, "pipe(): %m");
                        return EXIT_FAILURE;
                }

        cmdline[i++] = "/sbin/fsck";
        cmdline[i++] =  arg_repair;
        cmdline[i++] = "-T";

        /*
         * Since util-linux v2.25 fsck uses /run/fsck/<diskname>.lock files.
         * The previous versions use flock for the device and conflict with
         * udevd, see https://bugs.freedesktop.org/show_bug.cgi?id=79576#c5
         */
        cmdline[i++] = "-l";

        if (!root_directory)
                cmdline[i++] = "-M";

        if (arg_force)
                cmdline[i++] = "-f";

        if (progress_pipe[1] >= 0) {
                snprintf(dash_c, sizeof(dash_c), "-C%i", progress_pipe[1]);
                char_array_0(dash_c);
                cmdline[i++] = dash_c;
        }

        cmdline[i++] = device;
        cmdline[i++] = NULL;

        pid = fork();
        if (pid < 0) {
                log_error_errno(errno, "fork(): %m");
                goto finish;
        } else if (pid == 0) {
                /* Child */
                if (progress_pipe[0] >= 0)
                        safe_close(progress_pipe[0]);
                execv(cmdline[0], (char**) cmdline);
                _exit(8); /* Operational error */
        }

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

        if (progress_pipe[0] >= 0) {
                process_progress(progress_pipe[0]);
                progress_pipe[0] = -1;
        }

        q = wait_for_terminate(pid, &status);
        if (q < 0) {
                log_error_errno(q, "waitid(): %m");
                goto finish;
        }

        if (status.si_code != CLD_EXITED || (status.si_status & ~1)) {

                if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED)
                        log_error("fsck terminated by signal %s.", signal_to_string(status.si_status));
                else if (status.si_code == CLD_EXITED)
                        log_error("fsck failed with error code %i.", status.si_status);
                else
                        log_error("fsck failed due to unknown reason.");

                if (status.si_code == CLD_EXITED && (status.si_status & 2) && root_directory)
                        /* System should be rebooted. */
                        start_target(SPECIAL_REBOOT_TARGET);
                else if (status.si_code == CLD_EXITED && (status.si_status & 6))
                        /* Some other problem */
                        start_target(SPECIAL_EMERGENCY_TARGET);
                else {
                        r = EXIT_SUCCESS;
                        log_warning("Ignoring error.");
                }

        } else
                r = EXIT_SUCCESS;

        if (status.si_code == CLD_EXITED && (status.si_status & 1))
                touch("/run/systemd/quotacheck");

finish:
        safe_close_pair(progress_pipe);

        return r;
}
コード例 #22
0
ファイル: journald-console.c プロジェクト: vitalikp/journal
void server_forward_console(
                Server *s,
                int priority,
                const char *identifier,
                const char *message,
                struct ucred *ucred) {

        struct iovec iovec[5];
        char header_pid[16];
        struct timespec ts;
        char tbuf[4 + DECIMAL_STR_MAX(ts.tv_sec) + DECIMAL_STR_MAX(ts.tv_nsec)-3 + 1];
        int n = 0, fd;
        _cleanup_free_ char *ident_buf = NULL;
        const char *tty;

        assert(s);
        assert(message);

        if (LOG_PRI(priority) > s->max_level_console)
                return;

        /* First: timestamp */
        if (!clock_gettime(CLOCK_MONOTONIC, &ts)) {
                snprintf(tbuf, sizeof(tbuf), "[%5"PRI_TIME".%06ld] ",
                         ts.tv_sec,
                         ts.tv_nsec / 1000);
                IOVEC_SET_STRING(iovec[n++], tbuf);
        }

        /* Second: identifier and PID */
        if (ucred) {
                if (!identifier) {
                        get_process_comm(ucred->pid, &ident_buf);
                        identifier = ident_buf;
                }

                snprintf(header_pid, sizeof(header_pid), "["PID_FMT"]: ", ucred->pid);
                char_array_0(header_pid);

                if (identifier)
                        IOVEC_SET_STRING(iovec[n++], identifier);

                IOVEC_SET_STRING(iovec[n++], header_pid);
        } else if (identifier) {
                IOVEC_SET_STRING(iovec[n++], identifier);
                IOVEC_SET_STRING(iovec[n++], ": ");
        }

        /* Fourth: message */
        IOVEC_SET_STRING(iovec[n++], message);
        IOVEC_SET_STRING(iovec[n++], "\n");

        tty = s->tty_path ? s->tty_path : "/dev/console";

        fd = open_terminal(tty, O_WRONLY|O_NOCTTY|O_CLOEXEC);
        if (fd < 0) {
                log_debug("Failed to open %s for logging: %m", tty);
                return;
        }

        if (writev(fd, iovec, n) < 0)
                log_debug("Failed to write to %s for logging: %m", tty);

        safe_close(fd);
}