]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-device: Introduce sd_device_get_sysattr_value_with_size()
authoranonymix007 <48598263+anonymix007@users.noreply.github.com>
Tue, 1 Apr 2025 14:40:29 +0000 (17:40 +0300)
committeranonymix007 <48598263+anonymix007@users.noreply.github.com>
Wed, 7 May 2025 15:52:49 +0000 (18:52 +0300)
src/libsystemd/libsystemd.sym
src/libsystemd/sd-device/sd-device.c
src/libsystemd/sd-device/test-sd-device.c
src/systemd/sd-device.h

index 370e3b7c922f7203e1bbf39d1be86fc51c9ea70d..4543fb0e60d45aa3a83cbbd791a312b9b04a8c6f 100644 (file)
@@ -1064,6 +1064,7 @@ LIBSYSTEMD_258 {
 global:
         sd_bus_message_dump_json;
         sd_device_enumerator_add_all_parents;
+        sd_device_get_sysattr_value_with_size;
         sd_json_variant_type_from_string;
         sd_json_variant_type_to_string;
         sd_varlink_get_current_method;
index 98a10d5b1f918049a4064ea6323e17eff1169d06..12763f53b500667324979279a73019e75f030674 100644 (file)
@@ -2333,6 +2333,8 @@ void device_clear_sysattr_cache(sd_device *device) {
 typedef struct SysAttrCacheEntry {
         char *key;
         char *value;
+        char *value_stripped;
+        size_t size;
         int error;
 } SysAttrCacheEntry;
 
@@ -2342,6 +2344,7 @@ static SysAttrCacheEntry* sysattr_cache_entry_free(SysAttrCacheEntry *p) {
 
         free(p->key);
         free(p->value);
+        free(p->value_stripped);
         return mfree(p);
 }
 
@@ -2350,7 +2353,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
                 char, path_hash_func, path_compare,
                 SysAttrCacheEntry, sysattr_cache_entry_free);
 
-static int device_cache_sysattr_value_full(sd_device *device, char *key, char *value, int error, bool ignore_uevent) {
+static int device_cache_sysattr_value_full(sd_device *device, char *key, char *value, size_t size, int error, bool ignore_uevent) {
         int r;
 
         assert(device);
@@ -2375,9 +2378,20 @@ static int device_cache_sysattr_value_full(sd_device *device, char *key, char *v
         if (!entry)
                 return -ENOMEM;
 
+        _cleanup_free_ char *value_stripped = NULL;
+
+        if (value) {
+                value_stripped = memdup_suffix0(value, size);
+                if (!value_stripped)
+                        return -ENOMEM;
+                delete_trailing_chars(value_stripped, NEWLINE);
+        }
+
         *entry = (SysAttrCacheEntry) {
                 .key = key,
                 .value = value,
+                .value_stripped = value_stripped,
+                .size = size,
                 .error = error,
         };
 
@@ -2386,14 +2400,15 @@ static int device_cache_sysattr_value_full(sd_device *device, char *key, char *v
                 return r;
 
         TAKE_PTR(entry);
+        TAKE_PTR(value_stripped);
         return 1; /* cached */
 }
 
 int device_cache_sysattr_value(sd_device *device, char *key, char *value, int error) {
-        return device_cache_sysattr_value_full(device, key, value, error, /* ignore_uevent = */ true);
+        return device_cache_sysattr_value_full(device, key, value, strlen(value), error, /* ignore_uevent = */ true);
 }
 
-static int device_get_cached_sysattr_value(sd_device *device, const char *key, const char **ret_value) {
+static int device_get_cached_sysattr_value(sd_device *device, const char *key, const char **ret_value, size_t *ret_size) {
         SysAttrCacheEntry *entry;
 
         assert(device);
@@ -2408,7 +2423,9 @@ static int device_get_cached_sysattr_value(sd_device *device, const char *key, c
                 return -entry->error;
         }
         if (ret_value)
-                *ret_value = entry->value;
+                *ret_value = ret_size ? entry->value : entry->value_stripped;
+        if (ret_size)
+                *ret_size = entry->size;
         return 0;
 }
 
@@ -2459,16 +2476,17 @@ int device_chase(sd_device *device, const char *path, ChaseFlags flags, char **r
         return 0;
 }
 
-_public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **ret_value) {
+_public_ int sd_device_get_sysattr_value_with_size(sd_device *device, const char *sysattr, const char **ret_value, size_t *ret_size) {
         _cleanup_free_ char *resolved = NULL, *value = NULL;
         _cleanup_close_ int fd = -EBADF;
+        size_t size = 0;
         int r;
 
         assert_return(device, -EINVAL);
         assert_return(sysattr, -EINVAL);
 
         /* Look for possibly already cached result. */
-        r = device_get_cached_sysattr_value(device, sysattr, ret_value);
+        r = device_get_cached_sysattr_value(device, sysattr, ret_value, ret_size);
         if (r != -ENOANO)
                 return r;
 
@@ -2487,6 +2505,9 @@ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr,
                         return -ENOMEM;
 
                 r = readlink_value(prefixed, &value);
+                if (r >= 0)
+                        size = strlen(value);
+
                 if (r != -EINVAL) /* -EINVAL means the path is not a symlink. */
                         goto cache_result;
         }
@@ -2496,18 +2517,16 @@ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr,
                 goto cache_result;
 
         /* Look for cached result again with the resolved path. */
-        r = device_get_cached_sysattr_value(device, resolved, ret_value);
+        r = device_get_cached_sysattr_value(device, resolved, ret_value, ret_size);
         if (r != -ENOANO)
                 return r;
 
         /* Read attribute value, Some attributes contain embedded '\0'. So, it is necessary to also get the
          * size of the result. See issue #20025. */
-        size_t size;
         r = read_virtual_file_fd(fd, SIZE_MAX, &value, &size);
         if (r < 0)
                 goto cache_result;
 
-        delete_trailing_chars(value, NEWLINE);
         r = 0;
 
 cache_result:
@@ -2521,7 +2540,7 @@ cache_result:
                         return RET_GATHER(r, -ENOMEM);
         }
 
-        int k = device_cache_sysattr_value_full(device, resolved, value, -r, /* ignore_uevent = */ false);
+        int k = device_cache_sysattr_value_full(device, resolved, value, size, -r, /* ignore_uevent = */ false);
         if (k < 0) {
                 if (r < 0)
                         log_device_debug_errno(device, k,
@@ -2541,13 +2560,18 @@ cache_result:
         }
         assert(k > 0);
 
-        if (ret_value && r >= 0)
-                *ret_value = value;
-
         /* device_cache_sysattr_value_full() takes 'resolved' and 'value' on success. */
-        TAKE_PTR(resolved);
+        sysattr = TAKE_PTR(resolved);
         TAKE_PTR(value);
-        return r;
+
+        if (r < 0)
+                return r;
+
+        return device_get_cached_sysattr_value(device, sysattr, ret_value, ret_size);
+}
+
+_public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **ret_value) {
+        return sd_device_get_sysattr_value_with_size(device, sysattr, ret_value, NULL);
 }
 
 int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_value) {
index 9758e0733067fb5021c6db405fc1386f9391972e..2db4f42c746d3c05a962a3f31e0c17f834f08dec 100644 (file)
@@ -133,6 +133,18 @@ static void test_sd_device_one(sd_device *d) {
                         ASSERT_ERROR(r, ENOENT);
         }
 
+        if (streq(subsystem, "drm")) {
+                const char *edid_content;
+                size_t edid_size = 0;
+
+                r = sd_device_get_sysattr_value_with_size(d, "edid", &edid_content, &edid_size);
+                if (r < 0)
+                        ASSERT_ERROR(r, ENOENT);
+
+                /* at least 128 if monitor is connected, otherwise 0 */
+                ASSERT_TRUE(edid_size == 0 || edid_size >= 128);
+        }
+
         is_block = streq_ptr(subsystem, "block");
 
         r = sd_device_get_devname(d, &devname);
index 8f6141b3dfaffdfe9f76af5e2f62e41dde02905e..71d8c89983b9293b2744a0ae5c23970d240bf9cf 100644 (file)
@@ -108,7 +108,8 @@ int sd_device_has_tag(sd_device *device, const char *tag);
 int sd_device_has_current_tag(sd_device *device, const char *tag);
 int sd_device_get_property_value(sd_device *device, const char *key, const char **value);
 int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret);
-int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value);
+int sd_device_get_sysattr_value_with_size(sd_device *device, const char *sysattr, const char **ret_value, size_t *ret_size);
+int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **ret_value);
 
 int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *value);
 int sd_device_set_sysattr_valuef(sd_device *device, const char *sysattr, const char *format, ...) _sd_printf_(3, 4);