mirror of
https://github.com/systemd/systemd.git
synced 2026-08-02 22:20:20 +00:00
udevadm-info: parse all arguments before doing anything (#37292)
This commit is contained in:
@@ -42,6 +42,7 @@ typedef enum ActionType {
|
||||
ACTION_DEVICE_ID_FILE,
|
||||
ACTION_TREE,
|
||||
ACTION_EXPORT,
|
||||
ACTION_CLEANUP_DB,
|
||||
} ActionType;
|
||||
|
||||
typedef enum QueryType {
|
||||
@@ -50,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;
|
||||
@@ -58,12 +61,49 @@ 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 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
|
||||
|
||||
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);
|
||||
|
||||
@@ -83,8 +123,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);
|
||||
@@ -424,17 +462,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),
|
||||
@@ -444,18 +481,131 @@ 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)
|
||||
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;
|
||||
@@ -550,7 +700,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");
|
||||
@@ -571,6 +721,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) {
|
||||
@@ -856,30 +1008,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,
|
||||
@@ -932,11 +1061,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. */
|
||||
@@ -950,9 +1082,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/";
|
||||
@@ -962,55 +1096,58 @@ 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;
|
||||
if (streq(optarg, "property") || streq(optarg, "env"))
|
||||
query = QUERY_PROPERTY;
|
||||
else if (streq(optarg, "name"))
|
||||
query = QUERY_NAME;
|
||||
else if (streq(optarg, "symlink"))
|
||||
query = QUERY_SYMLINK;
|
||||
else if (streq(optarg, "path"))
|
||||
query = QUERY_PATH;
|
||||
else if (streq(optarg, "all"))
|
||||
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':
|
||||
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);
|
||||
@@ -1019,10 +1156,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;
|
||||
@@ -1034,133 +1174,100 @@ 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 <ATTR>=<value> 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 <ATTR>=<value> 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 <PROPERTY>=<value> 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");
|
||||
|
||||
if (action != ACTION_TREE && strv_isempty(devices))
|
||||
if (IN_SET(arg_action_type, ACTION_DEVICE_ID_FILE, ACTION_CLEANUP_DB) && !strv_isempty(arg_devices))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"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))
|
||||
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");
|
||||
|
||||
@@ -1168,15 +1275,34 @@ 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)
|
||||
return cleanup_db();
|
||||
|
||||
if (arg_action_type == ACTION_DEVICE_ID_FILE)
|
||||
return stat_device();
|
||||
|
||||
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);
|
||||
@@ -1206,14 +1332,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();
|
||||
|
||||
Reference in New Issue
Block a user