Exemplo n.º 1
0
static int recursive_relabel(Item *i, const char *path) {
        int r;
        struct stat st;

        r = item_set_perms(i, path);
        if (r < 0)
                return r;

        if (lstat(path, &st) < 0)
                return -errno;

        if (S_ISDIR(st.st_mode))
                r = recursive_relabel_children(i, path);

        return r;
}
Exemplo n.º 2
0
static int create_item(Item *i) {
        int r, e;
        mode_t u;
        struct stat st;

        assert(i);

        switch (i->type) {

        case IGNORE_PATH:
        case REMOVE_PATH:
        case RECURSIVE_REMOVE_PATH:
                return 0;

        case CREATE_FILE:
        case TRUNCATE_FILE:
        case WRITE_FILE: {
                int fd, flags;

                flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
                        i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;

                u = umask(0);
                label_context_set(i->path, S_IFREG);
                fd = open(i->path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
                e = errno;
                label_context_clear();
                umask(u);
                errno = e;

                if (fd < 0) {
                        if (i->type == WRITE_FILE && errno == ENOENT)
                                break;

                        log_error("Failed to create file %s: %m", i->path);
                        return -errno;
                }

                if (i->argument) {
                        ssize_t n;
                        size_t l;
                        struct iovec iovec[2];
                        static const char new_line = '\n';

                        l = strlen(i->argument);

                        zero(iovec);
                        iovec[0].iov_base = i->argument;
                        iovec[0].iov_len = l;

                        iovec[1].iov_base = (void*) &new_line;
                        iovec[1].iov_len = 1;

                        n = writev(fd, iovec, 2);

                        /* It's OK if we don't write the trailing
                         * newline, hence we check for l, instead of
                         * l+1 here. Files in /sys often refuse
                         * writing of the trailing newline. */
                        if (n < 0 || (size_t) n < l) {
                                log_error("Failed to write file %s: %s", i->path, n < 0 ? strerror(-n) : "Short write");
                                close_nointr_nofail(fd);
                                return n < 0 ? n : -EIO;
                        }
                }

                close_nointr_nofail(fd);

                if (stat(i->path, &st) < 0) {
                        log_error("stat(%s) failed: %m", i->path);
                        return -errno;
                }

                if (!S_ISREG(st.st_mode)) {
                        log_error("%s is not a file.", i->path);
                        return -EEXIST;
                }

                r = item_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;
        }

        case TRUNCATE_DIRECTORY:
        case CREATE_DIRECTORY:

                u = umask(0);
                mkdir_parents_label(i->path, 0755);
                r = mkdir(i->path, i->mode);
                umask(u);

                if (r < 0 && errno != EEXIST) {
                        log_error("Failed to create directory %s: %m", i->path);
                        return -errno;
                }

                if (stat(i->path, &st) < 0) {
                        log_error("stat(%s) failed: %m", i->path);
                        return -errno;
                }

                if (!S_ISDIR(st.st_mode)) {
                        log_error("%s is not a directory.", i->path);
                        return -EEXIST;
                }

                r = item_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;

        case CREATE_FIFO:

                u = umask(0);
                r = mkfifo(i->path, i->mode);
                umask(u);

                if (r < 0 && errno != EEXIST) {
                        log_error("Failed to create fifo %s: %m", i->path);
                        return -errno;
                }

                if (stat(i->path, &st) < 0) {
                        log_error("stat(%s) failed: %m", i->path);
                        return -errno;
                }

                if (!S_ISFIFO(st.st_mode)) {
                        log_error("%s is not a fifo.", i->path);
                        return -EEXIST;
                }

                r = item_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;

        case CREATE_SYMLINK: {
                char *x;

                label_context_set(i->path, S_IFLNK);
                r = symlink(i->argument, i->path);
                e = errno;
                label_context_clear();
                errno = e;

                if (r < 0 && errno != EEXIST) {
                        log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
                        return -errno;
                }

                r = readlink_malloc(i->path, &x);
                if (r < 0) {
                        log_error("readlink(%s) failed: %s", i->path, strerror(-r));
                        return -errno;
                }

                if (!streq(i->argument, x)) {
                        free(x);
                        log_error("%s is not the right symlinks.", i->path);
                        return -EEXIST;
                }

                free(x);
                break;
        }

        case CREATE_BLOCK_DEVICE:
        case CREATE_CHAR_DEVICE: {
                mode_t file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);

                u = umask(0);
                label_context_set(i->path, file_type);
                r = mknod(i->path, i->mode | file_type, i->major_minor);
                e = errno;
                label_context_clear();
                umask(u);
                errno = e;

                if (r < 0 && errno != EEXIST) {
                        log_error("Failed to create device node %s: %m", i->path);
                        return -errno;
                }

                if (stat(i->path, &st) < 0) {
                        log_error("stat(%s) failed: %m", i->path);
                        return -errno;
                }

                if ((st.st_mode & S_IFMT) != file_type) {
                        log_error("%s is not a device node.", i->path);
                        return -EEXIST;
                }

                r = item_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;
        }

        case RELABEL_PATH:

                r = glob_item(i, item_set_perms);
                if (r < 0)
                        return 0;
                break;

        case RECURSIVE_RELABEL_PATH:

                r = glob_item(i, recursive_relabel);
                if (r < 0)
                        return r;
        }

        log_debug("%s created successfully.", i->path);

        return 0;
}
Exemplo n.º 3
0
static int create_item(Item *i) {
        int r, e;
        mode_t u;
        struct stat st;

        assert(i);

        switch (i->type) {

        case IGNORE_PATH:
        case IGNORE_DIRECTORY_PATH:
        case REMOVE_PATH:
        case RECURSIVE_REMOVE_PATH:
                return 0;

        case CREATE_FILE:
        case TRUNCATE_FILE:
                r = write_one_file(i, i->path);
                if (r < 0)
                        return r;
                break;
        case WRITE_FILE:
                r = glob_item(i, write_one_file);
                if (r < 0)
                        return r;

                break;

        case TRUNCATE_DIRECTORY:
        case CREATE_DIRECTORY:

                u = umask(0);
                mkdir_parents_label(i->path, 0755);
                r = mkdir(i->path, i->mode);
                umask(u);

                if (r < 0 && errno != EEXIST) {
                        log_error("Failed to create directory %s: %m", i->path);
                        return -errno;
                }

                if (stat(i->path, &st) < 0) {
                        log_error("stat(%s) failed: %m", i->path);
                        return -errno;
                }

                if (!S_ISDIR(st.st_mode)) {
                        log_error("%s is not a directory.", i->path);
                        return -EEXIST;
                }

                r = item_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;

        case CREATE_FIFO:

                u = umask(0);
                r = mkfifo(i->path, i->mode);
                umask(u);

                if (r < 0 && errno != EEXIST) {
                        log_error("Failed to create fifo %s: %m", i->path);
                        return -errno;
                }

                if (stat(i->path, &st) < 0) {
                        log_error("stat(%s) failed: %m", i->path);
                        return -errno;
                }

                if (!S_ISFIFO(st.st_mode)) {
                        log_error("%s is not a fifo.", i->path);
                        return -EEXIST;
                }

                r = item_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;

        case CREATE_SYMLINK: {
                char *x;

                label_context_set(i->path, S_IFLNK);
                r = symlink(i->argument, i->path);
                e = errno;
                label_context_clear();
                errno = e;

                if (r < 0 && errno != EEXIST) {
                        log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
                        return -errno;
                }

                r = readlink_malloc(i->path, &x);
                if (r < 0) {
                        log_error("readlink(%s) failed: %s", i->path, strerror(-r));
                        return -errno;
                }

                if (!streq(i->argument, x)) {
                        free(x);
                        log_error("%s is not the right symlinks.", i->path);
                        return -EEXIST;
                }

                free(x);
                break;
        }

        case CREATE_BLOCK_DEVICE:
        case CREATE_CHAR_DEVICE: {
                mode_t file_type;

                if (have_effective_cap(CAP_MKNOD) == 0) {
                        /* In a container we lack CAP_MKNOD. We
                        shouldnt attempt to create the device node in
                        that case to avoid noise, and we don't support
                        virtualized devices in containers anyway. */

                        log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
                        return 0;
                }

                file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);

                u = umask(0);
                label_context_set(i->path, file_type);
                r = mknod(i->path, i->mode | file_type, i->major_minor);
                e = errno;
                label_context_clear();
                umask(u);
                errno = e;

                if (r < 0 && errno != EEXIST) {
                        log_error("Failed to create device node %s: %m", i->path);
                        return -errno;
                }

                if (stat(i->path, &st) < 0) {
                        log_error("stat(%s) failed: %m", i->path);
                        return -errno;
                }

                if ((st.st_mode & S_IFMT) != file_type) {
                        log_error("%s is not a device node.", i->path);
                        return -EEXIST;
                }

                r = item_set_perms(i, i->path);
                if (r < 0)
                        return r;

                break;
        }

        case RELABEL_PATH:

                r = glob_item(i, item_set_perms);
                if (r < 0)
                        return 0;
                break;

        case RECURSIVE_RELABEL_PATH:

                r = glob_item(i, recursive_relabel);
                if (r < 0)
                        return r;
        }

        log_debug("%s created successfully.", i->path);

        return 0;
}
Exemplo n.º 4
0
static int recursive_relabel_children(Item *i, const char *path) {
        DIR *d;
        int ret = 0;

        /* This returns the first error we run into, but nevertheless
         * tries to go on */

        d = opendir(path);
        if (!d)
                return errno == ENOENT ? 0 : -errno;

        for (;;) {
                struct dirent buf, *de;
                bool is_dir;
                int r;
                char *entry_path;

                r = readdir_r(d, &buf, &de);
                if (r != 0) {
                        if (ret == 0)
                                ret = -r;
                        break;
                }

                if (!de)
                        break;

                if (streq(de->d_name, ".") || streq(de->d_name, ".."))
                        continue;

                if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
                        if (ret == 0)
                                ret = -ENOMEM;
                        continue;
                }

                if (de->d_type == DT_UNKNOWN) {
                        struct stat st;

                        if (lstat(entry_path, &st) < 0) {
                                if (ret == 0 && errno != ENOENT)
                                        ret = -errno;
                                free(entry_path);
                                continue;
                        }

                        is_dir = S_ISDIR(st.st_mode);

                } else
                        is_dir = de->d_type == DT_DIR;

                r = item_set_perms(i, entry_path);
                if (r < 0) {
                        if (ret == 0 && r != -ENOENT)
                                ret = r;
                        free(entry_path);
                        continue;
                }

                if (is_dir) {
                        r = recursive_relabel_children(i, entry_path);
                        if (r < 0 && ret == 0)
                                ret = r;
                }

                free(entry_path);
        }

        closedir(d);

        return ret;
}
Exemplo n.º 5
0
static int write_one_file(Item *i, const char *path) {
        int r, e, fd, flags;
        struct stat st;
        mode_t u;

        flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
                i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;

        u = umask(0);
        label_context_set(path, S_IFREG);
        fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
        e = errno;
        label_context_clear();
        umask(u);
        errno = e;

        if (fd < 0) {
                if (i->type == WRITE_FILE && errno == ENOENT)
                        return 0;

                log_error("Failed to create file %s: %m", path);
                return -errno;
        }

        if (i->argument) {
                ssize_t n;
                size_t l;
                _cleanup_free_ char *unescaped;

                unescaped = cunescape(i->argument);
                if (unescaped == NULL) {
                        close_nointr_nofail(fd);
                        return log_oom();
                }

                l = strlen(unescaped);
                n = write(fd, unescaped, l);

                if (n < 0 || (size_t) n < l) {
                        log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
                        close_nointr_nofail(fd);
                        return n < 0 ? n : -EIO;
                }
        }

        close_nointr_nofail(fd);

        if (stat(path, &st) < 0) {
                log_error("stat(%s) failed: %m", path);
                return -errno;
        }

        if (!S_ISREG(st.st_mode)) {
                log_error("%s is not a file.", path);
                return -EEXIST;
        }

        r = item_set_perms(i, path);
        if (r < 0)
                return r;

        return 0;
}