diff options
Diffstat (limited to 'src/udev')
29 files changed, 619 insertions, 370 deletions
diff --git a/src/udev/Makefile.am b/src/udev/Makefile.am index f9af997ffe..652cb67006 100644 --- a/src/udev/Makefile.am +++ b/src/udev/Makefile.am @@ -34,7 +34,10 @@ udevadm_SOURCES = \ udevadm-settle.c \ udevadm-trigger.c \ udevadm-test.c \ - udevadm-test-builtin.c + udevadm-test-builtin.c \ + udevadm-util.c \ + udevadm-util.h + udevadm_LDADD = \ libudev-core.la diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c index f97f516462..93563d867b 100644 --- a/src/udev/udev-builtin-blkid.c +++ b/src/udev/udev-builtin-blkid.c @@ -138,6 +138,7 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t blkid_probe pr; const char *data; const char *name; + const char *prtype = NULL; int nvals; int i; int err = 0; @@ -172,7 +173,8 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | - BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); + BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION | + BLKID_SUBLKS_BADCSUM); if (noraid) blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); @@ -194,6 +196,15 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t err = probe_superblocks(pr); if (err < 0) goto out; + if (blkid_probe_has_value(pr, "SBBADCSUM")) { + if (!blkid_probe_lookup_value(pr, "TYPE", &prtype, NULL)) + log_warning("incorrect %s checksum on %s", + prtype, udev_device_get_devnode(dev)); + else + log_warning("incorrect checksum on %s", + udev_device_get_devnode(dev)); + goto out; + } nvals = blkid_probe_numof_values(pr); for (i = 0; i < nvals; i++) { @@ -214,6 +225,6 @@ out: const struct udev_builtin udev_builtin_blkid = { .name = "blkid", .cmd = builtin_blkid, - .help = "filesystem and partition probing", + .help = "Filesystem and partition probing", .run_once = true, }; diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c index 2e2112fd92..3643596a70 100644 --- a/src/udev/udev-builtin-btrfs.c +++ b/src/udev/udev-builtin-btrfs.c @@ -24,6 +24,7 @@ #include <fcntl.h> #include <errno.h> #include <sys/ioctl.h> + #ifdef HAVE_LINUX_BTRFS_H #include <linux/btrfs.h> #endif @@ -32,7 +33,7 @@ #include "udev.h" static int builtin_btrfs(struct udev_device *dev, int argc, char *argv[], bool test) { - struct btrfs_ioctl_vol_args args; + struct btrfs_ioctl_vol_args args = {}; _cleanup_close_ int fd = -1; int err; @@ -48,7 +49,7 @@ static int builtin_btrfs(struct udev_device *dev, int argc, char *argv[], bool t if (err < 0) return EXIT_FAILURE; - udev_builtin_add_property(dev, test, "ID_BTRFS_READY", err == 0 ? "1" : "0"); + udev_builtin_add_property(dev, test, "ID_BTRFS_READY", one_zero(err == 0)); return EXIT_SUCCESS; } diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c index 695a31a12f..1eddf86b61 100644 --- a/src/udev/udev-builtin-hwdb.c +++ b/src/udev/udev-builtin-hwdb.c @@ -214,5 +214,5 @@ const struct udev_builtin udev_builtin_hwdb = { .init = builtin_hwdb_init, .exit = builtin_hwdb_exit, .validate = builtin_hwdb_validate, - .help = "hardware database", + .help = "Hardware database", }; diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c index 1a1121ef94..26c723225d 100644 --- a/src/udev/udev-builtin-input_id.c +++ b/src/udev/udev-builtin-input_id.c @@ -1,9 +1,11 @@ /* - * compose persistent device path + * expose input properties via udev * * Copyright (C) 2009 Martin Pitt <martin.pitt@ubuntu.com> * Portions Copyright (C) 2004 David Zeuthen, <david@fubar.dk> * Copyright (C) 2011 Kay Sievers <kay@vrfy.org> + * Copyright (C) 2014 Carlos Garnacho <carlosg@gnome.org> + * Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +31,7 @@ #include <linux/input.h> #include "udev.h" +#include "util.h" /* we must use this kernel-compatible implementation */ #define BITS_PER_LONG (sizeof(unsigned long) * 8) @@ -38,6 +41,34 @@ #define LONG(x) ((x)/BITS_PER_LONG) #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) +static inline int abs_size_mm(const struct input_absinfo *absinfo) { + /* Resolution is defined to be in units/mm for ABS_X/Y */ + return (absinfo->maximum - absinfo->minimum) / absinfo->resolution; +} + +static void extract_info(struct udev_device *dev, const char *devpath, bool test) { + char width[DECIMAL_STR_MAX(int)], height[DECIMAL_STR_MAX(int)]; + struct input_absinfo xabsinfo = {}, yabsinfo = {}; + _cleanup_close_ int fd = -1; + + fd = open(devpath, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return; + + if (ioctl(fd, EVIOCGABS(ABS_X), &xabsinfo) < 0 || + ioctl(fd, EVIOCGABS(ABS_Y), &yabsinfo) < 0) + return; + + if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0) + return; + + snprintf(width, sizeof(width), "%d", abs_size_mm(&xabsinfo)); + snprintf(height, sizeof(height), "%d", abs_size_mm(&yabsinfo)); + + udev_builtin_add_property(dev, test, "ID_INPUT_WIDTH_MM", width); + udev_builtin_add_property(dev, test, "ID_INPUT_HEIGHT_MM", height); +} + /* * Read a capability attribute and return bitmask. * @param dev udev_device @@ -48,12 +79,17 @@ static void get_cap_mask(struct udev_device *dev, struct udev_device *pdev, const char* attr, unsigned long *bitmask, size_t bitmask_size, bool test) { + const char *v; char text[4096]; unsigned i; char* word; unsigned long val; - snprintf(text, sizeof(text), "%s", udev_device_get_sysattr_value(pdev, attr)); + v = udev_device_get_sysattr_value(pdev, attr); + if (!v) + v = ""; + + snprintf(text, sizeof(text), "%s", v); log_debug("%s raw kernel attribute: %s", attr, text); memzero(bitmask, bitmask_size); @@ -196,6 +232,7 @@ static int builtin_input_id(struct udev_device *dev, int argc, char *argv[], boo unsigned long bitmask_abs[NBITS(ABS_MAX)]; unsigned long bitmask_key[NBITS(KEY_MAX)]; unsigned long bitmask_rel[NBITS(REL_MAX)]; + const char *sysname, *devnode; /* walk up the parental chain until we find the real input device; the * argument is very likely a subdevice of this, like eventN */ @@ -203,24 +240,28 @@ static int builtin_input_id(struct udev_device *dev, int argc, char *argv[], boo while (pdev != NULL && udev_device_get_sysattr_value(pdev, "capabilities/ev") == NULL) pdev = udev_device_get_parent_with_subsystem_devtype(pdev, "input", NULL); - /* not an "input" class device */ - if (pdev == NULL) - return EXIT_SUCCESS; - - /* Use this as a flag that input devices were detected, so that this - * program doesn't need to be called more than once per device */ - udev_builtin_add_property(dev, test, "ID_INPUT", "1"); - get_cap_mask(dev, pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), test); - get_cap_mask(dev, pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), test); - get_cap_mask(dev, pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), test); - get_cap_mask(dev, pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test); - test_pointers(dev, bitmask_ev, bitmask_abs, bitmask_key, bitmask_rel, test); - test_key(dev, bitmask_ev, bitmask_key, test); + if (pdev) { + /* Use this as a flag that input devices were detected, so that this + * program doesn't need to be called more than once per device */ + udev_builtin_add_property(dev, test, "ID_INPUT", "1"); + get_cap_mask(dev, pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), test); + get_cap_mask(dev, pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), test); + get_cap_mask(dev, pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), test); + get_cap_mask(dev, pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test); + test_pointers(dev, bitmask_ev, bitmask_abs, bitmask_key, bitmask_rel, test); + test_key(dev, bitmask_ev, bitmask_key, test); + } + + devnode = udev_device_get_devnode(dev); + sysname = udev_device_get_sysname(dev); + if (devnode && sysname && startswith(sysname, "event")) + extract_info(dev, devnode, test); + return EXIT_SUCCESS; } const struct udev_builtin udev_builtin_input_id = { .name = "input_id", .cmd = builtin_input_id, - .help = "input device properties", + .help = "Input device properties", }; diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c index d6b7dbbac0..118e797c96 100644 --- a/src/udev/udev-builtin-keyboard.c +++ b/src/udev/udev-builtin-keyboard.c @@ -62,7 +62,7 @@ static int install_force_release(struct udev_device *dev, const unsigned int *re log_debug("keyboard: updating force-release list with '%s'", codes); ret = udev_device_set_sysattr_value(atkbd, "force_release", codes); if (ret < 0) - log_error("Error writing force-release attribute: %s", strerror(-ret)); + log_error_errno(ret, "Error writing force-release attribute: %m"); return ret; } @@ -140,7 +140,7 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo fd = open(udev_device_get_devnode(dev), O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (fd < 0) { - log_error("Error, opening device '%s': %m", node); + log_error_errno(errno, "Error, opening device '%s': %m", node); return EXIT_FAILURE; } @@ -149,7 +149,7 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo log_debug("keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)", map[i].scan, map[i].scan, map[i].key, map[i].key); if (ioctl(fd, EVIOCSKEYCODE, &map[i]) < 0) - log_error("Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", node, map[i].scan, map[i].key); + log_error_errno(errno, "Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", node, map[i].scan, map[i].key); } /* install list of force-release codes */ @@ -165,5 +165,5 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo const struct udev_builtin udev_builtin_keyboard = { .name = "keyboard", .cmd = builtin_keyboard, - .help = "keyboard scan code to key mapping", + .help = "Keyboard scan code to key mapping", }; diff --git a/src/udev/udev-builtin-kmod.c b/src/udev/udev-builtin-kmod.c index b83fd523d9..f39b01a452 100644 --- a/src/udev/udev-builtin-kmod.c +++ b/src/udev/udev-builtin-kmod.c @@ -34,7 +34,7 @@ #include "udev.h" -static struct kmod_ctx *ctx; +static struct kmod_ctx *ctx = NULL; static int load_module(struct udev *udev, const char *alias) { int err; @@ -47,18 +47,18 @@ static int load_module(struct udev *udev, const char *alias) { return err; if (list == NULL) - log_debug("no module matches '%s'", alias); + log_debug("No module matches '%s'", alias); kmod_list_foreach(l, list) { struct kmod_module *mod = kmod_module_get_module(l); err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); if (err == KMOD_PROBE_APPLY_BLACKLIST) - log_debug("module '%s' is blacklisted", kmod_module_get_name(mod)); + log_debug("Module '%s' is blacklisted", kmod_module_get_name(mod)); else if (err == 0) - log_debug("inserted '%s'", kmod_module_get_name(mod)); + log_debug("Inserted '%s'", kmod_module_get_name(mod)); else - log_debug("failed to insert '%s'", kmod_module_get_name(mod)); + log_debug("Failed to insert '%s'", kmod_module_get_name(mod)); kmod_module_unref(mod); } @@ -85,10 +85,8 @@ static int load_module(struct udev *udev, const char *alias) { return err; } -_printf_(6,0) -static void udev_kmod_log(void *data, int priority, const char *file, int line, - const char *fn, const char *format, va_list args) { - udev_main_log(data, priority, file, line, fn, format, args); +_printf_(6,0) static void udev_kmod_log(void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) { + log_internalv(priority, 0, file, line, fn, format, args); } static int builtin_kmod(struct udev_device *dev, int argc, char *argv[], bool test) { @@ -106,7 +104,7 @@ static int builtin_kmod(struct udev_device *dev, int argc, char *argv[], bool te } for (i = 2; argv[i]; i++) { - log_debug("execute '%s' '%s'", argv[1], argv[i]); + log_debug("Execute '%s' '%s'", argv[1], argv[i]); load_module(udev, argv[i]); } @@ -123,7 +121,7 @@ static int builtin_kmod_init(struct udev *udev) { if (!ctx) return -ENOMEM; - log_debug("load module index"); + log_debug("Load module index"); kmod_set_log_fn(ctx, udev_kmod_log, udev); kmod_load_resources(ctx); #endif @@ -133,7 +131,7 @@ static int builtin_kmod_init(struct udev *udev) { /* called on udev shutdown and reload request */ static void builtin_kmod_exit(struct udev *udev) { #ifdef HAVE_LIBKMOD - log_debug("unload module index"); + log_debug("Unload module index"); ctx = kmod_unref(ctx); #endif } @@ -141,7 +139,7 @@ static void builtin_kmod_exit(struct udev *udev) { #ifdef HAVE_LIBKMOD /* called every couple of seconds during event activity; 'true' if config has changed */ static bool builtin_kmod_validate(struct udev *udev) { - log_debug("validate module index"); + log_debug("Validate module index"); if (!ctx) return false; return (kmod_validate_resources(ctx) != KMOD_RESOURCES_OK); @@ -156,6 +154,6 @@ const struct udev_builtin udev_builtin_kmod = { #ifdef HAVE_LIBKMOD .validate = builtin_kmod_validate, #endif - .help = "kernel module loader", + .help = "Kernel module loader", .run_once = false, }; diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index 4731a860b0..5f350abd68 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -307,7 +307,7 @@ static int names_usb(struct udev_device *dev, struct netnames *names) { s[0] = '\0'; interf = s+1; - /* prefix every port number in the chain with "u"*/ + /* prefix every port number in the chain with "u" */ s = ports; while ((s = strchr(s, '.'))) s[0] = 'u'; @@ -562,5 +562,5 @@ out: const struct udev_builtin udev_builtin_net_id = { .name = "net_id", .cmd = builtin_net_id, - .help = "network device properties", + .help = "Network device properties", }; diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index 0d247f6b5a..b6749aab76 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -118,7 +118,7 @@ out: return parent; } -static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path) { +static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent, char **path) { struct udev *udev = udev_device_get_udev(parent); struct udev_device *targetdev; struct udev_device *target_parent; @@ -154,6 +154,100 @@ out: return parent; } +static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path) +{ + struct udev *udev = udev_device_get_udev(parent); + struct udev_device *targetdev; + struct udev_device *target_parent; + struct udev_device *port; + struct udev_device *expander; + struct udev_device *target_sasdev = NULL; + struct udev_device *expander_sasdev = NULL; + struct udev_device *port_sasdev = NULL; + const char *sas_address = NULL; + const char *phy_id; + const char *phy_count; + char *lun = NULL; + + targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); + if (targetdev == NULL) + return NULL; + + target_parent = udev_device_get_parent(targetdev); + if (target_parent == NULL) + return NULL; + + /* Get sas device */ + target_sasdev = udev_device_new_from_subsystem_sysname(udev, + "sas_device", udev_device_get_sysname(target_parent)); + if (target_sasdev == NULL) + return NULL; + + /* The next parent is sas port */ + port = udev_device_get_parent(target_parent); + if (port == NULL) { + parent = NULL; + goto out; + } + + /* Get port device */ + port_sasdev = udev_device_new_from_subsystem_sysname(udev, + "sas_port", udev_device_get_sysname(port)); + + phy_count = udev_device_get_sysattr_value(port_sasdev, "num_phys"); + if (phy_count == NULL) { + parent = NULL; + goto out; + } + + /* Check if we are simple disk */ + if (strncmp(phy_count, "1", 2) != 0) { + parent = handle_scsi_sas_wide_port(parent, path); + goto out; + } + + /* Get connected phy */ + phy_id = udev_device_get_sysattr_value(target_sasdev, "phy_identifier"); + if (phy_id == NULL) { + parent = NULL; + goto out; + } + + /* The port's parent is either hba or expander */ + expander = udev_device_get_parent(port); + if (expander == NULL) { + parent = NULL; + goto out; + } + + /* Get expander device */ + expander_sasdev = udev_device_new_from_subsystem_sysname(udev, + "sas_device", udev_device_get_sysname(expander)); + if (expander_sasdev != NULL) { + /* Get expander's address */ + sas_address = udev_device_get_sysattr_value(expander_sasdev, + "sas_address"); + if (sas_address == NULL) { + parent = NULL; + goto out; + } + } + + format_lun_number(parent, &lun); + if (sas_address) + path_prepend(path, "sas-exp%s-phy%s-%s", sas_address, phy_id, lun); + else + path_prepend(path, "sas-phy%s-%s", phy_id, lun); + + if (lun) + free(lun); +out: + udev_device_unref(target_sasdev); + udev_device_unref(expander_sasdev); + udev_device_unref(port_sasdev); + return parent; +} + static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) { struct udev *udev = udev_device_get_udev(parent); struct udev_device *transportdev; @@ -548,9 +642,9 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool } /* - * Do return devices with have an unknown type of parent device, they - * might produce conflicting IDs below multiple independent parent - * devices. + * Do not return devices with an unknown parent device type. They + * might produce conflicting IDs if the parent does not provide a + * unique and predictable name. */ if (!supported_parent) { free(path); @@ -558,9 +652,9 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool } /* - * Do not return a have-only a single-parent block devices, some - * have entire hidden buses behind it, and not create predictable - * IDs that way. + * Do not return block devices without a well-known transport. Some + * devices do not expose their buses and do not provide a unique + * and predictable name that way. */ if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport) { free(path); @@ -609,6 +703,6 @@ out: const struct udev_builtin udev_builtin_path_id = { .name = "path_id", .cmd = builtin_path_id, - .help = "compose persistent device path", + .help = "Compose persistent device path", .run_once = true, }; diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c index 06d4191584..ab0d96e377 100644 --- a/src/udev/udev-builtin-usb_id.c +++ b/src/udev/udev-builtin-usb_id.c @@ -471,6 +471,6 @@ fallback: const struct udev_builtin udev_builtin_usb_id = { .name = "usb_id", .cmd = builtin_usb_id, - .help = "usb device properties", + .help = "USB device properties", .run_once = true, }; diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c index 70b7ab4332..e4440a6e99 100644 --- a/src/udev/udev-builtin.c +++ b/src/udev/udev-builtin.c @@ -86,7 +86,7 @@ void udev_builtin_list(struct udev *udev) { unsigned int i; for (i = 0; i < ELEMENTSOF(builtins); i++) - fprintf(stderr, " %-12s %s\n", builtins[i]->name, builtins[i]->help); + fprintf(stderr, " %-14s %s\n", builtins[i]->name, builtins[i]->help); } const char *udev_builtin_name(enum udev_builtin_cmd cmd) { diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index 2fdf4561a9..898ef54514 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -85,7 +85,7 @@ struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd) { if (fd < 0) { uctrl->sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); if (uctrl->sock < 0) { - log_error("error getting socket: %m"); + log_error_errno(errno, "error getting socket: %m"); udev_ctrl_unref(uctrl); return NULL; } @@ -95,7 +95,7 @@ struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd) { } r = setsockopt(uctrl->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); if (r < 0) - log_warning("could not set SO_PASSCRED: %m"); + log_warning_errno(errno, "could not set SO_PASSCRED: %m"); uctrl->saddr.sun_family = AF_LOCAL; strscpy(uctrl->saddr.sun_path, sizeof(uctrl->saddr.sun_path), "/run/udev/control"); @@ -119,14 +119,14 @@ int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) { if (err < 0) { err = -errno; - log_error("bind failed: %m"); + log_error_errno(errno, "bind failed: %m"); return err; } err = listen(uctrl->sock, 0); if (err < 0) { err = -errno; - log_error("listen failed: %m"); + log_error_errno(errno, "listen failed: %m"); return err; } @@ -209,14 +209,14 @@ struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) { if (conn->sock < 0) { if (errno != EINTR) - log_error("unable to receive ctrl connection: %m"); + log_error_errno(errno, "unable to receive ctrl connection: %m"); goto err; } /* check peer credential of connection */ r = getpeercred(conn->sock, &ucred); if (r < 0) { - log_error("unable to receive credentials of ctrl connection: %s", strerror(-r)); + log_error_errno(r, "unable to receive credentials of ctrl connection: %m"); goto err; } if (ucred.uid > 0) { @@ -227,7 +227,7 @@ struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) { /* enable receiving of the sender credentials in the messages */ r = setsockopt(conn->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); if (r < 0) - log_warning("could not set SO_PASSCRED: %m"); + log_warning_errno(errno, "could not set SO_PASSCRED: %m"); udev_ctrl_ref(uctrl); return conn; @@ -383,7 +383,7 @@ struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) { goto err; } else { if (!(pfd[0].revents & POLLIN)) { - log_error("ctrl connection error: %m"); + log_error_errno(errno, "ctrl connection error: %m"); goto err; } } @@ -396,7 +396,7 @@ struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) { size = recvmsg(conn->sock, &smsg, 0); if (size < 0) { - log_error("unable to receive ctrl message: %m"); + log_error_errno(errno, "unable to receive ctrl message: %m"); goto err; } cmsg = CMSG_FIRSTHDR(&smsg); diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index e86f9cb059..5c1352b1b9 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -388,7 +388,7 @@ static int spawn_exec(struct udev_event *event, if (fd_stderr < 0) dup2(fd, STDERR_FILENO); } else - log_error("open /dev/null failed: %m"); + log_error_errno(errno, "open /dev/null failed: %m"); /* connect pipes to std{out,err} */ if (fd_stdout >= 0) { @@ -410,7 +410,7 @@ static int spawn_exec(struct udev_event *event, execve(argv[0], argv, envp); /* exec failed */ - log_error("failed to execute '%s' '%s': %m", argv[0], cmd); + log_error_errno(errno, "failed to execute '%s' '%s': %m", argv[0], cmd); return -errno; } @@ -438,14 +438,14 @@ static void spawn_read(struct udev_event *event, fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { - log_error("error creating epoll fd: %m"); + log_error_errno(errno, "error creating epoll fd: %m"); return; } if (fd_stdout >= 0) { r = epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stdout, &ep_outpipe); if (r < 0) { - log_error("fail to add stdout fd to epoll: %m"); + log_error_errno(errno, "fail to add stdout fd to epoll: %m"); return; } } @@ -453,7 +453,7 @@ static void spawn_read(struct udev_event *event, if (fd_stderr >= 0) { r = epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stderr, &ep_errpipe); if (r < 0) { - log_error("fail to add stderr fd to epoll: %m"); + log_error_errno(errno, "fail to add stderr fd to epoll: %m"); return; } } @@ -482,7 +482,7 @@ static void spawn_read(struct udev_event *event, if (fdcount < 0) { if (errno == EINTR) continue; - log_error("failed to poll: %m"); + log_error_errno(errno, "failed to poll: %m"); return; } else if (fdcount == 0) { log_error("timeout '%s'", cmd); @@ -528,7 +528,7 @@ static void spawn_read(struct udev_event *event, } else if (ev[i].events & EPOLLHUP) { r = epoll_ctl(fd_ep, EPOLL_CTL_DEL, *fd, NULL); if (r < 0) { - log_error("failed to remove fd from epoll: %m"); + log_error_errno(errno, "failed to remove fd from epoll: %m"); return; } *fd = -1; @@ -577,7 +577,7 @@ static int spawn_wait(struct udev_event *event, if (errno == EINTR) continue; err = -errno; - log_error("failed to poll: %m"); + log_error_errno(errno, "failed to poll: %m"); goto out; } if (fdcount == 0) { @@ -588,7 +588,7 @@ static int spawn_wait(struct udev_event *event, if (errno == EINTR) continue; err = -errno; - log_error("failed to poll: %m"); + log_error_errno(errno, "failed to poll: %m"); goto out; } if (fdcount == 0) { @@ -677,7 +677,6 @@ int udev_event_spawn(struct udev_event *event, usec_t timeout_warn_usec, const char *cmd, char **envp, const sigset_t *sigmask, char *result, size_t ressize) { - struct udev *udev = event->udev; int outpipe[2] = {-1, -1}; int errpipe[2] = {-1, -1}; pid_t pid; @@ -690,17 +689,17 @@ int udev_event_spawn(struct udev_event *event, udev_build_argv(event->udev, arg, NULL, argv); /* pipes from child to parent */ - if (result != NULL || udev_get_log_priority(udev) >= LOG_INFO) { + if (result != NULL || log_get_max_level() >= LOG_INFO) { if (pipe2(outpipe, O_NONBLOCK) != 0) { err = -errno; - log_error("pipe failed: %m"); + log_error_errno(errno, "pipe failed: %m"); goto out; } } - if (udev_get_log_priority(udev) >= LOG_INFO) { + if (log_get_max_level() >= LOG_INFO) { if (pipe2(errpipe, O_NONBLOCK) != 0) { err = -errno; - log_error("pipe failed: %m"); + log_error_errno(errno, "pipe failed: %m"); goto out; } } @@ -737,7 +736,7 @@ int udev_event_spawn(struct udev_event *event, _exit(2 ); case -1: - log_error("fork of '%s' failed: %m", cmd); + log_error_errno(errno, "fork of '%s' failed: %m", cmd); err = -1; goto out; default: @@ -785,7 +784,7 @@ static int rename_netif_dev_fromname_toname(struct udev_device *dev,const char * sk = socket(PF_INET, SOCK_DGRAM, 0); if (sk < 0) { err = -errno; - log_error("error opening socket: %m\n"); + log_error("error opening socket: %m"); return err; } @@ -799,11 +798,11 @@ static int rename_netif_dev_fromname_toname(struct udev_device *dev,const char * int loop; if (err == 0) { - log_info("renamed network interface %s to %s\n", ifr.ifr_name, ifr.ifr_newname); + log_info("renamed network interface %s to %s", ifr.ifr_name, ifr.ifr_newname); goto out; } /* keep trying if the destination interface name already exists */ - log_debug("collision on rename of network interface %s to %s , retrying until timeout\n", + log_debug("collision on rename of network interface %s to %s , retrying until timeout", ifr.ifr_name, ifr.ifr_newname); err = -errno; @@ -819,7 +818,7 @@ static int rename_netif_dev_fromname_toname(struct udev_device *dev,const char * err = ioctl(sk, SIOCSIFNAME, &ifr); if (err == 0) { - log_info("renamed network interface %s to %s\n", ifr.ifr_name, ifr.ifr_newname); + log_info("renamed network interface %s to %s", ifr.ifr_name, ifr.ifr_newname); break; } err = -errno; @@ -829,13 +828,13 @@ static int rename_netif_dev_fromname_toname(struct udev_device *dev,const char * out: if (err < 0) - log_error("error changing net interface name %s to %s: %m\n", ifr.ifr_name, ifr.ifr_newname); + log_error("error changing net interface name %s to %s: %m", ifr.ifr_name, ifr.ifr_newname); #else if (err >= 0) { - log_info("renamed network interface %s to %s\n", ifr.ifr_name, ifr.ifr_newname); + log_info("renamed network interface %s to %s", ifr.ifr_name, ifr.ifr_newname); } else { err = -errno; - log_error("error changing net interface name %s to %s: %m\n", ifr.ifr_name, ifr.ifr_newname); + log_error("error changing net interface name %s to %s: %m", ifr.ifr_name, ifr.ifr_newname); } #endif @@ -848,9 +847,10 @@ static int rename_netif(struct udev_event *event) { } void udev_event_execute_rules(struct udev_event *event, - usec_t timeout_usec, - usec_t timeout_warn_usec, - struct udev_rules *rules, const sigset_t *sigmask) { + usec_t timeout_usec, usec_t timeout_warn_usec, + struct udev_list *properties_list, + struct udev_rules *rules, + const sigset_t *sigmask) { struct udev_device *dev = event->dev; if (udev_device_get_subsystem(dev) == NULL) @@ -864,7 +864,10 @@ void udev_event_execute_rules(struct udev_event *event, if (major(udev_device_get_devnum(dev)) != 0) udev_watch_end(event->udev, dev); - udev_rules_apply_to_event(rules, event, timeout_usec, timeout_warn_usec, sigmask); + udev_rules_apply_to_event(rules, event, + timeout_usec, timeout_warn_usec, + properties_list, + sigmask); if (major(udev_device_get_devnum(dev)) != 0) udev_node_remove(dev); @@ -898,7 +901,10 @@ void udev_event_execute_rules(struct udev_event *event, } } - udev_rules_apply_to_event(rules, event, timeout_usec, timeout_warn_usec, sigmask); + udev_rules_apply_to_event(rules, event, + timeout_usec, timeout_warn_usec, + properties_list, + sigmask); /* rename a new network interface, if needed */ @@ -955,9 +961,9 @@ void udev_event_execute_rules(struct udev_event *event, r = rename_netif_dev_fromname_toname(dev,udev_device_get_sysname(dev),newifname); if (r == 0) { finalifname = newifname; - log_debug("renamed netif to '%s' for collision avoidance\n", newifname); + log_debug("renamed netif to '%s' for collision avoidance", newifname); } else { - log_error("could not rename netif to '%s' for collision avoidance\n",newifname); + log_error("could not rename netif to '%s' for collision avoidance",newifname); } } /* rename it now to its final target if its not already there */ diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index 4ac6f71490..c30a428ea1 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -112,12 +112,12 @@ static int node_symlink(struct udev_device *dev, const char *node, const char *s mac_selinux_create_file_clear(); } while (err == -ENOENT); if (err != 0) { - log_error("symlink '%s' '%s' failed: %m", target, slink_tmp); + log_error_errno(errno, "symlink '%s' '%s' failed: %m", target, slink_tmp); goto exit; } err = rename(slink_tmp, slink); if (err != 0) { - log_error("rename '%s' '%s' failed: %m", slink_tmp, slink); + log_error_errno(errno, "rename '%s' '%s' failed: %m", slink_tmp, slink); unlink(slink_tmp); } exit: @@ -264,7 +264,7 @@ static int node_permissions_apply(struct udev_device *dev, bool apply, if (lstat(devnode, &stats) != 0) { err = -errno; - log_debug("can not stat() node '%s' (%m)", devnode); + log_debug_errno(errno, "can not stat() node '%s' (%m)", devnode); goto out; } @@ -283,10 +283,10 @@ static int node_permissions_apply(struct udev_device *dev, bool apply, log_debug("set permissions %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid); err = chmod(devnode, mode); if (err < 0) - log_warning("setting mode of %s to %#o failed: %m", devnode, mode); + log_warning_errno(errno, "setting mode of %s to %#o failed: %m", devnode, mode); err = chown(devnode, uid, gid); if (err < 0) - log_warning("setting owner of %s to uid=%u, gid=%u failed: %m", devnode, uid, gid); + log_warning_errno(errno, "setting owner of %s to uid=%u, gid=%u failed: %m", devnode, uid, gid); } else { log_debug("preserve permissions %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid); } @@ -304,7 +304,7 @@ static int node_permissions_apply(struct udev_device *dev, bool apply, r = mac_selinux_apply(devnode, label); if (r < 0) - log_error("SECLABEL: failed to set SELinux label '%s': %s", label, strerror(-r)); + log_error_errno(r, "SECLABEL: failed to set SELinux label '%s': %m", label); else log_debug("SECLABEL: set SELinux label '%s'", label); @@ -313,7 +313,7 @@ static int node_permissions_apply(struct udev_device *dev, bool apply, r = mac_smack_apply(devnode, label); if (r < 0) - log_error("SECLABEL: failed to set SMACK label '%s': %s", label, strerror(-r)); + log_error_errno(r, "SECLABEL: failed to set SMACK label '%s': %m", label); else log_debug("SECLABEL: set SMACK label '%s'", label); @@ -323,7 +323,7 @@ static int node_permissions_apply(struct udev_device *dev, bool apply, /* set the defaults */ if (!selinux) - label_fix(devnode, true, false); + mac_selinux_fix(devnode, true, false); if (!smack) mac_smack_apply(devnode, NULL); } diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index b8fc35e11a..f51691143b 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -479,9 +479,9 @@ static uid_t add_uid(struct udev_rules *rules, const char *owner) { r = get_user_creds(&owner, &uid, NULL, NULL, NULL); if (r < 0) { if (r == -ENOENT || r == -ESRCH) - udev_err(rules->udev, "specified user '%s' unknown\n", owner); + log_error("specified user '%s' unknown", owner); else - udev_err(rules->udev, "error resolving user '%s': %s\n", owner, strerror(-r)); + log_error_errno(r, "error resolving user '%s': %m", owner); } /* grow buffer if needed */ @@ -526,9 +526,9 @@ static gid_t add_gid(struct udev_rules *rules, const char *group) { r = get_group_creds(&group, &gid); if (r < 0) { if (r == -ENOENT || r == -ESRCH) - udev_err(rules->udev, "specified group '%s' unknown\n", group); + log_error("specified group '%s' unknown", group); else - udev_err(rules->udev, "error resolving group '%s': %s\n", group, strerror(-r)); + log_error_errno(r, "error resolving group '%s': %m", group); } /* grow buffer if needed */ @@ -1047,11 +1047,11 @@ static int add_rule(struct udev_rules *rules, char *line, const char *filename, unsigned int filename_off, unsigned int lineno) { char *linepos; const char *attr; - struct rule_tmp rule_tmp; + struct rule_tmp rule_tmp = { + .rules = rules, + .rule.type = TK_RULE, + }; - memzero(&rule_tmp, sizeof(struct rule_tmp)); - rule_tmp.rules = rules; - rule_tmp.rule.type = TK_RULE; /* the offset in the rule is limited to unsigned short */ if (filename_off < USHRT_MAX) rule_tmp.rule.rule.filename_off = filename_off; @@ -1072,14 +1072,14 @@ static int add_rule(struct udev_rules *rules, char *line, /* If we aren't at the end of the line, this is a parsing error. * Make a best effort to describe where the problem is. */ - if (*linepos != '\n') { - char buf[2] = {linepos[1]}; + if (!strchr(NEWLINE, *linepos)) { + char buf[2] = {*linepos}; _cleanup_free_ char *tmp; tmp = cescape(buf); - log_error("invalid key/value pair in file %s on line %u, starting at character %tu ('%s')\n", + log_error("invalid key/value pair in file %s on line %u, starting at character %tu ('%s')", filename, lineno, linepos - line + 1, tmp); - if (linepos[1] == '#') + if (*linepos == '#') log_error("hint: comments can only start at beginning of line"); } break; @@ -1420,12 +1420,12 @@ static int add_rule(struct udev_rules *rules, char *line, } else { if (streq(value, "%k")) { log_error("NAME=\"%%k\" is ignored, because it breaks kernel supplied names, " - "please remove it from %s:%u\n", filename, lineno); + "please remove it from %s:%u", filename, lineno); continue; } if (value[0] == '\0') { log_debug("NAME=\"\" is ignored, because udev will not delete any device nodes, " - "please remove it from %s:%u\n", filename, lineno); + "please remove it from %s:%u", filename, lineno); continue; } rule_add_key(&rule_tmp, TK_A_NAME, op, value, NULL); @@ -1690,7 +1690,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) { r = conf_files_list_strv(&files, ".rules", NULL, rules_dirs); if (r < 0) { - log_error("failed to enumerate rules files: %s", strerror(-r)); + log_error_errno(r, "failed to enumerate rules files: %m"); return udev_rules_unref(rules); } @@ -1916,9 +1916,9 @@ int udev_rules_assigning_name_to(struct udev_rules *rules, const char *match_nam strscpy(name_str,UTIL_PATH_SIZE,name); count = util_replace_chars(name_str, "/"); if (count > 0) - log_debug("%i character(s) replaced\n", count); + log_debug("%i character(s) replaced", count); if (streq(name_str,match_name)) { - log_debug("found a match! NAME assigns %s in: %s:%u\n", + log_debug("found a match! NAME assigns %s in: %s:%u", name, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); @@ -1945,6 +1945,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, + struct udev_list *properties_list, const sigset_t *sigmask) { struct token *cur; struct token *rule; @@ -2334,9 +2335,9 @@ int udev_rules_apply_to_event(struct udev_rules *rules, r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL); if (r < 0) { if (r == -ENOENT || r == -ESRCH) - udev_err(event->udev, "specified user '%s' unknown\n", owner); + log_error("specified user '%s' unknown", owner); else - udev_err(event->udev, "error resolving user '%s': %s\n", owner, strerror(-r)); + log_error_errno(r, "error resolving user '%s': %m", owner); event->uid = 0; } @@ -2360,9 +2361,9 @@ int udev_rules_apply_to_event(struct udev_rules *rules, r = get_group_creds(&gr, &event->gid); if (r < 0) { if (r == -ENOENT || r == -ESRCH) - udev_err(event->udev, "specified group '%s' unknown\n", group); + log_error("specified group '%s' unknown", group); else - udev_err(event->udev, "error resolving group '%s': %s\n", group, strerror(-r)); + log_error_errno(r, "error resolving group '%s': %m", group); event->gid = 0; } @@ -2517,7 +2518,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, if (major(udev_device_get_devnum(event->dev)) && (!streq(name_str, udev_device_get_devnode(event->dev) + strlen("/dev/")))) { log_error("NAME=\"%s\" ignored, kernel device nodes " - "can not be renamed; please fix it in %s:%u\n", name, + "can not be renamed; please fix it in %s:%u", name, rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); break; } @@ -2592,10 +2593,10 @@ int udev_rules_apply_to_event(struct udev_rules *rules, f = fopen(attr, "we"); if (f != NULL) { if (fprintf(f, "%s", value) <= 0) - log_error("error writing ATTR{%s}: %m", attr); + log_error_errno(errno, "error writing ATTR{%s}: %m", attr); fclose(f); } else { - log_error("error opening ATTR{%s} for writing: %m", attr); + log_error_errno(errno, "error opening ATTR{%s} for writing: %m", attr); } break; } @@ -2710,7 +2711,7 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules) { strscpyl(tags_dir, sizeof(tags_dir), "/run/udev/static_node-tags/", *t, "/", NULL); r = mkdir_p(tags_dir, 0755); if (r < 0) { - log_error("failed to create %s: %s", tags_dir, strerror(-r)); + log_error_errno(r, "failed to create %s: %m", tags_dir); return r; } @@ -2718,10 +2719,10 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules) { strscpyl(tag_symlink, sizeof(tag_symlink), tags_dir, unescaped_filename, NULL); r = symlink(device_node, tag_symlink); - if (r < 0 && errno != EEXIST) { - log_error("failed to create symlink %s -> %s: %m", tag_symlink, device_node); - return -errno; - } else + if (r < 0 && errno != EEXIST) + return log_error_errno(errno, "failed to create symlink %s -> %s: %m", + tag_symlink, device_node); + else r = 0; } } diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c index 061bd05875..6ba8674d77 100644 --- a/src/udev/udev-watch.c +++ b/src/udev/udev-watch.c @@ -39,7 +39,7 @@ static int inotify_fd = -1; int udev_watch_init(struct udev *udev) { inotify_fd = inotify_init1(IN_CLOEXEC); if (inotify_fd < 0) - log_error("inotify_init failed: %m"); + log_error_errno(errno, "inotify_init failed: %m"); return inotify_fd; } @@ -56,7 +56,7 @@ void udev_watch_restore(struct udev *udev) { dir = opendir("/run/udev/watch.old"); if (dir == NULL) { - log_error("unable to open old watches dir /run/udev/watch.old; old watches will not be restored: %m"); + log_error_errno(errno, "unable to open old watches dir /run/udev/watch.old; old watches will not be restored: %m"); return; } @@ -88,7 +88,7 @@ unlink: rmdir("/run/udev/watch.old"); } else if (errno != ENOENT) { - log_error("unable to move watches dir /run/udev/watch; old watches will not be restored: %m"); + log_error_errno(errno, "unable to move watches dir /run/udev/watch; old watches will not be restored: %m"); } } @@ -103,7 +103,7 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev) { log_debug("adding watch on '%s'", udev_device_get_devnode(dev)); wd = inotify_add_watch(inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE); if (wd < 0) { - log_error("inotify_add_watch(%d, %s, %o) failed: %m", + log_error_errno(errno, "inotify_add_watch(%d, %s, %o) failed: %m", inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE); return; } @@ -113,7 +113,7 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev) { unlink(filename); r = symlink(udev_device_get_id_filename(dev), filename); if (r < 0) - log_error("Failed to create symlink %s: %m", filename); + log_error_errno(errno, "Failed to create symlink %s: %m", filename); udev_device_set_watch_handle(dev, wd); } diff --git a/src/udev/udev.h b/src/udev/udev.h index 5a1f5488cb..fae0408672 100644 --- a/src/udev/udev.h +++ b/src/udev/udev.h @@ -71,7 +71,9 @@ struct udev_rules; struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names); struct udev_rules *udev_rules_unref(struct udev_rules *rules); bool udev_rules_check_timestamp(struct udev_rules *rules); -int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, +int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, + usec_t timeout_usec, usec_t timeout_warn_usec, + struct udev_list *properties_list, const sigset_t *sigmask); int udev_rules_apply_static_dev_perms(struct udev_rules *rules); @@ -86,8 +88,11 @@ int udev_event_spawn(struct udev_event *event, usec_t timeout_warn_usec, const char *cmd, char **envp, const sigset_t *sigmask, char *result, size_t ressize); -void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, - struct udev_rules *rules, const sigset_t *sigset); +void udev_event_execute_rules(struct udev_event *event, + usec_t timeout_usec, usec_t timeout_warn_usec, + struct udev_list *properties_list, + struct udev_rules *rules, + const sigset_t *sigset); void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const sigset_t *sigset); int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]); @@ -193,11 +198,6 @@ int udev_builtin_add_property(struct udev_device *dev, bool test, const char *ke int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *prefix, const char *modalias, const char *filter, bool test); -/* udev logging */ -void udev_main_log(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) _printf_(6, 0); - /* udevadm commands */ struct udevadm_cmd { const char *name; diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c index 6e3bc2ae98..6af7163d47 100644 --- a/src/udev/udevadm-control.c +++ b/src/udev/udevadm-control.c @@ -29,16 +29,19 @@ #include "udev-util.h" static void print_help(void) { - printf("Usage: udevadm control COMMAND\n" - " -e,--exit instruct the daemon to cleanup and exit\n" - " -l,--log-priority=LEVEL set the udev log level for the daemon\n" - " -s,--stop-exec-queue do not execute events, queue only\n" - " -S,--start-exec-queue execute events, flush queue\n" - " -R,--reload reload rules and databases\n" - " -p,--property=KEY=VALUE set a global property for all events\n" - " -m,--children-max=N maximum number of children\n" - " --timeout=SECONDS maximum time to block for a reply\n" - " -h,--help print this help text\n\n"); + printf("%s control COMMAND\n\n" + "Control the udev daemon.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -e --exit Instruct the daemon to cleanup and exit\n" + " -l --log-priority=LEVEL Set the udev log level for the daemon\n" + " -s --stop-exec-queue Do not execute events, queue only\n" + " -S --start-exec-queue Execute events, flush queue\n" + " -R --reload Reload rules and databases\n" + " -p --property=KEY=VALUE Set a global property for all events\n" + " -m --children-max=N Maximum number of children\n" + " --timeout=SECONDS Maximum time to block for a reply\n" + , program_invocation_short_name); } static int adm_control(struct udev *udev, int argc, char *argv[]) { @@ -161,5 +164,5 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) { const struct udevadm_cmd udevadm_control = { .name = "control", .cmd = adm_control, - .help = "control the udev daemon", + .help = "Control the udev daemon", }; diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index 4a3f35c2af..a3f93ba343 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -435,6 +435,10 @@ static int insert_data(struct trie *trie, struct udev_list *match_list, value[0] = '\0'; value++; + /* libudev requires properties to start with a space */ + while (isblank(line[0]) && isblank(line[1])) + line++; + if (line[0] == '\0' || value[0] == '\0') { log_error("Error, empty key or value '%s' in '%s':", line, filename); return -EINVAL; @@ -615,7 +619,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { err = conf_files_list_strv(&files, ".hwdb", root, conf_file_dirs); if (err < 0) { - log_error("failed to enumerate hwdb files: %s", strerror(-err)); + log_error_errno(err, "failed to enumerate hwdb files: %m"); rc = EXIT_FAILURE; goto out; } @@ -648,7 +652,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { mkdir_parents(hwdb_bin, 0755); err = trie_store(trie, hwdb_bin); if (err < 0) { - log_error("Failure writing database %s: %s", hwdb_bin, strerror(-err)); + log_error_errno(err, "Failure writing database %s: %m", hwdb_bin); rc = EXIT_FAILURE; } } diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 3cb503fc1f..c845df7a23 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -31,6 +31,7 @@ #include "udev.h" #include "udev-util.h" +#include "udevadm-util.h" #include "util.h" static bool skip_attribute(const char *name) { @@ -258,33 +259,29 @@ static void cleanup_db(struct udev *udev) { } } -static struct udev_device *find_device(struct udev *udev, const char *id, const char *prefix) { - char name[UTIL_PATH_SIZE]; - - if (prefix && !startswith(id, prefix)) { - strscpyl(name, sizeof(name), prefix, id, NULL); - id = name; - } - - if (startswith(id, "/dev/")) { - struct stat statbuf; - char type; - - if (stat(id, &statbuf) < 0) - return NULL; - - if (S_ISBLK(statbuf.st_mode)) - type = 'b'; - else if (S_ISCHR(statbuf.st_mode)) - type = 'c'; - else - return NULL; - - return udev_device_new_from_devnum(udev, type, statbuf.st_rdev); - } else if (startswith(id, "/sys/")) - return udev_device_new_from_syspath(udev, id); - else - return NULL; +static void help(void) { + + printf("%s info [OPTIONS] [DEVPATH|FILE]\n\n" + "Query sysfs or the udev database.\n\n" + " -h --help Print this message\n" + " --version Print version of the program\n" + " -q --query=TYPE Query device information:\n" + " name Name of device node\n" + " symlink Pointing to node\n" + " path sysfs device path\n" + " property The device properties\n" + " all All 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" + " -a --attribute-walk Print all key matches walking along the chain\n" + " of parent devices\n" + " -d --device-id-of-file=FILE Print major:minor of device containing this file\n" + " -x --export Export key/value pairs\n" + " -P --export-prefix Export the key name with a prefix\n" + " -e --export-db Export the content of the udev database\n" + " -c --cleanup-db Clean up the udev database\n" + , program_invocation_short_name); } static int uinfo(struct udev *udev, int argc, char *argv[]) { @@ -312,27 +309,6 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) { {} }; - static const char *usage = - "Usage: udevadm info [OPTIONS] [DEVPATH|FILE]\n" - " -q,--query=TYPE query device information:\n" - " name name of device node\n" - " symlink pointing to node\n" - " path sys device path\n" - " property the device properties\n" - " all all values\n" - " -p,--path=SYSPATH sys 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" - " -a,--attribute-walk print all key matches walking along the chain\n" - " of parent devices\n" - " -d,--device-id-of-file=FILE print major:minor of device containing this file\n" - " -x,--export export key/value pairs\n" - " -P,--export-prefix export the key name with a prefix\n" - " -e,--export-db export the content of the udev database\n" - " -c,--cleanup-db cleanup the udev database\n" - " --version print version of the program\n" - " -h,--help print this message\n"; - enum action_type { ACTION_QUERY, ACTION_ATTRIBUTE_WALK, @@ -417,7 +393,7 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) { printf("%s\n", UDEV_VERSION); return 0; case 'h': - printf("%s\n", usage); + help(); return 0; default: return 1; @@ -427,7 +403,7 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) { case ACTION_QUERY: if (!device) { if (!argv[optind]) { - fprintf(stderr, "%s\n", usage); + help(); return 2; } device = find_device(udev, argv[optind], NULL); @@ -518,5 +494,5 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) { const struct udevadm_cmd udevadm_info = { .name = "info", .cmd = uinfo, - .help = "query sysfs or the udev database", + .help = "Query sysfs or the udev database", }; diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c index e776fb99dc..15ded09339 100644 --- a/src/udev/udevadm-monitor.c +++ b/src/udev/udevadm-monitor.c @@ -64,13 +64,16 @@ static void print_device(struct udev_device *device, const char *source, int pro } static void help(void) { - printf("Usage: udevadm monitor [--property] [--kernel] [--udev] [--help]\n" - " -p,--property print the event properties\n" - " -k,--kernel print kernel uevents\n" - " -u,--udev print udev events\n" - " -s,--subsystem-match=SUBSYSTEM[/DEVTYPE] filter events by subsystem\n" - " -t,--tag-match=TAG filter events by tag\n" - " -h,--help\n\n"); + printf("%s monitor [--property] [--kernel] [--udev] [--help]\n\n" + "Listen to kernel and udev events.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -p --property Print the event properties\n" + " -k --kernel Print kernel uevents\n" + " -u --udev Print udev events\n" + " -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n" + " -t --tag-match=TAG Filter events by tag\n" + , program_invocation_short_name); } static int adm_monitor(struct udev *udev, int argc, char *argv[]) { @@ -155,7 +158,7 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) { fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { - log_error("error creating epoll fd: %m"); + log_error_errno(errno, "error creating epoll fd: %m"); return 1; } @@ -195,7 +198,7 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) { ep_udev.events = EPOLLIN; ep_udev.data.fd = fd_udev; if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) { - log_error("fail to add fd to epoll: %m"); + log_error_errno(errno, "fail to add fd to epoll: %m"); return 2; } @@ -229,7 +232,7 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) { ep_kernel.events = EPOLLIN; ep_kernel.data.fd = fd_kernel; if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_kernel, &ep_kernel) < 0) { - log_error("fail to add fd to epoll: %m"); + log_error_errno(errno, "fail to add fd to epoll: %m"); return 5; } @@ -276,5 +279,5 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) { const struct udevadm_cmd udevadm_monitor = { .name = "monitor", .cmd = adm_monitor, - .help = "listen to kernel and udev events", + .help = "Listen to kernel and udev events", }; diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index 0a8f535c4a..fff5de7a8b 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -37,20 +37,23 @@ #include "util.h" static void help(void) { - printf("Usage: udevadm settle OPTIONS\n" - " -t,--timeout=<seconds> maximum time to wait for events\n" - " -E,--exit-if-exists=<file> stop waiting if file exists\n" - " -h,--help\n\n"); + printf("%s settle OPTIONS\n\n" + "Wait for pending udev events.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -t --timeout=SECONDS Maximum time to wait for events\n" + " -E --exit-if-exists=FILE Stop waiting if file exists\n" + , program_invocation_short_name); } static int adm_settle(struct udev *udev, int argc, char *argv[]) { static const struct option options[] = { - { "seq-start", required_argument, NULL, '\0' }, /* removed */ - { "seq-end", required_argument, NULL, '\0' }, /* removed */ { "timeout", required_argument, NULL, 't' }, { "exit-if-exists", required_argument, NULL, 'E' }, - { "quiet", no_argument, NULL, 'q' }, /* removed */ { "help", no_argument, NULL, 'h' }, + { "seq-start", required_argument, NULL, 's' }, /* removed */ + { "seq-end", required_argument, NULL, 'e' }, /* removed */ + { "quiet", no_argument, NULL, 'q' }, /* removed */ {} }; const char *exists = NULL; @@ -60,8 +63,9 @@ static int adm_settle(struct udev *udev, int argc, char *argv[]) { struct udev_queue *queue; int rc = EXIT_FAILURE; - while ((c = getopt_long(argc, argv, "s:e:t:E:qh", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "t:E:hs:e:q", options, NULL)) >= 0) { switch (c) { + case 't': { int r; @@ -73,14 +77,24 @@ static int adm_settle(struct udev *udev, int argc, char *argv[]) { }; break; } + case 'E': exists = optarg; break; + case 'h': help(); return EXIT_SUCCESS; + + case 's': + case 'e': + case 'q': + log_info("Option -%c no longer supported.", c); + return EXIT_FAILURE; + case '?': return EXIT_FAILURE; + default: assert_not_reached("Unknown argument"); } @@ -145,5 +159,5 @@ out: const struct udevadm_cmd udevadm_settle = { .name = "settle", .cmd = adm_settle, - .help = "wait for pending udev events", + .help = "Wait for pending udev events", }; diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c index f25608c486..baaeca9352 100644 --- a/src/udev/udevadm-test-builtin.c +++ b/src/udev/udevadm-test-builtin.c @@ -34,10 +34,14 @@ #include "udev.h" static void help(struct udev *udev) { - fprintf(stderr, "\n"); - fprintf(stderr, "Usage: udevadm builtin [--help] COMMAND SYSPATH\n"); + printf("%s builtin [--help] COMMAND SYSPATH\n\n" + "Test a built-in command.\n\n" + " -h --help Print this message\n" + " --version Print version of the program\n\n" + "Commands:\n" + , program_invocation_short_name); + udev_builtin_list(udev); - fprintf(stderr, "\n"); } static int adm_builtin(struct udev *udev, int argc, char *argv[]) { @@ -112,6 +116,6 @@ out: const struct udevadm_cmd udevadm_test_builtin = { .name = "test-builtin", .cmd = adm_builtin, - .help = "test a built-in command", + .help = "Test a built-in command", .debug = true, }; diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c index 4738b611c3..4922b5b6ac 100644 --- a/src/udev/udevadm-test.c +++ b/src/udev/udevadm-test.c @@ -31,6 +31,17 @@ #include "udev.h" #include "udev-util.h" +static void help(void) { + + printf("%s test OPTIONS <syspath>\n\n" + "Test an event run.\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -a --action=ACTION Set action string\n" + " -N --resolve-names=early|late|never When to resolve names\n" + , program_invocation_short_name); +} + static int adm_test(struct udev *udev, int argc, char *argv[]) { int resolve_names = 1; char filename[UTIL_PATH_SIZE]; @@ -71,11 +82,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) { } break; case 'h': - printf("Usage: udevadm test OPTIONS <syspath>\n" - " -a,--action=ACTION set action string\n" - " -N,--resolve-names=early|late|never when to resolve names\n" - " -h,--help print this help string\n" - "\n"); + help(); exit(EXIT_SUCCESS); case '?': exit(EXIT_FAILURE); @@ -136,7 +143,11 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) { goto out; } - udev_event_execute_rules(event, 60 * USEC_PER_SEC, 20 * USEC_PER_SEC, rules, &sigmask_orig); + udev_event_execute_rules(event, + 60 * USEC_PER_SEC, 20 * USEC_PER_SEC, + NULL, + rules, + &sigmask_orig); udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) printf("%s=%s\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry)); @@ -157,6 +168,6 @@ out: const struct udevadm_cmd udevadm_test = { .name = "test", .cmd = adm_test, - .help = "test an event run", + .help = "Test an event run", .debug = true, }; diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c index a52d1b5ad5..4dc756a28b 100644 --- a/src/udev/udevadm-trigger.c +++ b/src/udev/udevadm-trigger.c @@ -32,6 +32,7 @@ #include "udev.h" #include "udev-util.h" +#include "udevadm-util.h" #include "util.h" static int verbose; @@ -53,7 +54,7 @@ static void exec_list(struct udev_enumerate *udev_enumerate, const char *action) if (fd < 0) continue; if (write(fd, action, strlen(action)) < 0) - log_debug("error writing '%s' to '%s': %m", action, filename); + log_debug_errno(errno, "error writing '%s' to '%s': %m", action, filename); close(fd); } } @@ -72,39 +73,48 @@ static const char *keyval(const char *str, const char **val, char *buf, size_t s } static void help(void) { - printf("Usage: udevadm trigger OPTIONS\n" - " -v,--verbose print the list of devices while running\n" - " -n,--dry-run do not actually trigger the events\n" - " -t,--type= type of events to trigger\n" - " devices sys devices (default)\n" - " subsystems sys subsystems and drivers\n" - " -c,--action=<action> event action value, default is \"change\"\n" - " -s,--subsystem-match=<subsystem> trigger devices from a matching subsystem\n" - " -S,--subsystem-nomatch=<subsystem> exclude devices from a matching subsystem\n" - " -a,--attr-match=<file[=<value>]> trigger devices with a matching attribute\n" - " -A,--attr-nomatch=<file[=<value>]> exclude devices with a matching attribute\n" - " -p,--property-match=<key>=<value> trigger devices with a matching property\n" - " -g,--tag-match=<key>=<value> trigger devices with a matching property\n" - " -y,--sysname-match=<name> trigger devices with a matching name\n" - " -b,--parent-match=<name> trigger devices with that parent device\n" - " -h,--help\n\n"); + printf("%s trigger OPTIONS\n\n" + "Request events from the kernel.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -v --verbose Print the list of devices while running\n" + " -n --dry-run Do not actually trigger the events\n" + " -t --type= Type of events to trigger\n" + " devices sysfs devices (default)\n" + " subsystems sysfs subsystems and drivers\n" + " -c --action=ACTION Event action value, default is \"change\"\n" + " -s --subsystem-match=SUBSYSTEM Trigger devices from a matching subsystem\n" + " -S --subsystem-nomatch=SUBSYSTEM Exclude devices from a matching subsystem\n" + " -a --attr-match=FILE[=VALUE] Trigger devices with a matching attribute\n" + " -A --attr-nomatch=FILE[=VALUE] Exclude devices with a matching attribute\n" + " -p --property-match=KEY=VALUE Trigger devices with a matching property\n" + " -g --tag-match=KEY=VALUE Trigger devices with a matching property\n" + " -y --sysname-match=NAME Trigger devices with this /sys path\n" + " --name-match=NAME Trigger devices with this /dev name\n" + " -b --parent-match=NAME Trigger devices with that parent device\n" + , program_invocation_short_name); } static int adm_trigger(struct udev *udev, int argc, char *argv[]) { + enum { + ARG_NAME = 0x100, + }; + static const struct option options[] = { - { "verbose", no_argument, NULL, 'v' }, - { "dry-run", no_argument, NULL, 'n' }, - { "type", required_argument, NULL, 't' }, - { "action", required_argument, NULL, 'c' }, - { "subsystem-match", required_argument, NULL, 's' }, - { "subsystem-nomatch", required_argument, NULL, 'S' }, - { "attr-match", required_argument, NULL, 'a' }, - { "attr-nomatch", required_argument, NULL, 'A' }, - { "property-match", required_argument, NULL, 'p' }, - { "tag-match", required_argument, NULL, 'g' }, - { "sysname-match", required_argument, NULL, 'y' }, - { "parent-match", required_argument, NULL, 'b' }, - { "help", no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { "dry-run", no_argument, NULL, 'n' }, + { "type", required_argument, NULL, 't' }, + { "action", required_argument, NULL, 'c' }, + { "subsystem-match", required_argument, NULL, 's' }, + { "subsystem-nomatch", required_argument, NULL, 'S' }, + { "attr-match", required_argument, NULL, 'a' }, + { "attr-nomatch", required_argument, NULL, 'A' }, + { "property-match", required_argument, NULL, 'p' }, + { "tag-match", required_argument, NULL, 'g' }, + { "sysname-match", required_argument, NULL, 'y' }, + { "name-match", required_argument, NULL, ARG_NAME }, + { "parent-match", required_argument, NULL, 'b' }, + { "help", no_argument, NULL, 'h' }, {} }; enum { @@ -174,25 +184,31 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) { udev_enumerate_add_match_sysname(udev_enumerate, optarg); break; case 'b': { - char path[UTIL_PATH_SIZE]; - struct udev_device *dev; - - /* add sys dir if needed */ - if (!startswith(optarg, "/sys")) - strscpyl(path, sizeof(path), "/sys", optarg, NULL); - else - strscpy(path, sizeof(path), optarg); - util_remove_trailing_chars(path, '/'); - dev = udev_device_new_from_syspath(udev, path); + _cleanup_udev_device_unref_ struct udev_device *dev; + + dev = find_device(udev, optarg, "/sys"); + if (dev == NULL) { + log_error("unable to open the device '%s'", optarg); + return 2; + } + + udev_enumerate_add_match_parent(udev_enumerate, dev); + break; + } + + case ARG_NAME: { + _cleanup_udev_device_unref_ struct udev_device *dev; + + dev = find_device(udev, optarg, "/dev/"); if (dev == NULL) { log_error("unable to open the device '%s'", optarg); return 2; } + udev_enumerate_add_match_parent(udev_enumerate, dev); - /* drop reference immediately, enumerate pins the device as long as needed */ - udev_device_unref(dev); break; } + case 'h': help(); return 0; @@ -203,9 +219,16 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) { } } - if (optind < argc) { - fprintf(stderr, "Extraneous argument: '%s'\n", argv[optind]); - return 1; + for (; optind < argc; optind++) { + _cleanup_udev_device_unref_ struct udev_device *dev; + + dev = find_device(udev, argv[optind], NULL); + if (dev == NULL) { + log_error("unable to open the device '%s'", argv[optind]); + return 2; + } + + udev_enumerate_add_match_parent(udev_enumerate, dev); } switch (device_type) { @@ -225,5 +248,5 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) { const struct udevadm_cmd udevadm_trigger = { .name = "trigger", .cmd = adm_trigger, - .help = "request events from the kernel", + .help = "Request events from the kernel", }; diff --git a/src/udev/udevadm-util.c b/src/udev/udevadm-util.c new file mode 100644 index 0000000000..37e80c31df --- /dev/null +++ b/src/udev/udevadm-util.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008-2009 Kay Sievers <kay@vrfy.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "udevadm-util.h" + +struct udev_device *find_device(struct udev *udev, + const char *id, + const char *prefix) { + + assert(udev); + assert(id); + + if (prefix && !startswith(id, prefix)) + id = strappenda(prefix, id); + + if (startswith(id, "/dev/")) { + struct stat statbuf; + char type; + + if (stat(id, &statbuf) < 0) + return NULL; + + if (S_ISBLK(statbuf.st_mode)) + type = 'b'; + else if (S_ISCHR(statbuf.st_mode)) + type = 'c'; + else + return NULL; + + return udev_device_new_from_devnum(udev, type, statbuf.st_rdev); + } else if (startswith(id, "/sys/")) + return udev_device_new_from_syspath(udev, id); + else + return NULL; +} diff --git a/src/udev/udevadm-util.h b/src/udev/udevadm-util.h new file mode 100644 index 0000000000..dba651fddb --- /dev/null +++ b/src/udev/udevadm-util.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "udev.h" + +struct udev_device *find_device(struct udev *udev, + const char *id, + const char *prefix); diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c index fda5aecd83..3e57cf6dee 100644 --- a/src/udev/udevadm.c +++ b/src/udev/udevadm.c @@ -26,12 +26,6 @@ #include "udev.h" -void udev_main_log(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) { - log_metav(priority, file, line, fn, format, args); -} - static int adm_version(struct udev *udev, int argc, char *argv[]) { printf("%s\n", UDEV_VERSION); return 0; @@ -65,11 +59,14 @@ static const struct udevadm_cmd *udevadm_cmds[] = { static int adm_help(struct udev *udev, int argc, char *argv[]) { unsigned int i; - fprintf(stderr, "Usage: udevadm [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n"); + printf("%s [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n\n" + "Send control commands or test the device manager.\n\n" + "Commands:\n" + , program_invocation_short_name); + for (i = 0; i < ELEMENTSOF(udevadm_cmds); i++) if (udevadm_cmds[i]->help != NULL) - printf(" %-12s %s\n", udevadm_cmds[i]->name, udevadm_cmds[i]->help); - fprintf(stderr, "\n"); + printf(" %-12s %s\n", udevadm_cmds[i]->name, udevadm_cmds[i]->help); return 0; } @@ -97,7 +94,6 @@ int main(int argc, char *argv[]) { goto out; log_open(); - udev_set_log_fn(udev, udev_main_log); mac_selinux_init("/dev"); while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0) @@ -105,7 +101,6 @@ int main(int argc, char *argv[]) { case 'd': log_set_max_level(LOG_DEBUG); - udev_set_log_priority(udev, LOG_DEBUG); break; case 'h': diff --git a/src/udev/udevd.c b/src/udev/udevd.c index a74906aa62..e835bef8df 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -53,12 +53,6 @@ #include "dev-setup.h" #include "fileio.h" -void udev_main_log(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) { - log_metav(priority, file, line, fn, format, args); -} - static struct udev_rules *rules; static struct udev_ctrl *udev_ctrl; static struct udev_monitor *monitor; @@ -80,6 +74,7 @@ static sigset_t sigmask_orig; static UDEV_LIST(event_list); static UDEV_LIST(worker_list); static char *udev_cgroup; +static struct udev_list properties_list; static bool udev_exit; enum event_state { @@ -223,14 +218,14 @@ static void worker_new(struct event *event) { sigfillset(&mask); fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); if (fd_signal < 0) { - log_error("error creating signalfd %m"); + log_error_errno(errno, "error creating signalfd %m"); rc = 2; goto out; } fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { - log_error("error creating epoll fd: %m"); + log_error_errno(errno, "error creating epoll fd: %m"); rc = 3; goto out; } @@ -246,7 +241,7 @@ static void worker_new(struct event *event) { if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_signal, &ep_signal) < 0 || epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_monitor, &ep_monitor) < 0) { - log_error("fail to add fds to epoll: %m"); + log_error_errno(errno, "fail to add fds to epoll: %m"); rc = 4; goto out; } @@ -296,7 +291,7 @@ static void worker_new(struct event *event) { if (d) { fd_lock = open(udev_device_get_devnode(d), O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK); if (fd_lock >= 0 && flock(fd_lock, LOCK_SH|LOCK_NB) < 0) { - log_debug("Unable to flock(%s), skipping event handling: %m", udev_device_get_devnode(d)); + log_debug_errno(errno, "Unable to flock(%s), skipping event handling: %m", udev_device_get_devnode(d)); err = -EWOULDBLOCK; fd_lock = safe_close(fd_lock); goto skip; @@ -305,9 +300,15 @@ static void worker_new(struct event *event) { } /* apply rules, create node, symlinks */ - udev_event_execute_rules(udev_event, arg_event_timeout_usec, arg_event_timeout_warn_usec, rules, &sigmask_orig); + udev_event_execute_rules(udev_event, + arg_event_timeout_usec, arg_event_timeout_warn_usec, + &properties_list, + rules, + &sigmask_orig); - udev_event_execute_run(udev_event, arg_event_timeout_usec, arg_event_timeout_warn_usec, &sigmask_orig); + udev_event_execute_run(udev_event, + arg_event_timeout_usec, arg_event_timeout_warn_usec, + &sigmask_orig); /* apply/restore inotify watch */ if (udev_event->inotify_watch) { @@ -349,7 +350,7 @@ skip: if (fdcount < 0) { if (errno == EINTR) continue; - log_error("failed to poll: %m"); + log_error_errno(errno, "failed to poll: %m"); goto out; } @@ -389,7 +390,7 @@ out: udev_monitor_unref(worker_monitor); event->state = EVENT_QUEUED; free(worker); - log_error("fork of child failed: %m"); + log_error_errno(errno, "fork of child failed: %m"); break; default: /* close monitor, but keep address around */ @@ -420,7 +421,7 @@ static void event_run(struct event *event) { count = udev_monitor_send_device(monitor, worker->monitor, event->dev); if (count < 0) { - log_error("worker [%u] did not accept message %zi (%m), kill it", worker->pid, count); + log_error_errno(errno, "worker [%u] did not accept message %zi (%m), kill it", worker->pid, count); kill(worker->pid, SIGKILL); worker->state = WORKER_KILLED; continue; @@ -636,7 +637,6 @@ static struct udev_ctrl_connection *handle_ctrl_msg(struct udev_ctrl *uctrl) { if (i >= 0) { log_debug("udevd message (SET_LOG_LEVEL) received, log_priority=%i", i); log_set_max_level(i); - udev_set_log_priority(udev, i); worker_kill(udev); } @@ -669,10 +669,10 @@ static struct udev_ctrl_connection *handle_ctrl_msg(struct udev_ctrl *uctrl) { val = &val[1]; if (val[0] == '\0') { log_debug("udevd message (ENV) received, unset '%s'", key); - udev_add_property(udev, key, NULL); + udev_list_entry_add(&properties_list, key, NULL); } else { log_debug("udevd message (ENV) received, set '%s=%s'", key, val); - udev_add_property(udev, key, val); + udev_list_entry_add(&properties_list, key, val); } } else { log_error("wrong key format '%s'", key); @@ -807,41 +807,34 @@ static int synthesize_change(struct udev_device *dev) { } static int handle_inotify(struct udev *udev) { - int nbytes, pos; - char *buf; - struct inotify_event *ev; - int r; + union inotify_event_buffer buffer; + struct inotify_event *e; + ssize_t l; - r = ioctl(fd_inotify, FIONREAD, &nbytes); - if (r < 0 || nbytes <= 0) - return -errno; + l = read(fd_inotify, &buffer, sizeof(buffer)); + if (l < 0) { + if (errno == EAGAIN || errno == EINTR) + return 0; - buf = malloc(nbytes); - if (!buf) { - log_error("error getting buffer for inotify"); - return -ENOMEM; + return log_error_errno(errno, "Failed to read inotify fd: %m"); } - nbytes = read(fd_inotify, buf, nbytes); - - for (pos = 0; pos < nbytes; pos += sizeof(struct inotify_event) + ev->len) { + FOREACH_INOTIFY_EVENT(e, buffer, l) { struct udev_device *dev; - ev = (struct inotify_event *)(buf + pos); - dev = udev_watch_lookup(udev, ev->wd); + dev = udev_watch_lookup(udev, e->wd); if (!dev) continue; - log_debug("inotify event: %x for %s", ev->mask, udev_device_get_devnode(dev)); - if (ev->mask & IN_CLOSE_WRITE) + log_debug("inotify event: %x for %s", e->mask, udev_device_get_devnode(dev)); + if (e->mask & IN_CLOSE_WRITE) synthesize_change(dev); - else if (ev->mask & IN_IGNORED) + else if (e->mask & IN_IGNORED) udev_watch_end(udev, dev); udev_device_unref(dev); } - free(buf); return 0; } @@ -966,7 +959,7 @@ static void static_dev_create_from_modules(struct udev *udev) { strscpyl(filename, sizeof(filename), "/dev/", devname, NULL); mkdir_parents_label(filename, 0755); mac_selinux_create_file_prepare(filename, mode); - log_debug("mknod '%s' %c%u:%u\n", filename, type, maj, min); + log_debug("mknod '%s' %c%u:%u", filename, type, maj, min); if (mknod(filename, mode, makedev(maj, min)) < 0 && errno == EEXIST) utimensat(AT_FDCWD, filename, NULL, 0); mac_selinux_create_file_clear(); @@ -976,7 +969,7 @@ static void static_dev_create_from_modules(struct udev *udev) { } /* - * read the kernel commandline, in case we need to get into debug mode + * read the kernel command line, in case we need to get into debug mode * udev.log-priority=<level> syslog priority * udev.children-max=<number of workers> events are fully serialized if set to 1 * udev.exec-delay=<number of seconds> delay execution of every executed program @@ -988,13 +981,13 @@ static void kernel_cmdline_options(struct udev *udev) { int r; r = proc_cmdline(&line); - if (r < 0) - log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r)); - if (r <= 0) + if (r < 0) { + log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m"); return; + } FOREACH_WORD_QUOTED(word, l, line, state) { - char *s, *opt; + char *s, *opt, *value; s = strndup(word, l); if (!s) @@ -1006,24 +999,23 @@ static void kernel_cmdline_options(struct udev *udev) { else opt = s; - if (startswith(opt, "udev.log-priority=")) { + if ((value = startswith(opt, "udev.log-priority="))) { int prio; - prio = util_log_priority(opt + 18); + prio = util_log_priority(value); log_set_max_level(prio); - udev_set_log_priority(udev, prio); - } else if (startswith(opt, "udev.children-max=")) { - r = safe_atoi(opt + 18, &arg_children_max); + } else if ((value = startswith(opt, "udev.children-max="))) { + r = safe_atoi(value, &arg_children_max); if (r < 0) - log_warning("Invalid udev.children-max ignored: %s", opt + 18); - } else if (startswith(opt, "udev.exec-delay=")) { - r = safe_atoi(opt + 16, &arg_exec_delay); + log_warning("Invalid udev.children-max ignored: %s", value); + } else if ((value = startswith(opt, "udev.exec-delay="))) { + r = safe_atoi(value, &arg_exec_delay); if (r < 0) - log_warning("Invalid udev.exec-delay ignored: %s", opt + 16); - } else if (startswith(opt, "udev.event-timeout=")) { - r = safe_atou64(opt + 16, &arg_event_timeout_usec); + log_warning("Invalid udev.exec-delay ignored: %s", value); + } else if ((value = startswith(opt, "udev.event-timeout="))) { + r = safe_atou64(value, &arg_event_timeout_usec); if (r < 0) { - log_warning("Invalid udev.event-timeout ignored: %s", opt + 16); + log_warning("Invalid udev.event-timeout ignored: %s", value); break; } arg_event_timeout_usec *= USEC_PER_SEC; @@ -1037,14 +1029,15 @@ static void kernel_cmdline_options(struct udev *udev) { static void help(void) { printf("%s [OPTIONS...]\n\n" "Manages devices.\n\n" - " --daemon\n" - " --debug\n" - " --children-max=<maximum number of workers>\n" - " --exec-delay=<seconds to wait before executing RUN=>\n" - " --event-timeout=<seconds to wait before terminating an event>\n" - " --resolve-names=early|late|never\n" - " --version\n" - " --help\n" + " -h --help Print this message\n" + " --version Print version of the program\n" + " --daemon Detach and run in the background\n" + " --debug Enable debug output\n" + " --children-max=INT Set maximum number of workers\n" + " --exec-delay=SECONDS Seconds to wait before executing RUN=\n" + " --event-timeout=SECONDS Seconds to wait before terminating an event\n" + " --resolve-names=early|late|never\n" + " When to resolve users and groups\n" , program_invocation_short_name); } @@ -1146,19 +1139,14 @@ int main(int argc, char *argv[]) { log_set_target(LOG_TARGET_AUTO); log_open(); - udev_set_log_fn(udev, udev_main_log); - log_set_max_level(udev_get_log_priority(udev)); - r = parse_argv(argc, argv); if (r <= 0) goto exit; kernel_cmdline_options(udev); - if (arg_debug) { + if (arg_debug) log_set_max_level(LOG_DEBUG); - udev_set_log_priority(udev, LOG_DEBUG); - } if (getuid() != 0) { log_error("root privileges required"); @@ -1167,22 +1155,24 @@ int main(int argc, char *argv[]) { r = mac_selinux_init("/dev"); if (r < 0) { - log_error("could not initialize labelling: %s", strerror(-r)); + log_error_errno(r, "could not initialize labelling: %m"); goto exit; } /* set umask before creating any file/directory */ r = chdir("/"); if (r < 0) { - log_error("could not change dir to /: %m"); + log_error_errno(errno, "could not change dir to /: %m"); goto exit; } umask(022); + udev_list_init(udev, &properties_list, true); + r = mkdir("/run/udev", 0755); if (r < 0 && errno != EEXIST) { - log_error("could not create /run/udev: %m"); + log_error_errno(errno, "could not create /run/udev: %m"); goto exit; } @@ -1237,7 +1227,7 @@ int main(int argc, char *argv[]) { udev_monitor_set_receive_buffer_size(monitor, 128 * 1024 * 1024); - log_info("starting version " VERSION "\n"); + log_info("starting version " VERSION); udev_builtin_init(udev); @@ -1249,7 +1239,7 @@ int main(int argc, char *argv[]) { rc = udev_rules_apply_static_dev_perms(rules); if (rc < 0) - log_error("failed to apply permissions on static device nodes - %s", strerror(-rc)); + log_error_errno(rc, "failed to apply permissions on static device nodes - %m"); if (arg_daemonize) { pid_t pid; @@ -1259,7 +1249,7 @@ int main(int argc, char *argv[]) { case 0: break; case -1: - log_error("fork of daemon failed: %m"); + log_error_errno(errno, "fork of daemon failed: %m"); rc = 4; goto exit; default: @@ -1332,7 +1322,7 @@ int main(int argc, char *argv[]) { fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { - log_error("error creating epoll fd: %m"); + log_error_errno(errno, "error creating epoll fd: %m"); goto exit; } if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_ctrl, &ep_ctrl) < 0 || @@ -1340,7 +1330,7 @@ int main(int argc, char *argv[]) { epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_signal, &ep_signal) < 0 || epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_netlink, &ep_netlink) < 0 || epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_worker, &ep_worker) < 0) { - log_error("fail to add fds to epoll: %m"); + log_error_errno(errno, "fail to add fds to epoll: %m"); goto exit; } |