]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev-watch: replace udev_device by sd_device and modernize code a bit
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 14 Sep 2018 19:13:29 +0000 (04:13 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 10 Oct 2018 19:21:14 +0000 (04:21 +0900)
src/udev/meson.build
src/udev/udev-event.c
src/udev/udev-watch.c
src/udev/udev-watch.h [new file with mode: 0644]
src/udev/udev.h
src/udev/udevd.c

index 665cb83fb8c3c79063d85f6105eb66adbcaf6af4..96df2d3877d7a5c81c1d25f210b59edcb7db2e75 100644 (file)
@@ -19,11 +19,12 @@ systemd_udevd_sources = files('udevd.c')
 
 libudev_core_sources = '''
         udev.h
+        udev-ctrl.c
         udev-event.c
-        udev-watch.c
         udev-node.c
         udev-rules.c
-        udev-ctrl.c
+        udev-watch.c
+        udev-watch.h
         udev-builtin.c
         udev-builtin-btrfs.c
         udev-builtin-hwdb.c
index dc3a398c8d472f4d4b5bee6a6b760ed8f37f9de9..5b28e467980178c0b5ce6e5030a25c1305b3abd9 100644 (file)
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "format-util.h"
+#include "libudev-device-internal.h"
 #include "netlink-util.h"
 #include "path-util.h"
 #include "process-util.h"
 #include "signal-util.h"
 #include "string-util.h"
+#include "udev-watch.h"
 #include "udev.h"
 
 typedef struct Spawn {
@@ -799,7 +801,7 @@ void udev_event_execute_rules(struct udev_event *event,
                 udev_device_delete_db(dev);
 
                 if (major(udev_device_get_devnum(dev)) != 0)
-                        udev_watch_end(dev);
+                        udev_watch_end(dev->device);
 
                 udev_rules_apply_to_event(rules, event,
                                           timeout_usec, timeout_warn_usec,
@@ -812,7 +814,7 @@ void udev_event_execute_rules(struct udev_event *event,
                 if (event->dev_db != NULL) {
                         /* disable watch during event processing */
                         if (major(udev_device_get_devnum(dev)) != 0)
-                                udev_watch_end(event->dev_db);
+                                udev_watch_end(event->dev_db->device);
 
                         if (major(udev_device_get_devnum(dev)) == 0 &&
                             streq(udev_device_get_action(dev), "move"))
index 439117181a75aa506c32bdf45d6c5d2b7d033d16..d3e4391ee9acdd778dde5d422542d05b3cb814e7 100644 (file)
  * Copyright © 2009 Scott James Remnant <scott@netsplit.com>
  */
 
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
 #include <sys/inotify.h>
 #include <unistd.h>
 
+#include "device-private.h"
 #include "dirent-util.h"
+#include "mkdir.h"
 #include "stdio-util.h"
-#include "udev.h"
+#include "udev-watch.h"
 
 static int inotify_fd = -1;
 
 /* inotify descriptor, will be shared with rules directory;
  * set to cloexec since we need our children to be able to add
- * watches for us
- */
+ * watches for us. */
 int udev_watch_init(void) {
         inotify_fd = inotify_init1(IN_CLOEXEC);
         if (inotify_fd < 0)
-                log_error_errno(errno, "inotify_init failed: %m");
+                return log_error_errno(errno, "Failed to create inotify descriptor: %m");
+
         return inotify_fd;
 }
 
-/* move any old watches directory out of the way, and then restore
- * the watches
- */
-void udev_watch_restore(void) {
-        if (inotify_fd < 0)
-                return;
+/* Move any old watches directory out of the way, and then restore the watches. */
+int udev_watch_restore(void) {
+        struct dirent *ent;
+        DIR *dir;
+        int r;
 
-        if (rename("/run/udev/watch", "/run/udev/watch.old") == 0) {
-                DIR *dir;
-                struct dirent *ent;
+        if (inotify_fd < 0)
+                return log_error_errno(EINVAL, "Invalid inotify descriptor.");
 
-                dir = opendir("/run/udev/watch.old");
-                if (dir == NULL) {
-                        log_error_errno(errno, "unable to open old watches dir /run/udev/watch.old; old watches will not be restored: %m");
-                        return;
-                }
+        if (rename("/run/udev/watch", "/run/udev/watch.old") < 0) {
+                if (errno != ENOENT)
+                        return log_error_errno(errno, "Failed to move watches directory /run/udev/watch. Old watches will not be restored: %m");
 
-                FOREACH_DIRENT_ALL(ent, dir, break) {
-                        char device[UTIL_PATH_SIZE];
-                        ssize_t len;
-                        struct udev_device *dev;
+                return 0;
+        }
 
-                        if (ent->d_name[0] == '.')
-                                continue;
+        dir = opendir("/run/udev/watch.old");
+        if (!dir)
+                return log_error_errno(errno, "Failed to open old watches directory /run/udev/watch.old. Old watches will not be restored: %m");
+
+        FOREACH_DIRENT_ALL(ent, dir, break) {
+                _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+                char device[PATH_MAX];
+                ssize_t len;
+
+                if (ent->d_name[0] == '.')
+                        continue;
+
+                len = readlinkat(dirfd(dir), ent->d_name, device, sizeof(device));
+                if (len <= 0) {
+                        log_error_errno(errno, "Failed to read link '/run/udev/watch.old/%s', ignoring: %m", ent->d_name);
+                        goto unlink;
+                } else if (len >= (ssize_t) sizeof(device)) {
+                        log_error("Path specified by link '/run/udev/watch.old/%s' is truncated, ignoring.", ent->d_name);
+                        goto unlink;
+                }
+                device[len] = '\0';
 
-                        len = readlinkat(dirfd(dir), ent->d_name, device, sizeof(device));
-                        if (len <= 0 || len == (ssize_t)sizeof(device))
-                                goto unlink;
-                        device[len] = '\0';
+                r = sd_device_new_from_device_id(&dev, device);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to create sd_device object for '%s', ignoring: %m", device);
+                        goto unlink;
+                }
 
-                        dev = udev_device_new_from_device_id(NULL, device);
-                        if (dev == NULL)
-                                goto unlink;
+                if (DEBUG_LOGGING) {
+                        const char *devnode = NULL;
 
-                        log_debug("restoring old watch on '%s'", udev_device_get_devnode(dev));
-                        udev_watch_begin(dev);
-                        udev_device_unref(dev);
-unlink:
-                        (void) unlinkat(dirfd(dir), ent->d_name, 0);
+                        (void) sd_device_get_devname(dev, &devnode);
+                        log_debug("Restoring old watch on '%s'", strnull(devnode));
                 }
+                (void) udev_watch_begin(dev);
+unlink:
+                (void) unlinkat(dirfd(dir), ent->d_name, 0);
+        }
 
-                closedir(dir);
-                rmdir("/run/udev/watch.old");
+        (void) closedir(dir);
+        (void) rmdir("/run/udev/watch.old");
 
-        } else if (errno != ENOENT)
-                log_error_errno(errno, "unable to move watches dir /run/udev/watch; old watches will not be restored: %m");
+        return 0;
 }
 
-void udev_watch_begin(struct udev_device *dev) {
-        char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
-        int wd;
-        int r;
+int udev_watch_begin(sd_device *dev) {
+        char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
+        const char *devnode, *id_filename;
+        int wd, r;
 
         if (inotify_fd < 0)
-                return;
-
-        log_debug("adding watch on '%s'", udev_device_get_devnode(dev));
-        wd = inotify_add_watch(inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE);
-        if (wd < 0) {
-                log_error_errno(errno, "inotify_add_watch(%d, %s, %o) failed: %m",
-                                inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE);
-                return;
-        }
+                return log_error_errno(EINVAL, "Invalid inotify descriptor.");
+
+        r = sd_device_get_devname(dev, &devnode);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get device name: %m");
+
+        log_debug("Adding watch on '%s'", devnode);
+        wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE);
+        if (wd < 0)
+                return log_error_errno(errno, "Failed to add device '%s' to watch: %m", devnode);
+
+        device_set_watch_handle(dev, wd);
 
         xsprintf(filename, "/run/udev/watch/%d", wd);
-        mkdir_parents(filename, 0755);
-        unlink(filename);
-        r = symlink(udev_device_get_id_filename(dev), filename);
+        r = mkdir_parents(filename, 0755);
         if (r < 0)
-                log_error_errno(errno, "Failed to create symlink %s: %m", filename);
+                return log_error_errno(r, "Failed to create parent directory of '%s': %m", filename);
+        (void) unlink(filename);
+
+        r = device_get_id_filename(dev, &id_filename);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get device id-filename: %m");
+
+        if (symlink(id_filename, filename) < 0)
+                return log_error_errno(errno, "Failed to create symlink %s: %m", filename);
 
-        udev_device_set_watch_handle(dev, wd);
+        return 0;
 }
 
-void udev_watch_end(struct udev_device *dev) {
-        int wd;
-        char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
+int udev_watch_end(sd_device *dev) {
+        char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
+        const char *devnode;
+        int wd, r;
 
         if (inotify_fd < 0)
-                return;
+                return log_error_errno(EINVAL, "Invalid inotify descriptor.");
 
-        wd = udev_device_get_watch_handle(dev);
-        if (wd < 0)
-                return;
+        r = device_get_watch_handle(dev, &wd);
+        if (r == -ENOENT)
+                return 0;
+        if (r < 0)
+                return log_error_errno(r, "Failed to get watch handle for device '%s', ignoring: %m", devnode);
+
+        r = sd_device_get_devname(dev, &devnode);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get device name: %m");
 
-        log_debug("removing watch on '%s'", udev_device_get_devnode(dev));
-        inotify_rm_watch(inotify_fd, wd);
+        log_debug("Removing watch on '%s'", devnode);
+        (void) inotify_rm_watch(inotify_fd, wd);
 
         xsprintf(filename, "/run/udev/watch/%d", wd);
-        unlink(filename);
+        (void) unlink(filename);
 
-        udev_device_set_watch_handle(dev, -1);
+        device_set_watch_handle(dev, -1);
+
+        return 0;
 }
 
-struct udev_device *udev_watch_lookup(int wd) {
-        char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
-        char device[UTIL_NAME_SIZE];
+int udev_watch_lookup(int wd, sd_device **ret) {
+        char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)], device[PATH_MAX];
         ssize_t len;
+        int r;
+
+        assert(ret);
+
+        if (inotify_fd < 0)
+                return log_error_errno(EINVAL, "Invalid inotify descriptor.");
 
-        if (inotify_fd < 0 || wd < 0)
-                return NULL;
+        if (wd < 0)
+                return log_error_errno(EINVAL, "Invalid watch handle.");
 
         xsprintf(filename, "/run/udev/watch/%d", wd);
         len = readlink(filename, device, sizeof(device));
-        if (len <= 0 || (size_t)len == sizeof(device))
-                return NULL;
+        if (len <= 0) {
+                if (errno != ENOENT)
+                        return log_error_errno(errno, "Failed to read link '%s': %m", filename);
+                return 0;
+        } else if (len >= (ssize_t) sizeof(device))
+                return log_error_errno(ENAMETOOLONG, "Path specified by link '%s' is truncated.", filename);
         device[len] = '\0';
 
-        return udev_device_new_from_device_id(NULL, device);
+        r = sd_device_new_from_device_id(ret, device);
+        if (r < 0)
+                return log_error_errno(r, "Failed to create sd_device object for '%s': %m", device);
+
+        return 0;
 }
diff --git a/src/udev/udev-watch.h b/src/udev/udev-watch.h
new file mode 100644 (file)
index 0000000..24a136d
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#pragma once
+
+#include "sd-device.h"
+
+int udev_watch_init(void);
+int udev_watch_restore(void);
+int udev_watch_begin(sd_device *dev);
+int udev_watch_end(sd_device *dev);
+int udev_watch_lookup(int wd, sd_device **ret);
index 1164d2fb1b35a455bf03fb3f44a50aac7803e224..1176b4a44b2a2b395c8228b3734f05c930fa1046 100644 (file)
@@ -10,6 +10,7 @@
 #include <sys/types.h>
 
 #include "libudev.h"
+#include "sd-device.h"
 #include "sd-netlink.h"
 
 #include "label.h"
@@ -76,13 +77,6 @@ void udev_event_execute_rules(struct udev_event *event,
                               struct udev_rules *rules);
 void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec);
 
-/* udev-watch.c */
-int udev_watch_init(void);
-void udev_watch_restore(void);
-void udev_watch_begin(struct udev_device *dev);
-void udev_watch_end(struct udev_device *dev);
-struct udev_device *udev_watch_lookup(int wd);
-
 /* udev-node.c */
 void udev_node_add(struct udev_device *dev, bool apply,
                    mode_t mode, uid_t uid, gid_t gid,
index 40aa9650af1578c5e2e3b79fbc342f7d570628d5..3259d45c10d0c988a5233a488415173b6671f152 100644 (file)
 #include "cgroup-util.h"
 #include "cpu-set-util.h"
 #include "dev-setup.h"
+#include "device-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-util.h"
 #include "fs-util.h"
 #include "hashmap.h"
 #include "io-util.h"
+#include "libudev-device-internal.h"
 #include "list.h"
 #include "netlink-util.h"
 #include "parse-util.h"
@@ -51,6 +53,7 @@
 #include "string-util.h"
 #include "terminal-util.h"
 #include "udev-util.h"
+#include "udev-watch.h"
 #include "udev.h"
 #include "user-util.h"
 
@@ -451,7 +454,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
 
                         /* apply/restore inotify watch */
                         if (udev_event->inotify_watch) {
-                                udev_watch_begin(dev);
+                                udev_watch_begin(dev->device);
                                 udev_device_update_db(dev);
                         }
 
@@ -997,18 +1000,38 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd
         return 1;
 }
 
-static int synthesize_change(struct udev_device *dev) {
-        char filename[UTIL_PATH_SIZE];
+static int synthesize_change(sd_device *dev) {
+        const char *subsystem, *sysname, *devname, *syspath, *devtype;
+        char filename[PATH_MAX];
         int r;
 
-        if (streq_ptr("block", udev_device_get_subsystem(dev)) &&
-            streq_ptr("disk", udev_device_get_devtype(dev)) &&
-            !startswith(udev_device_get_sysname(dev), "dm-")) {
-                bool part_table_read = false;
-                bool has_partitions = false;
+        r = sd_device_get_subsystem(dev, &subsystem);
+        if (r < 0)
+                return r;
+
+        r = sd_device_get_sysname(dev, &sysname);
+        if (r < 0)
+                return r;
+
+        r = sd_device_get_devname(dev, &devname);
+        if (r < 0)
+                return r;
+
+        r = sd_device_get_syspath(dev, &syspath);
+        if (r < 0)
+                return r;
+
+        r = sd_device_get_devtype(dev, &devtype);
+        if (r < 0)
+                return r;
+
+        if (streq_ptr("block", subsystem) &&
+            streq_ptr("disk", devtype) &&
+            !startswith(sysname, "dm-")) {
+                _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+                bool part_table_read = false, has_partitions = false;
+                sd_device *d;
                 int fd;
-                _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
-                struct udev_list_entry *item;
 
                 /*
                  * Try to re-read the partition table. This only succeeds if
@@ -1016,7 +1039,7 @@ static int synthesize_change(struct udev_device *dev) {
                  * partition table is found, and we will not get an event for
                  * the disk.
                  */
-                fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK);
+                fd = open(devname, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK);
                 if (fd >= 0) {
                         r = flock(fd, LOCK_EX|LOCK_NB);
                         if (r >= 0)
@@ -1028,30 +1051,27 @@ static int synthesize_change(struct udev_device *dev) {
                 }
 
                 /* search for partitions */
-                e = udev_enumerate_new(NULL);
-                if (!e)
-                        return -ENOMEM;
-
-                r = udev_enumerate_add_match_parent(e, dev);
+                r = sd_device_enumerator_new(&e);
                 if (r < 0)
                         return r;
 
-                r = udev_enumerate_add_match_subsystem(e, "block");
+                r = sd_device_enumerator_allow_uninitialized(e);
                 if (r < 0)
                         return r;
 
-                r = udev_enumerate_scan_devices(e);
+                r = sd_device_enumerator_add_match_parent(e, dev);
                 if (r < 0)
                         return r;
 
-                udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) {
-                        _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
+                r = sd_device_enumerator_add_match_subsystem(e, "block", true);
+                if (r < 0)
+                        return r;
 
-                        d = udev_device_new_from_syspath(NULL, udev_list_entry_get_name(item));
-                        if (!d)
-                                continue;
+                FOREACH_DEVICE(e, d) {
+                        const char *t;
 
-                        if (!streq_ptr("partition", udev_device_get_devtype(d)))
+                        if (sd_device_get_devtype(d, &t) < 0 ||
+                            !streq("partition", t))
                                 continue;
 
                         has_partitions = true;
@@ -1070,31 +1090,31 @@ static int synthesize_change(struct udev_device *dev) {
                  * We have partitions but re-reading the partition table did not
                  * work, synthesize "change" for the disk and all partitions.
                  */
-                log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev));
-                strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL);
+                log_debug("Device '%s' is closed, synthesising 'change'", devname);
+                strscpyl(filename, sizeof(filename), syspath, "/uevent", NULL);
                 write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
 
-                udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) {
-                        _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
+                FOREACH_DEVICE(e, d) {
+                        const char *t, *n, *s;
 
-                        d = udev_device_new_from_syspath(NULL, udev_list_entry_get_name(item));
-                        if (!d)
+                        if (sd_device_get_devtype(d, &t) < 0 ||
+                            !streq("partition", t))
                                 continue;
 
-                        if (!streq_ptr("partition", udev_device_get_devtype(d)))
+                        if (sd_device_get_devname(d, &n) < 0 ||
+                            sd_device_get_syspath(d, &s) < 0)
                                 continue;
 
-                        log_debug("device %s closed, synthesising partition '%s' 'change'",
-                                  udev_device_get_devnode(dev), udev_device_get_devnode(d));
-                        strscpyl(filename, sizeof(filename), udev_device_get_syspath(d), "/uevent", NULL);
+                        log_debug("Device '%s' is closed, synthesising partition '%s' 'change'", devname, n);
+                        strscpyl(filename, sizeof(filename), s, "/uevent", NULL);
                         write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
                 }
 
                 return 0;
         }
 
-        log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev));
-        strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL);
+        log_debug("Device %s is closed, synthesising 'change'", devname);
+        strscpyl(filename, sizeof(filename), syspath, "/uevent", NULL);
         write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
 
         return 0;
@@ -1117,13 +1137,16 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
         }
 
         FOREACH_INOTIFY_EVENT(e, buffer, l) {
-                _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
+                _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+                const char *devnode;
+
+                if (udev_watch_lookup(e->wd, &dev) < 0)
+                        continue;
 
-                dev = udev_watch_lookup(e->wd);
-                if (!dev)
+                if (sd_device_get_devname(dev, &devnode) < 0)
                         continue;
 
-                log_debug("inotify event: %x for %s", e->mask, udev_device_get_devnode(dev));
+                log_debug("inotify event: %x for %s", e->mask, devnode);
                 if (e->mask & IN_CLOSE_WRITE) {
                         synthesize_change(dev);