diff --git a/man/udevadm.xml b/man/udevadm.xml index 2704156840..6091a3421f 100644 --- a/man/udevadm.xml +++ b/man/udevadm.xml @@ -98,6 +98,24 @@ + + + + When showing device properties using the + option, limit display to properties specified in the argument. The argument should + be a comma-separated list of property names. If not specified, all known properties + are shown. + + + + + + When showing device properties using the + option, print only their values, and skip the property name and =. + Cannot be used together with or + . + + diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm index 4210366808..08b4ab43a0 100644 --- a/shell-completion/bash/udevadm +++ b/shell-completion/bash/udevadm @@ -49,8 +49,8 @@ _udevadm() { [COMMON]='-h --help -V --version' [DEBUG]='-d --debug' [INFO_STANDALONE]='-r --root -a --attribute-walk -x --export -e --export-db -c --cleanup-db - -w --wait-for-initialization' - [INFO_ARG]='-q --query -p --path -n --name -P --export-prefix -d --device-id-of-file' + -w --wait-for-initialization --value' + [INFO_ARG]='-q --query -p --path -n --name -P --export-prefix -d --device-id-of-file --property' [TRIGGER_STANDALONE]='-v --verbose -n --dry-run -q --quiet -w --settle --wait-daemon --uuid' [TRIGGER_ARG]='-t --type -c --action -s --subsystem-match -S --subsystem-nomatch -a --attr-match -A --attr-nomatch -p --property-match diff --git a/shell-completion/zsh/_udevadm b/shell-completion/zsh/_udevadm index 1179f81a8b..eac56c7048 100644 --- a/shell-completion/zsh/_udevadm +++ b/shell-completion/zsh/_udevadm @@ -13,7 +13,9 @@ _udevadm_info(){ '--export-prefix=[Add a prefix to the key name of exported values.]:prefix' \ '--device-id-of-file=[Print major/minor numbers of the underlying device, where the file lives on.]:files:_udevadm_mounts' \ '--export-db[Export the content of the udev database.]' \ - '--cleanup-db[Cleanup the udev database.]' + '--cleanup-db[Cleanup the udev database.]' \ + '--value[When showing properties, print only their values.]' \ + '--property=[Show only properties by this name.]' } (( $+functions[_udevadm_trigger] )) || diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 85f826690c..84f7794e86 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -18,6 +18,7 @@ #include "dirent-util.h" #include "fd-util.h" #include "sort-util.h" +#include "static-destruct.h" #include "string-table.h" #include "string-util.h" #include "udev-util.h" @@ -38,8 +39,10 @@ typedef enum QueryType { QUERY_ALL, } QueryType; +static char **arg_properties = NULL; static bool arg_root = false; 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; @@ -60,6 +63,8 @@ typedef struct SysAttr { const char *value; } SysAttr; +STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); + static int sysattr_compare(const SysAttr *a, const SysAttr *b) { return strcmp(a->name, b->name); } @@ -316,11 +321,18 @@ static int query_device(QueryType query, sd_device* device) { case QUERY_PROPERTY: { const char *key, *value; - FOREACH_DEVICE_PROPERTY(device, key, value) + FOREACH_DEVICE_PROPERTY(device, key, value) { + if (arg_properties && !strv_contains(arg_properties, key)) + continue; + if (arg_export) printf("%s%s='%s'\n", strempty(arg_export_prefix), key, value); + else if (arg_value) + printf("%s\n", value); else printf("%s=%s\n", key, value); + } + return 0; } @@ -343,6 +355,8 @@ static int help(void) { " path sysfs device path\n" " property The device properties\n" " all All values\n" + " --property=NAME Show only properties by this name\n" + " --value When showing properties, print only their values\n" " -p --path=SYSPATH sysfs device path used for query or attribute walk\n" " -n --name=NAME Node or symlink name used for query or attribute walk\n" " -r --root Prepend dev directory to path names\n" @@ -365,20 +379,27 @@ int info_main(int argc, char *argv[], void *userdata) { _cleanup_free_ char *name = NULL; int c, r; + enum { + ARG_PROPERTY = 0x100, + ARG_VALUE, + }; + static const struct option options[] = { - { "attribute-walk", no_argument, NULL, 'a' }, - { "cleanup-db", no_argument, NULL, 'c' }, - { "device-id-of-file", required_argument, NULL, 'd' }, - { "export", no_argument, NULL, 'x' }, - { "export-db", no_argument, NULL, 'e' }, - { "export-prefix", required_argument, NULL, 'P' }, - { "help", no_argument, NULL, 'h' }, - { "name", required_argument, NULL, 'n' }, - { "path", required_argument, NULL, 'p' }, - { "query", required_argument, NULL, 'q' }, - { "root", no_argument, NULL, 'r' }, - { "version", no_argument, NULL, 'V' }, - { "wait-for-initialization", optional_argument, NULL, 'w' }, + { "attribute-walk", no_argument, NULL, 'a' }, + { "cleanup-db", no_argument, NULL, 'c' }, + { "device-id-of-file", required_argument, NULL, 'd' }, + { "export", no_argument, NULL, 'x' }, + { "export-db", no_argument, NULL, 'e' }, + { "export-prefix", required_argument, NULL, 'P' }, + { "help", no_argument, NULL, 'h' }, + { "name", required_argument, NULL, 'n' }, + { "path", required_argument, NULL, 'p' }, + { "property", required_argument, NULL, ARG_PROPERTY }, + { "query", required_argument, NULL, 'q' }, + { "root", no_argument, NULL, 'r' }, + { "value", no_argument, NULL, ARG_VALUE }, + { "version", no_argument, NULL, 'V' }, + { "wait-for-initialization", optional_argument, NULL, 'w' }, {} }; @@ -387,6 +408,22 @@ int info_main(int argc, char *argv[], void *userdata) { while ((c = getopt_long(argc, argv, "aced: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. */ + if (isempty(optarg) && !arg_properties) { + arg_properties = new0(char*, 1); + if (!arg_properties) + return log_oom(); + } else { + r = strv_split_and_extend(&arg_properties, optarg, ",", true); + if (r < 0) + return log_oom(); + } + break; + case ARG_VALUE: + arg_value = true; + break; case 'n': case 'p': { const char *prefix = c == 'n' ? "/dev/" : "/sys/"; @@ -478,6 +515,10 @@ int info_main(int argc, char *argv[], void *userdata) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Only one device may be specified with -a/--attribute-walk"); + if (arg_export && arg_value) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "-x/--export or -P/--export-prefix cannot be used with --value"); + char **p; STRV_FOREACH(p, devices) { _cleanup_(sd_device_unrefp) sd_device *device = NULL;