Exemple #1
0
char *resolve_dev_console(char **active) {
        char *tty;

        /* Resolve where /dev/console is pointing to, if /sys is actually ours
         * (i.e. not read-only-mounted which is a sign for container setups) */

        if (path_is_read_only_fs("/sys") > 0)
                return NULL;

        if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
                return NULL;

        /* If multiple log outputs are configured the last one is what
         * /dev/console points to */
        tty = strrchr(*active, ' ');
        if (tty)
                tty++;
        else
                tty = *active;

        if (streq(tty, "tty0")) {
                char *tmp;

                /* Get the active VC (e.g. tty1) */
                if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
                        free(*active);
                        tty = *active = tmp;
                }
        }

        return tty;
}
Exemple #2
0
static int condition_test_path_is_read_write(Condition *c) {
        assert(c);
        assert(c->parameter);
        assert(c->type == CONDITION_PATH_IS_READ_WRITE);

        return path_is_read_only_fs(c->parameter) <= 0;
}
Exemple #3
0
static int condition_test_needs_update(Condition *c) {
        const char *p;
        struct stat usr, other;

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

        /* If the file system is read-only we shouldn't suggest an update */
        if (path_is_read_only_fs(c->parameter) > 0)
                return false;

        /* Any other failure means we should allow the condition to be true,
         * so that we rather invoke too many update tools then too
         * few. */

        if (!path_is_absolute(c->parameter))
                return true;

        p = strjoina(c->parameter, "/.updated");
        if (lstat(p, &other) < 0)
                return true;

        if (lstat("/usr/", &usr) < 0)
                return true;

        return usr.st_mtim.tv_sec > other.st_mtim.tv_sec ||
                (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec);
}
static int parse_fstab(bool initrd) {
        _cleanup_endmntent_ FILE *f = NULL;
        const char *fstab_path;
        struct mntent *me;
        int r = 0;

        fstab_path = initrd ? "/sysroot/etc/fstab" : "/etc/fstab";
        f = setmntent(fstab_path, "re");
        if (!f) {
                if (errno == ENOENT)
                        return 0;

                log_error_errno(errno, "Failed to open %s: %m", fstab_path);
                return -errno;
        }

        while ((me = getmntent(f))) {
                _cleanup_free_ char *where = NULL, *what = NULL;
                bool noauto, nofail;
                int k;

                if (initrd && !mount_in_initrd(me))
                        continue;

                what = fstab_node_to_udev_node(me->mnt_fsname);
                if (!what)
                        return log_oom();

                if (is_device_path(what) && path_is_read_only_fs("sys") > 0) {
                        log_info("Running in a container, ignoring fstab device entry for %s.", what);
                        continue;
                }

                where = initrd ? strappend("/sysroot/", me->mnt_dir) : strdup(me->mnt_dir);
                if (!where)
                        return log_oom();

                if (is_path(where))
                        path_kill_slashes(where);

                noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
                nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
                log_debug("Found entry what=%s where=%s type=%s nofail=%s noauto=%s",
                          what, where, me->mnt_type,
                          yes_no(noauto), yes_no(nofail));

                if (streq(me->mnt_type, "swap"))
                        k = add_swap(what, me, noauto, nofail);
                else {
                        bool automount;
                        const char *post;

                        automount = fstab_test_option(me->mnt_opts,
                                                      "comment=systemd.automount\0"
                                                      "x-systemd.automount\0");
                        if (initrd)
                                post = SPECIAL_INITRD_FS_TARGET;
                        else if (mount_in_initrd(me))
                                post = SPECIAL_INITRD_ROOT_FS_TARGET;
                        else if (mount_is_network(me))
                                post = SPECIAL_REMOTE_FS_TARGET;
                        else
                                post = SPECIAL_LOCAL_FS_TARGET;

                        k = add_mount(what,
                                      where,
                                      me->mnt_type,
                                      me->mnt_opts,
                                      me->mnt_passno,
                                      noauto,
                                      nofail,
                                      automount,
                                      post,
                                      fstab_path);
                }

                if (k < 0)
                        r = k;
        }

        return r;
}
static int condition_test_needs_update(Condition *c) {
        const char *p;
        struct stat usr, other;

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

        /* If the file system is read-only we shouldn't suggest an update */
        if (path_is_read_only_fs(c->parameter) > 0)
                return false;

        /* Any other failure means we should allow the condition to be true,
         * so that we rather invoke too many update tools than too
         * few. */

        if (!path_is_absolute(c->parameter))
                return true;

        p = strjoina(c->parameter, "/.updated");
        if (lstat(p, &other) < 0)
                return true;

        if (lstat("/usr/", &usr) < 0)
                return true;

        /*
         * First, compare seconds as they are always accurate...
         */
        if (usr.st_mtim.tv_sec != other.st_mtim.tv_sec)
                return usr.st_mtim.tv_sec > other.st_mtim.tv_sec;

        /*
         * ...then compare nanoseconds.
         *
         * A false positive is only possible when /usr's nanoseconds > 0
         * (otherwise /usr cannot be strictly newer than the target file)
         * AND the target file's nanoseconds == 0
         * (otherwise the filesystem supports nsec timestamps, see stat(2)).
         */
        if (usr.st_mtim.tv_nsec > 0 && other.st_mtim.tv_nsec == 0) {
                _cleanup_free_ char *timestamp_str = NULL;
                uint64_t timestamp;
                int r;

                r = parse_env_file(p, NULL, "TIMESTAMP_NSEC", &timestamp_str, NULL);
                if (r < 0) {
                        log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p);
                        return true;
                } else if (r == 0) {
                        log_debug("No data in timestamp file '%s', using mtime", p);
                        return true;
                }

                r = safe_atou64(timestamp_str, &timestamp);
                if (r < 0) {
                        log_error_errno(r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", timestamp_str, p);
                        return true;
                }

                timespec_store(&other.st_mtim, timestamp);
        }

        return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec;
}
Exemple #6
0
static bool condition_test(Condition *c) {
        assert(c);

        switch(c->type) {

        case CONDITION_PATH_EXISTS:
                return (access(c->parameter, F_OK) >= 0) == !c->negate;

        case CONDITION_PATH_EXISTS_GLOB:
                return (glob_exists(c->parameter) > 0) == !c->negate;

        case CONDITION_PATH_IS_DIRECTORY: {
                struct stat st;

                if (stat(c->parameter, &st) < 0)
                        return c->negate;
                return S_ISDIR(st.st_mode) == !c->negate;
        }

        case CONDITION_PATH_IS_SYMBOLIC_LINK: {
                struct stat st;

                if (lstat(c->parameter, &st) < 0)
                        return c->negate;
                return S_ISLNK(st.st_mode) == !c->negate;
        }

        case CONDITION_PATH_IS_MOUNT_POINT:
                return (path_is_mount_point(c->parameter, true) > 0) == !c->negate;

        case CONDITION_PATH_IS_READ_WRITE:
                return (path_is_read_only_fs(c->parameter) > 0) == c->negate;

        case CONDITION_DIRECTORY_NOT_EMPTY: {
                int k;

                k = dir_is_empty(c->parameter);
                return !(k == -ENOENT || k > 0) == !c->negate;
        }

        case CONDITION_FILE_NOT_EMPTY: {
                struct stat st;

                if (stat(c->parameter, &st) < 0)
                        return c->negate;

                return (S_ISREG(st.st_mode) && st.st_size > 0) == !c->negate;
        }

        case CONDITION_FILE_IS_EXECUTABLE: {
                struct stat st;

                if (stat(c->parameter, &st) < 0)
                        return c->negate;

                return (S_ISREG(st.st_mode) && (st.st_mode & 0111)) == !c->negate;
        }

        case CONDITION_KERNEL_COMMAND_LINE:
                return condition_test_kernel_command_line(c);

        case CONDITION_VIRTUALIZATION:
                return condition_test_virtualization(c);

        case CONDITION_SECURITY:
                return condition_test_security(c);

        case CONDITION_CAPABILITY:
                return condition_test_capability(c);

        case CONDITION_HOST:
                return condition_test_host(c);

        case CONDITION_AC_POWER:
                return condition_test_ac_power(c);

        case CONDITION_ARCHITECTURE:
                return condition_test_architecture(c);

        case CONDITION_NEEDS_UPDATE:
                return condition_test_needs_update(c);

        case CONDITION_FIRST_BOOT:
                return condition_test_first_boot(c);

        case CONDITION_NULL:
                return !c->negate;

        default:
                assert_not_reached("Invalid condition type.");
        }
}