From 1fc74d251e30196c9196cafd60d163c218bdc1aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 23 Aug 2022 16:24:02 +0200
Subject: [PATCH] sd-device: add helper to read a unsigned int attribute

There are dozens of places where this could be used, but I don't
want to do the conversion now because it's quite a bit of work.
I think we could export this function later on, because reading
numerical attributes is so common. But for now, I'm just adding the
helper to use it one place.

(cherry picked from commit 48a511cf92cbf202e9ef6064a9b5ebd1f497e1a8)

Conflict:code context adaptation
Reference:https://github.com/systemd/systemd-stable/commit/1fc74d251e30196c9196cafd60d163c218bdc1aa
---
 src/libsystemd/sd-device/device-private.h |  2 ++
 src/libsystemd/sd-device/sd-device.c      | 33 +++++++++++++++++++++++
 src/libsystemd/sd-device/test-sd-device.c |  7 +++++
 3 files changed, 42 insertions(+)

diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h
index 9602f9eda3..7fa8dc0035 100644
--- a/src/libsystemd/sd-device/device-private.h
+++ b/src/libsystemd/sd-device/device-private.h
@@ -18,6 +18,8 @@ static inline int device_new_from_watch_handle(sd_device **ret, int wd) {
         return device_new_from_watch_handle_at(ret, -1, wd);
 }
 
+int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value);
+int device_get_sysattr_bool(sd_device *device, const char *sysattr);
 int device_get_device_id(sd_device *device, const char **ret);
 
 int device_get_devlink_priority(sd_device *device, int *priority);
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index 62531b9564..5660538dd3 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -2172,6 +2172,39 @@ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr,
         return 0;
 }
 
+int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value) {
+        const char *value;
+        int r;
+
+        r = sd_device_get_sysattr_value(device, sysattr, &value);
+        if (r < 0)
+                return r;
+
+        unsigned v;
+        r = safe_atou(value, &v);
+        if (r < 0)
+                return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr);
+
+        if (ret_value)
+                *ret_value = v;
+        /* We return "true" if the value is positive. */
+        return v > 0;
+}
+
+int device_get_sysattr_bool(sd_device *device, const char *sysattr) {
+        const char *value;
+        int r;
+
+        assert(device);
+        assert(sysattr);
+
+        r = sd_device_get_sysattr_value(device, sysattr, &value);
+        if (r < 0)
+                return r;
+
+        return parse_boolean(value);
+}
+
 static void device_remove_cached_sysattr_value(sd_device *device, const char *_key) {
         _cleanup_free_ char *key = NULL;
 
diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c
index fa334df6c7..01c184a7d0 100644
--- a/src/libsystemd/sd-device/test-sd-device.c
+++ b/src/libsystemd/sd-device/test-sd-device.c
@@ -177,6 +177,13 @@ static void test_sd_device_one(sd_device *d) {
 
         r = sd_device_get_sysattr_value(d, "name_assign_type", &val);
         assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || IN_SET(r, -ENOENT, -EINVAL));
+
+        if (r > 0) {
+                unsigned x;
+
+                assert_se(device_get_sysattr_unsigned(d, "name_assign_type", NULL) >= 0);
+                assert_se(device_get_sysattr_unsigned(d, "name_assign_type", &x) >= 0);
+        }
 
         r = sd_device_get_property_value(d, "ID_NET_DRIVER", &val);
         assert_se(r >= 0 || r == -ENOENT);
-- 
2.33.0

