コード例 #1
0
int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) {
        const char *name, *devpath;
        int r;

        assert(dev);
        assert(dev_old);

        r = sd_device_get_devpath(dev, &devpath);
        if (r < 0)
                return log_device_debug_errno(dev, r, "Failed to get devpath: %m");

        /* update possible left-over symlinks */
        FOREACH_DEVICE_DEVLINK(dev_old, name) {
                const char *name_current;
                bool found = false;

                /* check if old link name still belongs to this device */
                FOREACH_DEVICE_DEVLINK(dev, name_current)
                        if (streq(name, name_current)) {
                                found = true;
                                break;
                        }

                if (found)
                        continue;

                log_device_debug(dev, "Updating old name, '%s' no longer belonging to '%s'",
                                 name, devpath);
                link_update(dev, name, false);
        }

        return 0;
}
コード例 #2
0
static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool test) {
        _cleanup_free_ char *driver = NULL;
        const char *name = NULL;
        link_config *link;
        int r;

        if (argc > 1)
                return log_device_error_errno(dev, EINVAL, "This program takes no arguments.");

        r = link_get_driver(ctx, dev, &driver);
        if (r >= 0)
                udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver);

        r = link_config_get(ctx, dev, &link);
        if (r < 0) {
                if (r == -ENOENT)
                        return log_device_debug_errno(dev, r, "No matching link configuration found.");

                return log_device_error_errno(dev, r, "Failed to get link config: %m");
        }

        r = link_config_apply(ctx, link, dev, &name);
        if (r < 0)
                log_device_warning_errno(dev, r, "Could not apply link config, ignoring: %m");

        udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->filename);

        if (name)
                udev_builtin_add_property(dev, test, "ID_NET_NAME", name);

        return 0;
}
コード例 #3
0
static int builtin_btrfs(sd_device *dev, int argc, char *argv[], bool test) {
        struct btrfs_ioctl_vol_args args = {};
        _cleanup_close_ int fd = -1;
        int r;

        if (argc != 3 || !streq(argv[1], "ready"))
                return log_device_error_errno(dev, EINVAL, "Invalid arguments");

        fd = open("/dev/btrfs-control", O_RDWR|O_CLOEXEC);
        if (fd < 0)
                return log_device_debug_errno(dev, errno, "Failed to open /dev/btrfs-control: %m");

        strscpy(args.name, sizeof(args.name), argv[2]);
        r = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args);
        if (r < 0)
                return log_device_debug_errno(dev, errno, "Failed to call BTRFS_IOC_DEVICES_READY: %m");

        udev_builtin_add_property(dev, test, "ID_BTRFS_READY", one_zero(r == 0));
        return 0;
}
コード例 #4
0
/* manage "stack of names" with possibly specified device priorities */
static int link_update(sd_device *dev, const char *slink, bool add) {
        _cleanup_free_ char *target = NULL, *filename = NULL, *dirname = NULL;
        char name_enc[PATH_MAX];
        const char *id_filename;
        int r;

        assert(dev);
        assert(slink);

        r = device_get_id_filename(dev, &id_filename);
        if (r < 0)
                return log_device_debug_errno(dev, r, "Failed to get id_filename: %m");

        util_path_encode(slink + STRLEN("/dev"), name_enc, sizeof(name_enc));
        dirname = path_join("/run/udev/links/", name_enc);
        if (!dirname)
                return log_oom();
        filename = path_join(dirname, id_filename);
        if (!filename)
                return log_oom();

        if (!add && unlink(filename) == 0)
                (void) rmdir(dirname);

        r = link_find_prioritized(dev, add, dirname, &target);
        if (r < 0) {
                log_device_debug(dev, "No reference left, removing '%s'", slink);
                if (unlink(slink) == 0)
                        (void) rmdir_parents(slink, "/");
        } else
                (void) node_symlink(dev, target, slink);

        if (add)
                do {
                        _cleanup_close_ int fd = -1;

                        r = mkdir_parents(filename, 0755);
                        if (!IN_SET(r, 0, -ENOENT))
                                break;
                        fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC|O_NOFOLLOW, 0444);
                        if (fd < 0)
                                r = -errno;
                } while (r == -ENOENT);

        return r;
}
コード例 #5
0
static int node_symlink(sd_device *dev, const char *node, const char *slink) {
        _cleanup_free_ char *slink_dirname = NULL, *target = NULL;
        const char *id_filename, *slink_tmp;
        struct stat stats;
        int r;

        assert(dev);
        assert(node);
        assert(slink);

        slink_dirname = dirname_malloc(slink);
        if (!slink_dirname)
                return log_oom();

        /* use relative link */
        r = path_make_relative(slink_dirname, node, &target);
        if (r < 0)
                return log_device_error_errno(dev, r, "Failed to get relative path from '%s' to '%s': %m", slink, node);

        /* preserve link with correct target, do not replace node of other device */
        if (lstat(slink, &stats) == 0) {
                if (S_ISBLK(stats.st_mode) || S_ISCHR(stats.st_mode)) {
                        log_device_error(dev, "Conflicting device node '%s' found, link to '%s' will not be created.", slink, node);
                        return -EOPNOTSUPP;
                } else if (S_ISLNK(stats.st_mode)) {
                        _cleanup_free_ char *buf = NULL;

                        if (readlink_malloc(slink, &buf) >= 0 &&
                            streq(target, buf)) {
                                log_device_debug(dev, "Preserve already existing symlink '%s' to '%s'", slink, target);
                                (void) label_fix(slink, LABEL_IGNORE_ENOENT);
                                (void) utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW);
                                return 0;
                        }
                }
        } else {
                log_device_debug(dev, "Creating symlink '%s' to '%s'", slink, target);
                do {
                        r = mkdir_parents_label(slink, 0755);
                        if (!IN_SET(r, 0, -ENOENT))
                                break;
                        mac_selinux_create_file_prepare(slink, S_IFLNK);
                        if (symlink(target, slink) < 0)
                                r = -errno;
                        mac_selinux_create_file_clear();
                } while (r == -ENOENT);
                if (r == 0)
                        return 0;
                if (r < 0)
                        log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s', trying to replace '%s': %m", slink, target, slink);
        }

        log_device_debug(dev, "Atomically replace '%s'", slink);
        r = device_get_id_filename(dev, &id_filename);
        if (r < 0)
                return log_device_error_errno(dev, r, "Failed to get id_filename: %m");
        slink_tmp = strjoina(slink, ".tmp-", id_filename);
        (void) unlink(slink_tmp);
        do {
                r = mkdir_parents_label(slink_tmp, 0755);
                if (!IN_SET(r, 0, -ENOENT))
                        break;
                mac_selinux_create_file_prepare(slink_tmp, S_IFLNK);
                if (symlink(target, slink_tmp) < 0)
                        r = -errno;
                mac_selinux_create_file_clear();
        } while (r == -ENOENT);
        if (r < 0)
                return log_device_error_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink_tmp, target);

        if (rename(slink_tmp, slink) < 0) {
                r = log_device_error_errno(dev, errno, "Failed to rename '%s' to '%s' failed: %m", slink_tmp, slink);
                (void) unlink(slink_tmp);
        }

        return r;
}
コード例 #6
0
static int node_permissions_apply(sd_device *dev, bool apply,
                                  mode_t mode, uid_t uid, gid_t gid,
                                  Hashmap *seclabel_list) {
        const char *devnode, *subsystem, *id_filename = NULL;
        struct stat stats;
        dev_t devnum;
        int r = 0;

        assert(dev);

        r = sd_device_get_devname(dev, &devnode);
        if (r < 0)
                return log_device_debug_errno(dev, r, "Failed to get devname: %m");
        r = sd_device_get_subsystem(dev, &subsystem);
        if (r < 0)
                return log_device_debug_errno(dev, r, "Failed to get subsystem: %m");
        r = sd_device_get_devnum(dev, &devnum);
        if (r < 0)
                return log_device_debug_errno(dev, r, "Failed to get devnum: %m");
        (void) device_get_id_filename(dev, &id_filename);

        if (streq(subsystem, "block"))
                mode |= S_IFBLK;
        else
                mode |= S_IFCHR;

        if (lstat(devnode, &stats) < 0)
                return log_device_debug_errno(dev, errno, "cannot stat() node '%s' (%m)", devnode);

        if (((stats.st_mode & S_IFMT) != (mode & S_IFMT)) || (stats.st_rdev != devnum))
                return log_device_debug_errno(dev, EEXIST, "Found node '%s' with non-matching devnum %s, skip handling",
                                              devnode, id_filename);

        if (apply) {
                bool selinux = false, smack = false;
                const char *name, *label;
                Iterator i;

                if ((stats.st_mode & 0777) != (mode & 0777) || stats.st_uid != uid || stats.st_gid != gid) {
                        log_device_debug(dev, "Setting permissions %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid);
                        if (chmod(devnode, mode) < 0)
                                r = log_device_warning_errno(dev, errno, "Failed to set mode of %s to %#o: %m", devnode, mode);
                        if (chown(devnode, uid, gid) < 0)
                                r = log_device_warning_errno(dev, errno, "Failed to set owner of %s to uid=%u, gid=%u: %m", devnode, uid, gid);
                } else
                        log_device_debug(dev, "Preserve permissions of %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid);

                /* apply SECLABEL{$module}=$label */
                HASHMAP_FOREACH_KEY(label, name, seclabel_list, i) {
                        int q;

                        if (streq(name, "selinux")) {
                                selinux = true;

                                q = mac_selinux_apply(devnode, label);
                                if (q < 0)
                                        log_device_error_errno(dev, q, "SECLABEL: failed to set SELinux label '%s': %m", label);
                                else
                                        log_device_debug(dev, "SECLABEL: set SELinux label '%s'", label);

                        } else if (streq(name, "smack")) {
                                smack = true;

                                q = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label);
                                if (q < 0)
                                        log_device_error_errno(dev, q, "SECLABEL: failed to set SMACK label '%s': %m", label);
                                else
                                        log_device_debug(dev, "SECLABEL: set SMACK label '%s'", label);

                        } else
                                log_device_error(dev, "SECLABEL: unknown subsystem, ignoring '%s'='%s'", name, label);
                }

                /* set the defaults */
                if (!selinux)
                        (void) mac_selinux_fix(devnode, LABEL_IGNORE_ENOENT);
                if (!smack)
                        (void) mac_smack_apply(devnode, SMACK_ATTR_ACCESS, NULL);
        }
コード例 #7
0
ファイル: device-private.c プロジェクト: dvdhrm/systemd
static int device_amend(sd_device *device, const char *key, const char *value) {
        int r;

        assert(device);
        assert(key);
        assert(value);

        if (streq(key, "DEVPATH")) {
                char *path;

                path = strjoina("/sys", value);

                /* the caller must verify or trust this data (e.g., if it comes from the kernel) */
                r = device_set_syspath(device, path, false);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set syspath to '%s': %m", path);
        } else if (streq(key, "SUBSYSTEM")) {
                r = device_set_subsystem(device, value);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem to '%s': %m", value);
        } else if (streq(key, "DEVTYPE")) {
                r = device_set_devtype(device, value);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set devtype to '%s': %m", value);
        } else if (streq(key, "DEVNAME")) {
                r = device_set_devname(device, value);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set devname to '%s': %m", value);
        } else if (streq(key, "USEC_INITIALIZED")) {
                usec_t t;

                r = safe_atou64(value, &t);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to parse timestamp '%s': %m", value);

                r = device_set_usec_initialized(device, t);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set usec-initialized to '%s': %m", value);
        } else if (streq(key, "DRIVER")) {
                r = device_set_driver(device, value);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set driver to '%s': %m", value);
        } else if (streq(key, "IFINDEX")) {
                r = device_set_ifindex(device, value);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set ifindex to '%s': %m", value);
        } else if (streq(key, "DEVMODE")) {
                r = device_set_devmode(device, value);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set devmode to '%s': %m", value);
        } else if (streq(key, "DEVUID")) {
                r = device_set_devuid(device, value);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set devuid to '%s': %m", value);
        } else if (streq(key, "DEVGID")) {
                r = device_set_devgid(device, value);
                if (r < 0)
                        return log_device_debug_errno(device, r, "sd-device: Failed to set devgid to '%s': %m", value);
        } else if (streq(key, "DEVLINKS")) {
                const char *word, *state;
                size_t l;

                FOREACH_WORD(word, l, value, state) {
                        char devlink[l + 1];

                        strncpy(devlink, word, l);
                        devlink[l] = '\0';

                        r = device_add_devlink(device, devlink);
                        if (r < 0)
                                return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", devlink);
                }
        } else if (streq(key, "TAGS")) {