From cb3f6c9e0d3268e710c79b9f84911a882fc67577 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Thu, 17 Apr 2025 10:20:33 +0200 Subject: [PATCH 1/8] udevadm-info: move static dtor closer to args --- src/udev/udevadm-info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 1838d12f5f5..c358a503ff5 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -61,6 +61,8 @@ static usec_t arg_wait_for_initialization_timeout = 0; PagerFlags arg_pager_flags = 0; static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF; +STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); + /* Put a limit on --tree descent level to not exhaust our stack */ #define TREE_DEPTH_MAX 64 @@ -83,8 +85,6 @@ typedef struct SysAttr { const char *value; } SysAttr; -STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); - static int sysattr_compare(const SysAttr *a, const SysAttr *b) { assert(a); assert(b); From 5b4d73208e1aec9155fe4bcd3a2c3780a7fdf9df Mon Sep 17 00:00:00 2001 From: David Tardon Date: Thu, 17 Apr 2025 10:21:41 +0200 Subject: [PATCH 2/8] udevadm-info: make arg_pager_flags static --- src/udev/udevadm-info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index c358a503ff5..dae9c010d58 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -58,7 +58,7 @@ static bool arg_export = false; static bool arg_value = false; static const char *arg_export_prefix = NULL; static usec_t arg_wait_for_initialization_timeout = 0; -PagerFlags arg_pager_flags = 0; +static PagerFlags arg_pager_flags = 0; static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF; STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); From 86ff972ac3b5c362a813c523225b8c5c18b4fc3f Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 25 Apr 2025 14:42:34 +0200 Subject: [PATCH 3/8] udevadm-info: drop superfluous pager_open() call It's already called in advance in info_main(). --- src/udev/udevadm-info.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index dae9c010d58..9b72977bcae 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -454,8 +454,6 @@ static int export_devices(sd_device_enumerator *e) { if (r < 0) return log_error_errno(r, "Failed to scan devices: %m"); - pager_open(arg_pager_flags); - FOREACH_DEVICE_AND_SUBSYSTEM(e, d) if (sd_json_format_enabled(arg_json_format_flags)) { _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; From d89b3004da54228eb5ab2f3326a773a6e97924b9 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 3 Nov 2023 14:56:52 +0100 Subject: [PATCH 4/8] udevadm-info: split arg. parsing into a separate function --- src/udev/udevadm-info.c | 396 ++++++++++++++++++++++++++-------------- 1 file changed, 260 insertions(+), 136 deletions(-) diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 9b72977bcae..2eda70d1c01 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -42,6 +42,7 @@ typedef enum ActionType { ACTION_DEVICE_ID_FILE, ACTION_TREE, ACTION_EXPORT, + ACTION_CLEANUP_DB, } ActionType; typedef enum QueryType { @@ -60,8 +61,33 @@ static const char *arg_export_prefix = NULL; static usec_t arg_wait_for_initialization_timeout = 0; static PagerFlags arg_pager_flags = 0; static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF; +static ActionType arg_action_type = ACTION_QUERY; +static QueryType arg_query = QUERY_ALL; +static char **arg_devices = NULL; +static char *arg_name = NULL; +static char **arg_attr_match = NULL; +static char **arg_attr_nomatch = NULL; +static char **arg_name_match = NULL; +static char **arg_parent_match = NULL; +static char **arg_property_match = NULL; +static char **arg_subsystem_match = NULL; +static char **arg_subsystem_nomatch = NULL; +static char **arg_sysname_match = NULL; +static char **arg_tag_match = NULL; +static int arg_initialized_match = -1; STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_devices, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_name, freep); +STATIC_DESTRUCTOR_REGISTER(arg_attr_match, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_attr_nomatch, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_name_match, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_parent_match, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_property_match, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_subsystem_match, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_subsystem_nomatch, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_sysname_match, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_tag_match, strv_freep); /* Put a limit on --tree descent level to not exhaust our stack */ #define TREE_DEPTH_MAX 64 @@ -444,11 +470,126 @@ static int stat_device(const char *name, bool export, const char *prefix) { return 0; } -static int export_devices(sd_device_enumerator *e) { - sd_device *d; +static int add_match_parent(sd_device_enumerator *e, const char *s, const char *prefix) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; int r; assert(e); + assert(s); + + r = find_device(s, prefix, &dev); + if (r < 0) + return log_error_errno(r, "Failed to open the device '%s': %m", s); + + r = device_enumerator_add_match_parent_incremental(e, dev); + if (r < 0) + return log_error_errno(r, "Failed to add parent match '%s': %m", s); + + return 0; +} + +static int setup_matches(sd_device_enumerator *e) { + int r; + + assert(e); + + STRV_FOREACH(n, arg_name_match) { + r = add_match_parent(e, *n, "/dev"); + if (r < 0) + return r; + } + + STRV_FOREACH(p, arg_parent_match) { + r = add_match_parent(e, *p, "/sys"); + if (r < 0) + return r; + } + + STRV_FOREACH(s, arg_subsystem_match) { + r = sd_device_enumerator_add_match_subsystem(e, *s, /* match= */ true); + if (r < 0) + return log_error_errno(r, "Failed to add subsystem match '%s': %m", *s); + } + + STRV_FOREACH(s, arg_subsystem_nomatch) { + r = sd_device_enumerator_add_match_subsystem(e, *s, /* match= */ false); + if (r < 0) + return log_error_errno(r, "Failed to add negative subsystem match '%s': %m", *s); + } + + STRV_FOREACH(a, arg_attr_match) { + _cleanup_free_ char *k = NULL, *v = NULL; + + r = parse_key_value_argument(*a, /* require_value= */ true, &k, &v); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_sysattr(e, k, v, /* match= */ true); + if (r < 0) + return log_error_errno(r, "Failed to add sysattr match '%s=%s': %m", k, v); + } + + STRV_FOREACH(a, arg_attr_nomatch) { + _cleanup_free_ char *k = NULL, *v = NULL; + + r = parse_key_value_argument(*a, /* require_value= */ true, &k, &v); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_sysattr(e, k, v, /* match= */ false); + if (r < 0) + return log_error_errno(r, "Failed to add negative sysattr match '%s=%s': %m", k, v); + } + + STRV_FOREACH(p, arg_property_match) { + _cleanup_free_ char *k = NULL, *v = NULL; + + r = parse_key_value_argument(*p, /* require_value= */ true, &k, &v); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_property_required(e, k, v); + if (r < 0) + return log_error_errno(r, "Failed to add property match '%s=%s': %m", k, v); + } + + STRV_FOREACH(t, arg_tag_match) { + r = sd_device_enumerator_add_match_tag(e, *t); + if (r < 0) + return log_error_errno(r, "Failed to add tag match '%s': %m", *t); + } + + STRV_FOREACH(s, arg_sysname_match) { + r = sd_device_enumerator_add_match_sysname(e, *s); + if (r < 0) + return log_error_errno(r, "Failed to add sysname match '%s': %m", *s); + } + + if (arg_initialized_match != -1) { + r = device_enumerator_add_match_is_initialized(e, arg_initialized_match); + if (r < 0) + return log_error_errno(r, "Failed to set initialized filter: %m"); + } + + return 0; +} + +static int export_devices(void) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d; + int r; + + r = sd_device_enumerator_new(&e); + if (r < 0) + return log_error_errno(r, "Failed to create device enumerator: %m"); + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return log_error_errno(r, "Failed to allow uninitialized devices: %m"); + + r = setup_matches(e); + if (r < 0) + return r; r = device_enumerator_scan_devices(e); if (r < 0) @@ -854,30 +995,7 @@ static int print_tree(sd_device* below) { return 0; } -static int ensure_device_enumerator(sd_device_enumerator **e) { - int r; - - assert(e); - - if (*e) - return 0; - - r = sd_device_enumerator_new(e); - if (r < 0) - return log_error_errno(r, "Failed to create device enumerator: %m"); - - r = sd_device_enumerator_allow_uninitialized(*e); - if (r < 0) - return log_error_errno(r, "Failed to allow uninitialized devices: %m"); - - return 0; -} - -int info_main(int argc, char *argv[], void *userdata) { - _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; - _cleanup_strv_free_ char **devices = NULL; - _cleanup_free_ char *name = NULL; - int c, r, ret; +static int parse_argv(int argc, char *argv[]) { enum { ARG_PROPERTY = 0x100, @@ -930,11 +1048,14 @@ int info_main(int argc, char *argv[], void *userdata) { {} }; - ActionType action = ACTION_QUERY; - QueryType query = QUERY_ALL; + int c, r; + + assert(argc >= 0); + assert(argv); while ((c = getopt_long(argc, argv, "atced:n:p:q:rxP:w::Vh", options, NULL)) >= 0) switch (c) { + case ARG_PROPERTY: /* Make sure that if the empty property list was specified, we won't show any properties. */ @@ -948,9 +1069,11 @@ int info_main(int argc, char *argv[], void *userdata) { return log_oom(); } break; + case ARG_VALUE: arg_value = true; break; + case 'n': case 'p': { const char *prefix = c == 'n' ? "/dev/" : "/sys/"; @@ -960,55 +1083,64 @@ int info_main(int argc, char *argv[], void *userdata) { if (!path) return log_oom(); - r = strv_consume(&devices, path); + r = strv_consume(&arg_devices, path); if (r < 0) return log_oom(); break; } case 'q': - action = ACTION_QUERY; + arg_action_type = ACTION_QUERY; if (streq(optarg, "property") || streq(optarg, "env")) - query = QUERY_PROPERTY; + arg_query = QUERY_PROPERTY; else if (streq(optarg, "name")) - query = QUERY_NAME; + arg_query = QUERY_NAME; else if (streq(optarg, "symlink")) - query = QUERY_SYMLINK; + arg_query = QUERY_SYMLINK; else if (streq(optarg, "path")) - query = QUERY_PATH; + arg_query = QUERY_PATH; else if (streq(optarg, "all")) - query = QUERY_ALL; + arg_query = QUERY_ALL; else return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "unknown query type"); break; + case 'r': arg_root = true; break; + case 'd': - action = ACTION_DEVICE_ID_FILE; - r = free_and_strdup(&name, optarg); + arg_action_type = ACTION_DEVICE_ID_FILE; + r = free_and_strdup(&arg_name, optarg); if (r < 0) return log_oom(); break; + case 'a': - action = ACTION_ATTRIBUTE_WALK; + arg_action_type = ACTION_ATTRIBUTE_WALK; break; + case 't': - action = ACTION_TREE; + arg_action_type = ACTION_TREE; break; + case 'e': - action = ACTION_EXPORT; + arg_action_type = ACTION_EXPORT; break; + case 'c': - cleanup_db(); - return 0; + arg_action_type = ACTION_CLEANUP_DB; + break; + case 'x': arg_export = true; break; + case 'P': arg_export = true; arg_export_prefix = optarg; break; + case 'w': if (optarg) { r = parse_sec(optarg, &arg_wait_for_initialization_timeout); @@ -1017,10 +1149,13 @@ int info_main(int argc, char *argv[], void *userdata) { } else arg_wait_for_initialization_timeout = USEC_INFINITY; break; + case 'V': return print_version(); + case 'h': return help(); + case ARG_NO_PAGER: arg_pager_flags |= PAGER_DISABLE; break; @@ -1032,133 +1167,101 @@ int info_main(int argc, char *argv[], void *userdata) { break; case ARG_SUBSYSTEM_MATCH: + r = strv_extend(&arg_subsystem_match, optarg); + if (r < 0) + return log_oom(); + break; + case ARG_SUBSYSTEM_NOMATCH: - r = ensure_device_enumerator(&e); + r = strv_extend(&arg_subsystem_nomatch, optarg); if (r < 0) - return r; - - r = sd_device_enumerator_add_match_subsystem(e, optarg, c == ARG_SUBSYSTEM_MATCH); - if (r < 0) - return log_error_errno(r, "Failed to add%s subsystem match '%s': %m", - c == ARG_SUBSYSTEM_MATCH ? "" : " negative", optarg); - + return log_oom(); break; case ARG_ATTR_MATCH: - case ARG_ATTR_NOMATCH: { - _cleanup_free_ char *k = NULL, *v = NULL; + if (!strchr(optarg, '=')) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "expect = instead of '%s'", optarg); - r = ensure_device_enumerator(&e); + r = strv_extend(&arg_attr_match, optarg); if (r < 0) - return r; - - r = parse_key_value_argument(optarg, /* require_value= */ true, &k, &v); - if (r < 0) - return r; - - r = sd_device_enumerator_add_match_sysattr(e, k, v, c == ARG_ATTR_MATCH); - if (r < 0) - return log_error_errno(r, "Failed to add%s sysattr match '%s=%s': %m", - c == ARG_ATTR_MATCH ? "" : " negative", k, v); + return log_oom(); break; - } - case ARG_PROPERTY_MATCH: { - _cleanup_free_ char *k = NULL, *v = NULL; + case ARG_ATTR_NOMATCH: + if (!strchr(optarg, '=')) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "expect = instead of '%s'", optarg); - r = ensure_device_enumerator(&e); + r = strv_extend(&arg_attr_nomatch, optarg); if (r < 0) - return r; - - r = parse_key_value_argument(optarg, /* require_value= */ true, &k, &v); - if (r < 0) - return r; - - r = sd_device_enumerator_add_match_property_required(e, k, v); - if (r < 0) - return log_error_errno(r, "Failed to add property match '%s=%s': %m", k, v); + return log_oom(); + break; + + case ARG_PROPERTY_MATCH: + if (!strchr(optarg, '=')) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "expect = instead of '%s'", optarg); + + r = strv_extend(&arg_property_match, optarg); + if (r < 0) + return log_oom(); break; - } case ARG_TAG_MATCH: - r = ensure_device_enumerator(&e); + r = strv_extend(&arg_tag_match, optarg); if (r < 0) - return r; - - r = sd_device_enumerator_add_match_tag(e, optarg); - if (r < 0) - return log_error_errno(r, "Failed to add tag match '%s': %m", optarg); + return log_oom(); break; case ARG_SYSNAME_MATCH: - r = ensure_device_enumerator(&e); + r = strv_extend(&arg_sysname_match, optarg); if (r < 0) - return r; - - r = sd_device_enumerator_add_match_sysname(e, optarg); - if (r < 0) - return log_error_errno(r, "Failed to add sysname match '%s': %m", optarg); + return log_oom(); break; case ARG_NAME_MATCH: - case ARG_PARENT_MATCH: { - _cleanup_(sd_device_unrefp) sd_device *dev = NULL; - - r = find_device(optarg, c == ARG_NAME_MATCH ? "/dev" : "/sys", &dev); + r = strv_extend(&arg_name_match, optarg); if (r < 0) - return log_error_errno(r, "Failed to open the device '%s': %m", optarg); - - r = ensure_device_enumerator(&e); - if (r < 0) - return r; - - r = device_enumerator_add_match_parent_incremental(e, dev); - if (r < 0) - return log_error_errno(r, "Failed to add parent match '%s': %m", optarg); + return log_oom(); + break; + + case ARG_PARENT_MATCH: + r = strv_extend(&arg_parent_match, optarg); + if (r < 0) + return log_oom(); break; - } case ARG_INITIALIZED_MATCH: - case ARG_INITIALIZED_NOMATCH: - r = ensure_device_enumerator(&e); - if (r < 0) - return r; + arg_initialized_match = MATCH_INITIALIZED_YES; + break; - r = device_enumerator_add_match_is_initialized(e, c == ARG_INITIALIZED_MATCH ? MATCH_INITIALIZED_YES : MATCH_INITIALIZED_NO); - if (r < 0) - return log_error_errno(r, "Failed to set initialized filter: %m"); + case ARG_INITIALIZED_NOMATCH: + arg_initialized_match = MATCH_INITIALIZED_NO; break; case '?': return -EINVAL; + default: assert_not_reached(); } - if (action == ACTION_DEVICE_ID_FILE) { - if (argv[optind]) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Positional arguments are not allowed with -d/--device-id-of-file."); - assert(name); - return stat_device(name, arg_export, arg_export_prefix); - } - - if (action == ACTION_EXPORT) { - r = ensure_device_enumerator(&e); - if (r < 0) - return r; - - return export_devices(e); - } - - r = strv_extend_strv(&devices, argv + optind, false); + r = strv_extend_strv(&arg_devices, argv + optind, /* filter_duplicates= */ false); if (r < 0) return log_error_errno(r, "Failed to build argument list: %m"); + bool has_positional_args = r > 0; - if (action != ACTION_TREE && strv_isempty(devices)) + if (IN_SET(arg_action_type, ACTION_DEVICE_ID_FILE, ACTION_CLEANUP_DB) && has_positional_args) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Positional arguments are not allowed with -d/--device-id-of-file and -c/--cleanup-db."); + + if (!IN_SET(arg_action_type, ACTION_DEVICE_ID_FILE, ACTION_CLEANUP_DB, ACTION_EXPORT, ACTION_TREE) && + strv_isempty(arg_devices)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "A device name or path is required"); - if (IN_SET(action, ACTION_ATTRIBUTE_WALK, ACTION_TREE) && strv_length(devices) > 1) + + if (IN_SET(arg_action_type, ACTION_ATTRIBUTE_WALK, ACTION_TREE) && strv_length(arg_devices) > 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Only one device may be specified with -a/--attribute-walk and -t/--tree"); @@ -1166,15 +1269,36 @@ int info_main(int argc, char *argv[], void *userdata) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "-x/--export or -P/--export-prefix cannot be used with --value"); + return 1; +} + +int info_main(int argc, char *argv[], void *userdata) { + int r, ret; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (arg_action_type == ACTION_CLEANUP_DB) { + cleanup_db(); + return 0; + } + + if (arg_action_type == ACTION_DEVICE_ID_FILE) + return stat_device(arg_name, arg_export, arg_export_prefix); + pager_open(arg_pager_flags); - if (strv_isempty(devices)) { - assert(action == ACTION_TREE); + if (arg_action_type == ACTION_EXPORT) + return export_devices(); + + if (strv_isempty(arg_devices)) { + assert(arg_action_type == ACTION_TREE); return print_tree(NULL); } ret = 0; - STRV_FOREACH(p, devices) { + STRV_FOREACH(p, arg_devices) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; r = find_device(*p, NULL, &device); @@ -1204,14 +1328,14 @@ int info_main(int argc, char *argv[], void *userdata) { device = d; } - if (action == ACTION_QUERY) - r = query_device(query, device); - else if (action == ACTION_ATTRIBUTE_WALK) { + if (arg_action_type == ACTION_QUERY) + r = query_device(arg_query, device); + else if (arg_action_type == ACTION_ATTRIBUTE_WALK) { if (sd_json_format_enabled(arg_json_format_flags)) r = print_device_chain_in_json(device); else r = print_device_chain(device); - } else if (action == ACTION_TREE) + } else if (arg_action_type == ACTION_TREE) r = print_tree(device); else assert_not_reached(); From 31767b92a0b3980e0ae8a0f44715f86e72c35f77 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Wed, 7 May 2025 14:35:54 +0200 Subject: [PATCH 5/8] udevadm-info: reject devices passed via opts too Follow-up-for a6b4b2fa010f6dc5e18f1a14d93204c6c1416278 --- src/udev/udevadm-info.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 2eda70d1c01..373ecdbe5d5 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -1250,11 +1250,10 @@ static int parse_argv(int argc, char *argv[]) { r = strv_extend_strv(&arg_devices, argv + optind, /* filter_duplicates= */ false); if (r < 0) return log_error_errno(r, "Failed to build argument list: %m"); - bool has_positional_args = r > 0; - if (IN_SET(arg_action_type, ACTION_DEVICE_ID_FILE, ACTION_CLEANUP_DB) && has_positional_args) + if (IN_SET(arg_action_type, ACTION_DEVICE_ID_FILE, ACTION_CLEANUP_DB) && !strv_isempty(arg_devices)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Positional arguments are not allowed with -d/--device-id-of-file and -c/--cleanup-db."); + "Devices are not allowed with -d/--device-id-of-file and -c/--cleanup-db."); if (!IN_SET(arg_action_type, ACTION_DEVICE_ID_FILE, ACTION_CLEANUP_DB, ACTION_EXPORT, ACTION_TREE) && strv_isempty(arg_devices)) From 8ea3c1fb9eaa709af1d38866a570b0156e3dd7a4 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 25 Apr 2025 14:36:02 +0200 Subject: [PATCH 6/8] udevadm-info: shorten the code a bit --- src/udev/udevadm-info.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 373ecdbe5d5..17fd33f45c6 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -689,7 +689,7 @@ static void cleanup_dirs_after_db_cleanup(DIR *dir, DIR *datadir) { } } -static void cleanup_db(void) { +static int cleanup_db(void) { _cleanup_closedir_ DIR *dir1 = NULL, *dir2 = NULL, *dir3 = NULL, *dir4 = NULL; dir1 = opendir("/run/udev/data"); @@ -710,6 +710,8 @@ static void cleanup_db(void) { /* Do not remove /run/udev/watch. It will be handled by udevd well on restart. * And should not be removed by external program when udevd is running. */ + + return 0; } static int query_device(QueryType query, sd_device* device) { @@ -1278,10 +1280,8 @@ int info_main(int argc, char *argv[], void *userdata) { if (r <= 0) return r; - if (arg_action_type == ACTION_CLEANUP_DB) { - cleanup_db(); - return 0; - } + if (arg_action_type == ACTION_CLEANUP_DB) + return cleanup_db(); if (arg_action_type == ACTION_DEVICE_ID_FILE) return stat_device(arg_name, arg_export, arg_export_prefix); From 4ef3019ceb104ab80513c06287f1cd7dce6fdec3 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 25 Apr 2025 14:56:35 +0200 Subject: [PATCH 7/8] udevadm-info: drop args of stat_device() They are all static vars now, so can be used directly. --- src/udev/udevadm-info.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 17fd33f45c6..f7cbfa48787 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -450,17 +450,16 @@ static int record_to_json(sd_device *device, sd_json_variant **ret) { return 0; } -static int stat_device(const char *name, bool export, const char *prefix) { +static int stat_device(void) { struct stat statbuf; - assert(name); + assert(arg_name); - if (stat(name, &statbuf) != 0) + if (stat(arg_name, &statbuf) != 0) return -errno; - if (export) { - if (!prefix) - prefix = "INFO_"; + if (arg_export) { + const char *prefix = arg_export_prefix ?: "INFO_"; printf("%sMAJOR=%u\n" "%sMINOR=%u\n", prefix, major(statbuf.st_dev), @@ -1284,7 +1283,7 @@ int info_main(int argc, char *argv[], void *userdata) { return cleanup_db(); if (arg_action_type == ACTION_DEVICE_ID_FILE) - return stat_device(arg_name, arg_export, arg_export_prefix); + return stat_device(); pager_open(arg_pager_flags); From 6cdc63d120b3b11e2bb34bdde43c1cae16b02e44 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Wed, 7 May 2025 15:05:22 +0200 Subject: [PATCH 8/8] udevadm-info: use string table to parse query type --- src/udev/udevadm-info.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index f7cbfa48787..f505680dbd7 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -51,6 +51,8 @@ typedef enum QueryType { QUERY_SYMLINK, QUERY_PROPERTY, QUERY_ALL, + _QUERY_TYPE_MAX, + _QUERY_TYPE_INVALID = -EINVAL, } QueryType; static char **arg_properties = NULL; @@ -92,6 +94,16 @@ STATIC_DESTRUCTOR_REGISTER(arg_tag_match, strv_freep); /* Put a limit on --tree descent level to not exhaust our stack */ #define TREE_DEPTH_MAX 64 +static const char *query_type_table[_QUERY_TYPE_MAX] = { + [QUERY_NAME] = "name", + [QUERY_PATH] = "path", + [QUERY_SYMLINK] = "symlink", + [QUERY_PROPERTY] = "property", + [QUERY_ALL] = "all", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(query_type, QueryType); + static bool skip_attribute(const char *name) { assert(name); @@ -1091,19 +1103,13 @@ static int parse_argv(int argc, char *argv[]) { } case 'q': - arg_action_type = ACTION_QUERY; - if (streq(optarg, "property") || streq(optarg, "env")) - arg_query = QUERY_PROPERTY; - else if (streq(optarg, "name")) - arg_query = QUERY_NAME; - else if (streq(optarg, "symlink")) - arg_query = QUERY_SYMLINK; - else if (streq(optarg, "path")) - arg_query = QUERY_PATH; - else if (streq(optarg, "all")) - arg_query = QUERY_ALL; - else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "unknown query type"); + arg_query = query_type_from_string(optarg); + if (arg_query < 0) { + if (streq(optarg, "env")) /* deprecated */ + arg_query = QUERY_PROPERTY; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "unknown query type"); + } break; case 'r':