diff --git a/man/rules/meson.build b/man/rules/meson.build index f10abdaf0d..add28a724c 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -502,6 +502,19 @@ manpages = [ 'sd_bus_track_unrefp'], ''], ['sd_bus_wait', '3', [], ''], + ['sd_device_get_syspath', + '3', + ['sd_device_get_devname', + 'sd_device_get_devnum', + 'sd_device_get_devpath', + 'sd_device_get_devtype', + 'sd_device_get_diskseq', + 'sd_device_get_driver', + 'sd_device_get_ifindex', + 'sd_device_get_subsystem', + 'sd_device_get_sysname', + 'sd_device_get_sysnum'], + ''], ['sd_event_add_child', '3', ['sd_event_add_child_pidfd', diff --git a/man/sd_device_get_syspath.xml b/man/sd_device_get_syspath.xml new file mode 100644 index 0000000000..54cb87a3f4 --- /dev/null +++ b/man/sd_device_get_syspath.xml @@ -0,0 +1,200 @@ + + + + + + + + sd_device_get_syspath + systemd + + + + sd_device_get_syspath + 3 + + + + sd_device_get_syspath + sd_device_get_devpath + sd_device_get_sysname + sd_device_get_sysnum + sd_device_get_subsystem + sd_device_get_devtype + sd_device_get_devname + sd_device_get_devnum + sd_device_get_ifindex + sd_device_get_driver + sd_device_get_diskseq + + Returns various fields of device objects + + + + + #include <systemd/sd-device.h> + + + int sd_device_get_syspath + sd_device *device + const char **ret + + + + int sd_device_get_devpath + sd_device *device + const char **ret + + + + int sd_device_get_sysname + sd_device *device + const char **ret + + + + int sd_device_get_sysnum + sd_device *device + const char **ret + + + + int sd_device_get_subsystem + sd_device *device + const char **ret + + + + int sd_device_get_devtype + sd_device *device + const char **ret + + + + int sd_device_get_devname + sd_device *device + const char **ret + + + + int sd_device_get_devnum + sd_device *device + dev_t *ret + + + + int sd_device_get_ifindex + sd_device *device + int *ret + + + + int sd_device_get_driver + sd_device *device + const char **ret + + + + int sd_device_get_diskseq + sd_device *device + uint64_t *ret + + + + + + + Description + + sd_device_get_syspath() returns the sysfs path of the specified device record, + including the /sys prefix. Example: /sys/devices/virtual/tty/tty7 + + sd_device_get_devpath() returns the sysfs path of the specified device record, + excluding the /sys prefix. Example: /devices/virtual/tty/tty7 + + sd_device_get_sysname() returns the sysfs name of the specified device record, + i.e. the last component of the sysfs path. Example: tty7 for the device + /sys/devices/virtual/tty/tty7 + + sd_device_get_sysnum() returns the sysfs device number of the specified device + record, i.e. the numeric suffix of the last component of the sysfs path. Example: 7 + for the device /sys/devices/virtual/tty/tty7 + + sd_device_get_subsystem() returns the kernel subsystem of the specified device + record. This is a short string fitting into a filename, and thus does not contain a slash and cannot be + empty. Example: tty, block or net. + + sd_device_get_devtype() returns the device type of the specified device + record, if the subsystem manages multiple types of devices. Example: for devices of the + block subsystem this can be disk or partition + + + sd_device_get_devname() returns the device node path of the specified device + record if the device has a device node. Example: for /sys/devices/virtual/tty/tty7 + the string /dev/tty7 is typically returned. + + sd_device_get_devnum() returns the device node major/minor + (i.e. dev_t) of the specified device record if the device has a device node (i.e. the one + returned by sd_device_get_devname()). For devices belonging to the + block subsystem this refers to a block device node, in all other cases to a character + device node. Example: for the /sys/devices/virtual/tty/tty7 device this typically + returns the device number with major/minor 4:7. + + sd_device_get_ifindex() returns the network interface index of the specified + device record, if the device encapsulates a network interface device, i.e. belongs to the + net subsystem. Example: the lo interface typically has interface + index 1. + + sd_device_get_driver() returns the kernel driver name attached to the + device. Note that the driver field is set on the devices consumed by the driver, not on the device + created by it. Example: a PCI device /sys/bus/pci/devices/0000:00:1f.6 might be + attached to a driver e1000e. + + sd_device_get_diskseq() returns the kernel disk sequence number of the block + device. This number monotonically increases whenever a backing medium of a block device changes without + the device name changing, and is relevant for block devices encapsulating devices with changing media + (e.g. floppy or CD-ROM), or loopback block devices. Only defined for block devices, i.e. those of + subsystem block. + + + + Return Value + + On success, these calls return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + A specified parameter is invalid. + + + + -ENOENT + + The requested field is not present in the device record. + + + + + + + + + + See Also + + + systemd1 + + + + diff --git a/man/udevadm.xml b/man/udevadm.xml index 3248cfd256..b0e448e568 100644 --- a/man/udevadm.xml +++ b/man/udevadm.xml @@ -230,6 +230,30 @@ P: Device path in /sys/ + + M: + Device name in /sys/ (i.e. the last component of P:) + + + R: + Device number in /sys/ (i.e. the numeric suffix of the last component of P:) + + + U: + Kernel subsystem + + + T: + Kernel device type within subsystem + + + D: + Kernel device node major/minor + + + I: + Network interface index + N: Kernel device node name @@ -242,6 +266,14 @@ S: Device node symlink + + Q: + Block device sequence number (DISKSEQ) + + + V: + Attached driver + E: Device property diff --git a/src/libsystemd/sd-device/device-internal.h b/src/libsystemd/sd-device/device-internal.h index 49d0f0fd1f..7ea964acf9 100644 --- a/src/libsystemd/sd-device/device-internal.h +++ b/src/libsystemd/sd-device/device-internal.h @@ -109,6 +109,7 @@ int device_set_devname(sd_device *device, const char *devname); int device_set_devtype(sd_device *device, const char *devtype); int device_set_devnum(sd_device *device, const char *major, const char *minor); int device_set_subsystem(sd_device *device, const char *subsystem); +int device_set_diskseq(sd_device *device, const char *str); int device_set_drivers_subsystem(sd_device *device); int device_set_driver(sd_device *device, const char *driver); int device_set_usec_initialized(sd_device *device, usec_t when); diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c index 5f3644aac4..de12ad7e00 100644 --- a/src/libsystemd/sd-device/device-private.c +++ b/src/libsystemd/sd-device/device-private.c @@ -255,28 +255,6 @@ static int device_set_seqnum(sd_device *device, const char *str) { return 0; } -static int device_set_diskseq(sd_device *device, const char *str) { - uint64_t diskseq; - int r; - - assert(device); - assert(str); - - r = safe_atou64(str, &diskseq); - if (r < 0) - return r; - if (diskseq == 0) - return -EINVAL; - - r = device_add_property_internal(device, "DISKSEQ", str); - if (r < 0) - return r; - - device->diskseq = diskseq; - - return 0; -} - static int device_amend(sd_device *device, const char *key, const char *value) { int r; diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 4f413880eb..22200c0eea 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -570,7 +570,34 @@ int device_set_devnum(sd_device *device, const char *major, const char *minor) { return 0; } -static int handle_uevent_line(sd_device *device, const char *key, const char *value, const char **major, const char **minor) { +int device_set_diskseq(sd_device *device, const char *str) { + uint64_t diskseq; + int r; + + assert(device); + assert(str); + + r = safe_atou64(str, &diskseq); + if (r < 0) + return r; + if (diskseq == 0) + return -EINVAL; + + r = device_add_property_internal(device, "DISKSEQ", str); + if (r < 0) + return r; + + device->diskseq = diskseq; + + return 0; +} + +static int handle_uevent_line( + sd_device *device, + const char *key, + const char *value, + const char **major, + const char **minor) { int r; assert(device); @@ -595,6 +622,10 @@ static int handle_uevent_line(sd_device *device, const char *key, const char *va r = device_set_devmode(device, value); if (r < 0) return r; + } else if (streq(key, "DISKSEQ")) { + r = device_set_diskseq(device, value); + if (r < 0) + return r; } else if (streq(key, "MAJOR")) *major = value; else if (streq(key, "MINOR")) @@ -1047,14 +1078,15 @@ _public_ int sd_device_get_driver(sd_device *device, const char **ret) { return 0; } -_public_ int sd_device_get_devpath(sd_device *device, const char **devpath) { +_public_ int sd_device_get_devpath(sd_device *device, const char **ret) { assert_return(device, -EINVAL); assert(device->devpath); assert(device->devpath[0] == '/'); - if (devpath) - *devpath = device->devpath; + if (ret) + *ret = device->devpath; + return 0; } diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index a088c1727c..12a1769bd8 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -22,9 +22,10 @@ #include "static-destruct.h" #include "string-table.h" #include "string-util.h" +#include "terminal-util.h" #include "udev-util.h" -#include "udevadm-util.h" #include "udevadm.h" +#include "udevadm-util.h" typedef enum ActionType { ACTION_QUERY, @@ -171,26 +172,72 @@ static int print_device_chain(sd_device *device) { } static int print_record(sd_device *device) { - const char *str, *val; - int i; + const char *str, *val, *subsys; + dev_t devnum; + uint64_t q; + int i, ifi; assert(device); - (void) sd_device_get_devpath(device, &str); - printf("P: %s\n", str); + /* We don't show syspath here, because it's identical to devpath (modulo the "/sys" prefix). + * + * We don't show action/seqnum here because that only makes sense for records synthesized from + * uevents, not for those synthesized from database entries. + * + * We don't show sysattrs here, because they can be expensive and potentially issue expensive driver + * IO. + * + * Coloring: let's be conservative with coloring. Let's use it to group related fields. Right now: + * + * • white for fields that give the device a name + * • green for fields that categorize the device into subsystem/devtype and similar + * • cyan for fields about associated device nodes/symlinks/network interfaces and such + * • magenta for block device diskseq + * • yellow for driver info + * • no color for regular properties */ + + assert_se(sd_device_get_devpath(device, &str) >= 0); + printf("P: %s%s%s\n", ansi_highlight_white(), str, ansi_normal()); + + if (sd_device_get_sysname(device, &str) >= 0) + printf("M: %s%s%s\n", ansi_highlight_white(), str, ansi_normal()); + + if (sd_device_get_sysnum(device, &str) >= 0) + printf("R: %s%s%s\n", ansi_highlight_white(), str, ansi_normal()); + + if (sd_device_get_subsystem(device, &subsys) >= 0) + printf("U: %s%s%s\n", ansi_highlight_green(), subsys, ansi_normal()); + + if (sd_device_get_devtype(device, &str) >= 0) + printf("T: %s%s%s\n", ansi_highlight_green(), str, ansi_normal()); + + if (sd_device_get_devnum(device, &devnum) >= 0) + printf("D: %s%c %u:%u%s\n", + ansi_highlight_cyan(), + streq_ptr(subsys, "block") ? 'b' : 'c', major(devnum), minor(devnum), + ansi_normal()); + + if (sd_device_get_ifindex(device, &ifi) >= 0) + printf("I: %s%i%s\n", ansi_highlight_cyan(), ifi, ansi_normal()); if (sd_device_get_devname(device, &str) >= 0) { assert_se(val = path_startswith(str, "/dev/")); - printf("N: %s\n", val); + printf("N: %s%s%s\n", ansi_highlight_cyan(), val, ansi_normal()); + + if (device_get_devlink_priority(device, &i) >= 0) + printf("L: %s%i%s\n", ansi_highlight_cyan(), i, ansi_normal()); + + FOREACH_DEVICE_DEVLINK(device, str) { + assert_se(val = path_startswith(str, "/dev/")); + printf("S: %s%s%s\n", ansi_highlight_cyan(), val, ansi_normal()); + } } - if (device_get_devlink_priority(device, &i) >= 0) - printf("L: %i\n", i); + if (sd_device_get_diskseq(device, &q) >= 0) + printf("Q: %s%" PRIu64 "%s\n", ansi_highlight_magenta(), q, ansi_normal()); - FOREACH_DEVICE_DEVLINK(device, str) { - assert_se(val = path_startswith(str, "/dev/")); - printf("S: %s\n", val); - } + if (sd_device_get_driver(device, &str) >= 0) + printf("V: %s%s%s\n", ansi_highlight_yellow4(), str, ansi_normal()); FOREACH_DEVICE_PROPERTY(device, str, val) printf("E: %s=%s\n", str, val); @@ -442,7 +489,7 @@ static int help(void) { int info_main(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **devices = NULL; _cleanup_free_ char *name = NULL; - int c, r; + int c, r, ret; enum { ARG_PROPERTY = 0x100, @@ -584,14 +631,21 @@ 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"); + ret = 0; 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 (r < 0) { + if (r == -EINVAL) + log_error_errno(r, "Bad argument \"%s\", expected an absolute path in /dev/ or /sys/ or a unit name: %m", *p); + else + log_error_errno(r, "Unknown device \"%s\": %m", *p); + + if (ret == 0) + ret = r; + continue; + } if (arg_wait_for_initialization_timeout > 0) { sd_device *d; @@ -618,5 +672,5 @@ int info_main(int argc, char *argv[], void *userdata) { return r; } - return 0; + return ret; }