]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev-util: re-implement on_ac_power() with sd-device
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 4 Jan 2022 23:29:00 +0000 (08:29 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 6 Jan 2022 09:28:50 +0000 (18:28 +0900)
src/shared/udev-util.c

index 73ca886fb301d9dccc643286032966f84697c302..800493afe9e614bde6f2d481632bc42120074f73 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <ctype.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <sys/inotify.h>
 #include <unistd.h>
 
 #include "device-nodes.h"
 #include "device-private.h"
 #include "device-util.h"
-#include "dirent-util.h"
 #include "env-file.h"
 #include "errno-util.h"
 #include "escape.h"
 #include "fd-util.h"
-#include "fileio.h"
 #include "log.h"
 #include "macro.h"
 #include "parse-util.h"
@@ -584,60 +581,68 @@ int udev_queue_init(void) {
 }
 
 int on_ac_power(void) {
+        _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
         bool found_offline = false, found_online = false;
-        _cleanup_closedir_ DIR *d = NULL;
+        sd_device *d;
         int r;
 
-        d = opendir("/sys/class/power_supply");
-        if (!d)
-                return errno == ENOENT ? true : -errno;
+        r = sd_device_enumerator_new(&e);
+        if (r < 0)
+                return r;
 
-        FOREACH_DIRENT(de, d, return -errno) {
-                _cleanup_close_ int device_fd = -1;
-                _cleanup_free_ char *contents = NULL;
-                unsigned v;
+        r = sd_device_enumerator_allow_uninitialized(e);
+        if (r < 0)
+                return r;
 
-                device_fd = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
-                if (device_fd < 0) {
-                        if (IN_SET(errno, ENOENT, ENOTDIR))
-                                continue;
+        r = sd_device_enumerator_add_match_subsystem(e, "power_supply", true);
+        if (r < 0)
+                return r;
 
-                        return -errno;
-                }
+        FOREACH_DEVICE(e, d) {
+                const char *val;
+                unsigned v;
 
-                r = read_virtual_file_at(device_fd, "type", SIZE_MAX, &contents, NULL);
-                if (r == -ENOENT)
+                r = sd_device_get_sysattr_value(d, "type", &val);
+                if (r < 0) {
+                        log_device_debug_errno(d, r, "Failed to read 'type' sysfs attribute, ignoring: %m");
                         continue;
-                if (r < 0)
-                        return r;
-
-                delete_trailing_chars(contents, NEWLINE);
+                }
 
                 /* We assume every power source is AC, except for batteries. See
                  * https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176
                  * for defined power source types. Also see:
                  * https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power */
-                if (streq(contents, "Battery"))
+                if (streq(val, "Battery")) {
+                        log_device_debug(d, "The power supply is battery, ignoring.");
                         continue;
+                }
 
-                contents = mfree(contents);
-
-                r = read_virtual_file_at(device_fd, "online", SIZE_MAX, &contents, NULL);
-                if (r == -ENOENT)
+                r = sd_device_get_sysattr_value(d, "online", &val);
+                if (r < 0) {
+                        log_device_debug_errno(d, r, "Failed to read 'online' sysfs attribute, ignoring: %m");
                         continue;
-                if (r < 0)
-                        return r;
+                }
 
-                delete_trailing_chars(contents, NEWLINE);
+                r = safe_atou(val, &v);
+                if (r < 0) {
+                        log_device_debug_errno(d, r, "Failed to parse 'online' attribute, ignoring: %m");
+                        continue;
+                }
 
-                r = safe_atou(contents, &v);
-                if (r < 0)
-                        return r;
                 if (v > 0) /* At least 1 and 2 are defined as different types of 'online' */
                         found_online = true;
                 else
                         found_offline = true;
+
+                log_device_debug(d, "The power supply is currently %s.", v > 0 ? "online" : "offline");
         }
 
+        if (found_online)
+                log_debug("Found at least one online non-battery power supply, system is running on AC power.");
+        else if (!found_offline)
+                log_debug("Found no offline non-battery power supply, assuming system is running on AC power.");
+        else
+                log_debug("All non-battery power supplies are offline, assuming system is running with battery.");
+
         return found_online || !found_offline;
 }