From: anonymix007 <48598263+anonymix007@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:40:29 +0000 (+0300) Subject: sd-device: Introduce sd_device_get_sysattr_value_with_size() X-Git-Tag: v258-rc1~668^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=907328749f7838762d901f302702b083c8b86b30;p=thirdparty%2Fsystemd.git sd-device: Introduce sd_device_get_sysattr_value_with_size() --- diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 370e3b7c922..4543fb0e60d 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -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; diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 98a10d5b1f9..12763f53b50 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -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) { diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c index 9758e073306..2db4f42c746 100644 --- a/src/libsystemd/sd-device/test-sd-device.c +++ b/src/libsystemd/sd-device/test-sd-device.c @@ -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); diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h index 8f6141b3dfa..71d8c89983b 100644 --- a/src/systemd/sd-device.h +++ b/src/systemd/sd-device.h @@ -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);