<refsect2><title>udevadm info
<arg choice="opt"><replaceable>options</replaceable></arg>
- <arg choice="opt"><replaceable>devpath</replaceable>|<replaceable>file</replaceable></arg>
+ <arg choice="opt" rep="repeat"><replaceable>devpath</replaceable>|<replaceable>file</replaceable>|<replaceable>unit</replaceable></arg>
</title>
- <para>Queries the udev database for device information
- stored in the udev database. It can also query the properties
- of a device from its sysfs representation to help creating udev
- rules that match this device.</para>
+ <para>Query the udev database for device information.</para>
+
+ <para>Positional arguments should be used to specify one or more devices. Each one may be a device name
+ (in which case it must start with <filename>/dev/</filename>), a sys path (in which case it must start
+ with <filename>/sys/</filename>), or a systemd device unit name (in which case it must end with
+ <literal>.device</literal>, see
+ <citerefentry><refentrytitle>systemd.device</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
+ </para>
+
<variablelist>
<varlistentry>
<term><option>-q</option></term>
<term><option>--query=<replaceable>TYPE</replaceable></option></term>
<listitem>
- <para>Query the database for the specified type of device
- data. It needs the <option>--path</option> or
- <option>--name</option> to identify the specified device.
+ <para>Query the database for the specified type of device data.
Valid <replaceable>TYPE</replaceable>s are:
<constant>name</constant>, <constant>symlink</constant>,
<constant>path</constant>, <constant>property</constant>,
<constant>all</constant>.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term><option>-p</option></term>
<term><option>--path=<replaceable>DEVPATH</replaceable></option></term>
<listitem>
- <para>The <filename>/sys</filename> path of the device to
- query, e.g.
- <filename><optional>/sys</optional>/class/block/sda</filename>.
- Note that this option usually is not very useful, since
- <command>udev</command> can guess the type of the
- argument, so <command>udevadm info
- --path=/class/block/sda</command> is equivalent to
- <command>udevadm info /sys/class/block/sda</command>.</para>
+ <para>The <filename>/sys</filename> path of the device to query, e.g.
+ <filename><optional>/sys</optional>/class/block/sda</filename>. This option is an alternative to
+ the positional argument with a <filename>/sys/</filename> prefix. <command>udevadm info
+ --path=/class/block/sda</command> is equivalent to <command>udevadm info
+ /sys/class/block/sda</command>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--name=<replaceable>FILE</replaceable></option></term>
<listitem>
<para>The name of the device node or a symlink to query,
- e.g. <filename><optional>/dev</optional>/sda</filename>.
- Note that this option usually is not very useful, since
- <command>udev</command> can guess the type of the
- argument, so <command>udevadm info --name=sda</command> is
- equivalent to <command>udevadm info /dev/sda</command>.</para>
+ e.g. <filename><optional>/dev</optional>/sda</filename>. This option is an alternative to the
+ positional argument with a <filename>/dev/</filename> prefix. <command>udevadm info
+ --name=sda</command> is equivalent to <command>udevadm info /dev/sda</command>.</para>
</listitem>
</varlistentry>
<varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
-
- <para>In addition, an optional positional argument can be used
- to specify a device name or a sys path. It must start with
- <filename>/dev</filename> or <filename>/sys</filename>
- respectively.</para>
</refsect2>
<refsect2><title>udevadm trigger
<arg choice="opt"><replaceable>options</replaceable></arg>
- <arg choice="opt" rep="repeat"><replaceable>devpath</replaceable>|<replaceable>file</replaceable></arg></title>
+ <arg choice="opt" rep="repeat"><replaceable>devpath</replaceable>|<replaceable>file</replaceable>|<replaceable>unit</replaceable></arg>
+ </title>
<para>Request device events from the kernel. Primarily used to replay events at system coldplug time.</para>
+
+ <para>Takes one or more device specifications as arguments. See the description of <command>info</command>
+ above.</para>
+
<variablelist>
<varlistentry>
<term><option>-v</option></term>
#include "udevadm.h"
#include "udevadm-util.h"
+typedef enum ActionType {
+ ACTION_QUERY,
+ ACTION_ATTRIBUTE_WALK,
+ ACTION_DEVICE_ID_FILE,
+} ActionType;
+
+typedef enum QueryType {
+ QUERY_NAME,
+ QUERY_PATH,
+ QUERY_SYMLINK,
+ QUERY_PROPERTY,
+ QUERY_ALL,
+} QueryType;
+
+static bool arg_root = false;
+static bool arg_export = false;
+static const char *arg_export_prefix = NULL;
+
static bool skip_attribute(const char *name) {
static const char* const skip[] = {
"uevent",
printf(" %s{%s}==\"%s\"\n", key, name, value);
}
- printf("\n");
+ puts("");
}
static int print_device_chain(sd_device *device) {
return 0;
}
-static void print_record(sd_device *device) {
+static int print_record(sd_device *device) {
const char *str, *val;
int i;
(void) sd_device_get_devpath(device, &str);
printf("P: %s\n", str);
- if (sd_device_get_devname(device, &str) >= 0)
- printf("N: %s\n", str + STRLEN("/dev/"));
+ if (sd_device_get_devname(device, &str) >= 0) {
+ assert_se(val = path_startswith(str, "/dev/"));
+ printf("N: %s\n", val);
+ }
if (device_get_devlink_priority(device, &i) >= 0)
printf("L: %i\n", i);
- FOREACH_DEVICE_DEVLINK(device, str)
- printf("S: %s\n", str + STRLEN("/dev/"));
+ FOREACH_DEVICE_DEVLINK(device, str) {
+ assert_se(val = path_startswith(str, "/dev/"));
+ printf("S: %s\n", val);
+ }
FOREACH_DEVICE_PROPERTY(device, str, val)
printf("E: %s=%s\n", str, val);
- printf("\n");
+ puts("");
+ return 0;
}
static int stat_device(const char *name, bool export, const char *prefix) {
cleanup_dir(dir5, 0, 1);
}
-static int help(void) {
+static int query_device(QueryType query, sd_device* device) {
+ int r;
+
+ assert(device);
+
+ switch(query) {
+ case QUERY_NAME: {
+ const char *node;
+
+ r = sd_device_get_devname(device, &node);
+ if (r < 0)
+ return log_error_errno(r, "No device node found: %m");
+
+ if (!arg_root)
+ assert_se(node = path_startswith(node, "/dev/"));
+ printf("%s\n", node);
+ return 0;
+ }
+
+ case QUERY_SYMLINK: {
+ const char *devlink, *prefix = "";
+
+ FOREACH_DEVICE_DEVLINK(device, devlink) {
+ if (!arg_root)
+ assert_se(devlink = path_startswith(devlink, "/dev/"));
+ printf("%s%s", prefix, devlink);
+ prefix = " ";
+ }
+ puts("");
+ return 0;
+ }
+
+ case QUERY_PATH: {
+ const char *devpath;
+
+ r = sd_device_get_devpath(device, &devpath);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get device path: %m");
+ printf("%s\n", devpath);
+ return 0;
+ }
+
+ case QUERY_PROPERTY: {
+ const char *key, *value;
+
+ FOREACH_DEVICE_PROPERTY(device, key, value)
+ if (arg_export)
+ printf("%s%s='%s'\n", strempty(arg_export_prefix), key, value);
+ else
+ printf("%s=%s\n", key, value);
+ return 0;
+ }
+
+ case QUERY_ALL:
+ return print_record(device);
+ }
+
+ assert_not_reached("unknown query type");
+ return 0;
+}
+
+static int help(void) {
printf("%s info [OPTIONS] [DEVPATH|FILE]\n\n"
"Query sysfs or the udev database.\n\n"
" -h --help Print this message\n"
}
int info_main(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_device_unrefp) sd_device *device = NULL;
- bool root = false, export = false;
+ _cleanup_strv_free_ char **devices = NULL;
_cleanup_free_ char *name = NULL;
- const char *export_prefix = NULL;
int c, r;
static const struct option options[] = {
{}
};
- enum action_type {
- ACTION_QUERY,
- ACTION_ATTRIBUTE_WALK,
- ACTION_DEVICE_ID_FILE,
- } action = ACTION_QUERY;
-
- enum query_type {
- QUERY_NAME,
- QUERY_PATH,
- QUERY_SYMLINK,
- QUERY_PROPERTY,
- QUERY_ALL,
- } query = QUERY_ALL;
+ ActionType action = ACTION_QUERY;
+ QueryType query = QUERY_ALL;
while ((c = getopt_long(argc, argv, "aced:n:p:q:rxP:RVh", options, NULL)) >= 0)
switch (c) {
case 'n':
- if (device) {
- log_error("device already specified");
- return -EINVAL;
- }
+ case 'p': {
+ const char *prefix = c == 'n' ? "/dev/" : "/sys/";
+ char *path;
- r = find_device(optarg, "/dev/", &device);
- if (r < 0)
- return log_error_errno(r, "device node not found: %m");
- break;
- case 'p':
- if (device) {
- log_error("device already specified");
- return -EINVAL;
- }
+ path = path_join(path_startswith(optarg, prefix) ? NULL : prefix, optarg);
+ if (!path)
+ return log_oom();
- r = find_device(optarg, "/sys", &device);
+ r = strv_consume(&devices, path);
if (r < 0)
- return log_error_errno(r, "syspath not found: %m");
+ return log_oom();
break;
+ }
+
case 'q':
action = ACTION_QUERY;
if (streq(optarg, "property") || streq(optarg, "env"))
}
break;
case 'r':
- root = true;
+ arg_root = true;
break;
case 'd':
action = ACTION_DEVICE_ID_FILE;
cleanup_db();
return 0;
case 'x':
- export = true;
+ arg_export = true;
break;
case 'P':
- export_prefix = optarg;
+ arg_export_prefix = optarg;
break;
case 'V':
return print_version();
assert_not_reached("Unknown option");
}
- switch (action) {
- case ACTION_QUERY:
- if (!device) {
- if (!argv[optind]) {
- help();
- return -EINVAL;
- }
- r = find_device(argv[optind], NULL, &device);
- if (r < 0)
- return log_error_errno(r, "Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected: %m");
- }
-
- switch(query) {
- case QUERY_NAME: {
- const char *node;
-
- r = sd_device_get_devname(device, &node);
- if (r < 0)
- return log_error_errno(r, "no device node found: %m");
-
- if (root)
- printf("%s\n", node);
- else
- printf("%s\n", node + STRLEN("/dev/"));
- break;
- }
- case QUERY_SYMLINK: {
- const char *devlink;
- bool first = true;
-
- FOREACH_DEVICE_DEVLINK(device, devlink) {
- if (!first)
- printf(" ");
- if (root)
- printf("%s", devlink);
- else
- printf("%s", devlink + STRLEN("/dev/"));
-
- first = false;
- }
- printf("\n");
- break;
- }
- case QUERY_PATH: {
- const char *devpath;
-
- r = sd_device_get_devpath(device, &devpath);
- if (r < 0)
- return log_error_errno(r, "Failed to get device path: %m");
- printf("%s\n", devpath);
- return 0;
- }
- case QUERY_PROPERTY: {
- const char *key, *value;
-
- FOREACH_DEVICE_PROPERTY(device, key, value)
- if (export)
- printf("%s%s='%s'\n", strempty(export_prefix), key, value);
- else
- printf("%s=%s\n", key, value);
+ 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);
+ }
- break;
- }
- case QUERY_ALL:
- print_record(device);
- break;
- default:
- assert_not_reached("unknown query type");
- }
- break;
- case ACTION_ATTRIBUTE_WALK:
- if (!device && argv[optind]) {
- r = find_device(argv[optind], NULL, &device);
- if (r < 0)
- return log_error_errno(r, "Unknown device, absolute path in /dev/ or /sys expected: %m");
- }
- if (!device) {
- log_error("Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.");
- return -EINVAL;
- }
- print_device_chain(device);
- break;
- case ACTION_DEVICE_ID_FILE:
- r = stat_device(name, export, export_prefix);
+ r = strv_extend_strv(&devices, argv + optind, false);
+ if (r < 0)
+ return log_error_errno(r, "Failed to build argument list: %m");
+
+ if (strv_isempty(devices))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "A device name or path is required");
+ if (action == ACTION_ATTRIBUTE_WALK && strv_length(devices) > 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Only one device may be specified with -a/--attribute-walk");
+
+ char **p;
+ STRV_FOREACH(p, devices) {
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
+
+ r = find_device(*p, NULL, &device);
+ if (r == -EINVAL)
+ return log_error_errno(r, "Bad argument \"%s\", expected an absolute path in /dev/ or /sys or a unit name: %m", *p);
+ if (r < 0)
+ return log_error_errno(r, "Unknown device \"%s\": %m", *p);
+
+ if (action == ACTION_QUERY)
+ r = query_device(query, device);
+ else if (action == ACTION_ATTRIBUTE_WALK)
+ r = print_device_chain(device);
+ else
+ assert_not_reached("Unknown action");
if (r < 0)
return r;
- break;
}
return 0;