sd-device: Introduce sd_device_get_sysattr_value_with_size()

This commit is contained in:
anonymix007
2025-05-07 18:52:49 +03:00
parent eec1f041b1
commit 907328749f
4 changed files with 54 additions and 16 deletions
+1
View 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;
+39 -15
View 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) {
+12
View 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);
+2 -1
View 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);