diff options
Diffstat (limited to 'src/udev')
26 files changed, 463 insertions, 127 deletions
diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c index 1e414664ce..ad152b9d31 100644 --- a/src/udev/ata_id/ata_id.c +++ b/src/udev/ata_id/ata_id.c @@ -427,6 +427,8 @@ int main(int argc, char *argv[]) {} }; + log_set_target(LOG_TARGET_AUTO); + udev_parse_config(); log_parse_environment(); log_open(); diff --git a/src/udev/cdrom_id/cdrom_id.c b/src/udev/cdrom_id/cdrom_id.c index 72f284f710..1f906a8525 100644 --- a/src/udev/cdrom_id/cdrom_id.c +++ b/src/udev/cdrom_id/cdrom_id.c @@ -38,6 +38,7 @@ #include "libudev-private.h" #include "random-util.h" +#include "udev-util.h" /* device info */ static unsigned int cd_cd_rom; @@ -843,8 +844,7 @@ static int cd_media_toc(struct udev *udev, int fd) return 0; } -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { struct udev *udev; static const struct option options[] = { { "lock-media", no_argument, NULL, 'l' }, @@ -862,6 +862,8 @@ int main(int argc, char *argv[]) int cnt; int rc = 0; + log_set_target(LOG_TARGET_AUTO); + udev_parse_config(); log_parse_environment(); log_open(); diff --git a/src/udev/collect/collect.c b/src/udev/collect/collect.c index 0e973cd521..57dfb016f9 100644 --- a/src/udev/collect/collect.c +++ b/src/udev/collect/collect.c @@ -29,6 +29,7 @@ #include "macro.h" #include "stdio-util.h" #include "string-util.h" +#include "udev-util.h" #define BUFSIZE 16 #define UDEV_ALARM_TIMEOUT 180 @@ -343,9 +344,7 @@ static void everybody(void) } } -int main(int argc, char **argv) -{ - struct udev *udev; +int main(int argc, char **argv) { static const struct option options[] = { { "add", no_argument, NULL, 'a' }, { "remove", no_argument, NULL, 'r' }, @@ -361,11 +360,10 @@ int main(int argc, char **argv) int prune = 0; char tmpdir[UTIL_PATH_SIZE]; - udev = udev_new(); - if (udev == NULL) { - ret = EXIT_FAILURE; - goto exit; - } + log_set_target(LOG_TARGET_AUTO); + udev_parse_config(); + log_parse_environment(); + log_open(); for (;;) { int option; @@ -386,26 +384,23 @@ int main(int argc, char **argv) break; case 'h': usage(); - goto exit; + return 0; default: - ret = 1; - goto exit; + return 1; } } argi = optind; if (argi + 2 > argc) { printf("Missing parameter(s)\n"); - ret = 1; - goto exit; + return 1; } checkpoint = argv[argi++]; us = argv[argi++]; if (signal(SIGALRM, sig_alrm) == SIG_ERR) { fprintf(stderr, "Cannot set SIGALRM: %m\n"); - ret = 2; - goto exit; + return 2; } udev_list_node_init(&bunch); @@ -485,7 +480,5 @@ out: everybody(); if (ret >= 0) printf("COLLECT_%s=%d\n", checkpoint, ret); -exit: - udev_unref(udev); return ret; } diff --git a/src/udev/generate-keyboard-keys-gperf.sh b/src/udev/generate-keyboard-keys-gperf.sh new file mode 100755 index 0000000000..5724e4e3dc --- /dev/null +++ b/src/udev/generate-keyboard-keys-gperf.sh @@ -0,0 +1,10 @@ +#!/bin/sh -eu +awk ' BEGIN { + print "struct key_name { const char* name; unsigned short id; };" + print "%null-strings" + print "%%" + } + + /^KEY_/ { print tolower(substr($1 ,5)) ", " $1 } + { print tolower($1) ", " $1 } +' < "$1" diff --git a/src/udev/generate-keyboard-keys-list.sh b/src/udev/generate-keyboard-keys-list.sh new file mode 100755 index 0000000000..7a74e0dae1 --- /dev/null +++ b/src/udev/generate-keyboard-keys-list.sh @@ -0,0 +1,6 @@ +#!/bin/sh -eu + +$1 -dM -include linux/input.h - </dev/null | awk ' + /\<(KEY_(MAX|MIN_INTERESTING))|(BTN_(MISC|MOUSE|JOYSTICK|GAMEPAD|DIGI|WHEEL|TRIGGER_HAPPY))\>/ { next } + /^#define[ \t]+(KEY|BTN)_[^ ]+[ \t]+[0-9BK]/ { print $2 } +' diff --git a/src/udev/meson.build b/src/udev/meson.build new file mode 100644 index 0000000000..eeb341f8d1 --- /dev/null +++ b/src/udev/meson.build @@ -0,0 +1,152 @@ +udevadm_sources = files(''' + udevadm.c + udevadm-info.c + udevadm-control.c + udevadm-monitor.c + udevadm-hwdb.c + udevadm-settle.c + udevadm-trigger.c + udevadm-test.c + udevadm-test-builtin.c + udevadm-util.c + udevadm-util.h +'''.split()) + +systemd_udevd_sources = files('udevd.c') + +libudev_core_sources = ''' + udev.h + udev-event.c + udev-watch.c + udev-node.c + udev-rules.c + udev-ctrl.c + udev-builtin.c + udev-builtin-btrfs.c + udev-builtin-hwdb.c + udev-builtin-input_id.c + udev-builtin-keyboard.c + udev-builtin-net_id.c + udev-builtin-net_setup_link.c + udev-builtin-path_id.c + udev-builtin-usb_id.c + net/link-config.c + net/link-config.h + net/ethtool-util.c + net/ethtool-util.h +'''.split() + +if conf.get('HAVE_KMOD', false) + libudev_core_sources += ['udev-builtin-kmod.c'] +endif + +if conf.get('HAVE_BLKID', false) + libudev_core_sources += ['udev-builtin-blkid.c'] +endif + +if conf.get('HAVE_ACL', false) + libudev_core_sources += ['udev-builtin-uaccess.c', + logind_acl_c, + sd_login_c] +endif + +############################################################ + +generate_keyboard_keys_list = find_program('generate-keyboard-keys-list.sh') +keyboard_keys_list_txt = custom_target( + 'keyboard-keys-list.txt', + output : 'keyboard-keys-list.txt', + command : [generate_keyboard_keys_list, cpp], + capture : true) + +generate_keyboard_keys_gperf = find_program('generate-keyboard-keys-gperf.sh') +fname = 'keyboard-keys-from-name.gperf' +gperf_file = custom_target( + fname, + input : keyboard_keys_list_txt, + output : fname, + command : [generate_keyboard_keys_gperf, '@INPUT@'], + capture : true) + +fname = 'keyboard-keys-from-name.h' +keyboard_keys_from_name_h = custom_target( + fname, + input : gperf_file, + output : fname, + command : [gperf, + '-L', 'ANSI-C', '-t', + '-N', 'keyboard_lookup_key', + '-H', 'hash_key_name', + '-p', '-C', + '@INPUT@'], + capture : true) + +############################################################ + +link_config_gperf_c = custom_target( + 'link-config-gperf.c', + input : 'net/link-config-gperf.gperf', + output : 'link-config-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + +############################################################ + +if get_option('link-udev-shared') + udev_link_with = [libshared] + udev_rpath = rootlibexecdir +else + udev_link_with = [libshared_static, + libsystemd_internal] + udev_rpath = '' +endif + +libudev_internal = static_library( + 'udev', + libudev_sources, + include_directories : includes, + link_with : udev_link_with) + +libudev_core_includes = [includes, include_directories('net')] +libudev_core = static_library( + 'udev-core', + libudev_core_sources, + link_config_gperf_c, + keyboard_keys_from_name_h, + include_directories : libudev_core_includes, + link_with : udev_link_with, + dependencies : [libblkid, libkmod]) + +foreach prog : [['ata_id/ata_id.c'], + ['cdrom_id/cdrom_id.c'], + ['collect/collect.c'], + ['scsi_id/scsi_id.c', + 'scsi_id/scsi_id.h', + 'scsi_id/scsi_serial.c', + 'scsi_id/scsi.h'], + ['v4l_id/v4l_id.c'], + ['mtd_probe/mtd_probe.c', + 'mtd_probe/mtd_probe.h', + 'mtd_probe/probe_smartmedia.c']] + + executable(prog[0].split('/')[0], + prog, + include_directories : includes, + c_args : ['-DLOG_REALM=LOG_REALM_UDEV'], + link_with : [libudev_internal], + install_rpath : udev_rpath, + install : true, + install_dir : udevlibexecdir) +endforeach + +install_data('udev.conf', + install_dir : join_paths(sysconfdir, 'udev')) + +udev_pc = configure_file( + input : 'udev.pc.in', + output : 'udev.pc', + configuration : substs) +install_data(udev_pc, + install_dir : pkgconfigdatadir) + +meson.add_install_script('sh', '-c', + mkdir_p.format(join_paths(sysconfdir, 'udev/rules.d'))) diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c index d7edbb396b..201fc23437 100644 --- a/src/udev/net/ethtool-util.c +++ b/src/udev/net/ethtool-util.c @@ -25,6 +25,7 @@ #include "conf-parser.h" #include "ethtool-util.h" #include "log.h" +#include "link-config.h" #include "socket-util.h" #include "string-table.h" #include "strxcpyx.h" @@ -48,6 +49,17 @@ static const char* const wol_table[_WOL_MAX] = { DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan); DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting"); +static const char* const port_table[_NET_DEV_PORT_MAX] = { + [NET_DEV_PORT_TP] = "tp", + [NET_DEV_PORT_AUI] = "aui", + [NET_DEV_PORT_MII] = "mii", + [NET_DEV_PORT_FIBRE] = "fibre", + [NET_DEV_PORT_BNC] = "bnc" +}; + +DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort); +DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse Port setting"); + static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = { [NET_DEV_FEAT_GSO] = "tx-generic-segmentation", [NET_DEV_FEAT_GRO] = "rx-gro", @@ -488,12 +500,12 @@ static int set_sset(int *fd, struct ifreq *ifr, const struct ethtool_link_usetti * enabled speed and @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode. */ -int ethtool_set_glinksettings(int *fd, const char *ifname, unsigned int speed, Duplex duplex, int autonegotiation) { +int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *link) { _cleanup_free_ struct ethtool_link_usettings *u = NULL; struct ifreq ifr = {}; int r; - if (autonegotiation != 0) { + if (link->autonegotiation != 0) { log_info("link_config: autonegotiation is unset or enabled, the speed and duplex are not writable."); return 0; } @@ -514,13 +526,16 @@ int ethtool_set_glinksettings(int *fd, const char *ifname, unsigned int speed, D return log_warning_errno(r, "link_config: Cannot get device settings for %s : %m", ifname); } - if (speed) - u->base.speed = speed; + if (link->speed) + u->base.speed = DIV_ROUND_UP(link->speed, 1000000); + + if (link->duplex != _DUP_INVALID) + u->base.duplex = link->duplex; - if (duplex != _DUP_INVALID) - u->base.duplex = duplex; + if (link->port != _NET_DEV_PORT_INVALID) + u->base.port = link->port; - u->base.autoneg = autonegotiation; + u->base.autoneg = link->autonegotiation; if (u->base.cmd == ETHTOOL_GLINKSETTINGS) r = set_slinksettings(fd, &ifr, u); diff --git a/src/udev/net/ethtool-util.h b/src/udev/net/ethtool-util.h index 75d6af396b..27ce0e0aba 100644 --- a/src/udev/net/ethtool-util.h +++ b/src/udev/net/ethtool-util.h @@ -24,11 +24,13 @@ #include "missing.h" +struct link_config; + /* we can't use DUPLEX_ prefix, as it * clashes with <linux/ethtool.h> */ typedef enum Duplex { - DUP_FULL, - DUP_HALF, + DUP_HALF = DUPLEX_HALF, + DUP_FULL = DUPLEX_FULL, _DUP_MAX, _DUP_INVALID = -1 } Duplex; @@ -51,6 +53,18 @@ typedef enum NetDevFeature { _NET_DEV_FEAT_INVALID = -1 } NetDevFeature; +typedef enum NetDevPort { + NET_DEV_PORT_TP = 0x00, + NET_DEV_PORT_AUI = 0x01, + NET_DEV_PORT_MII = 0x02, + NET_DEV_PORT_FIBRE = 0x03, + NET_DEV_PORT_BNC = 0x04, + NET_DEV_PORT_DA = 0x05, + NET_DEV_PORT_NONE = 0xef, + NET_DEV_PORT_OTHER = 0xff, + _NET_DEV_PORT_MAX, + _NET_DEV_PORT_INVALID = -1 +} NetDevPort; #define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32 (SCHAR_MAX) @@ -71,7 +85,7 @@ int ethtool_get_driver(int *fd, const char *ifname, char **ret); int ethtool_set_speed(int *fd, const char *ifname, unsigned int speed, Duplex duplex); int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol); int ethtool_set_features(int *fd, const char *ifname, NetDevFeature *features); -int ethtool_set_glinksettings(int *fd, const char *ifname, unsigned int speed, Duplex duplex, int autoneg); +int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *link); const char *duplex_to_string(Duplex d) _const_; Duplex duplex_from_string(const char *d) _pure_; @@ -79,5 +93,9 @@ Duplex duplex_from_string(const char *d) _pure_; const char *wol_to_string(WakeOnLan wol) _const_; WakeOnLan wol_from_string(const char *wol) _pure_; +const char *port_to_string(NetDevPort port) _const_; +NetDevPort port_from_string(const char *port) _pure_; + int config_parse_duplex(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_wol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 78e551df22..5488867ba7 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -36,6 +36,7 @@ Link.BitsPerSecond, config_parse_si_size, 0, Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex) Link.AutoNegotiation, config_parse_tristate, 0, offsetof(link_config, autonegotiation) Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol) +Link.Port, config_parse_port, 0, offsetof(link_config, port) Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO]) Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO]) Link.UDPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_UFO]) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 3af87f1388..05a186357c 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -167,6 +167,7 @@ static int load_link(link_config_ctx *ctx, const char *filename) { link->mac_policy = _MACPOLICY_INVALID; link->wol = _WOL_INVALID; link->duplex = _DUP_INVALID; + link->port = _NET_DEV_PORT_INVALID; link->autonegotiation = -1; memset(&link->features, -1, sizeof(link->features)); @@ -377,12 +378,13 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, if (!old_name) return -EINVAL; - - speed = DIV_ROUND_UP(config->speed, 1000000); - - r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, speed, config->duplex, config->autonegotiation); + r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, config); if (r < 0) { + if (config->port != _NET_DEV_PORT_INVALID) + log_warning_errno(r, "Could not set port (%s) of %s: %m", port_to_string(config->port), old_name); + + speed = DIV_ROUND_UP(config->speed, 1000000); if (r == -EOPNOTSUPP) r = ethtool_set_speed(&ctx->ethtool_fd, old_name, speed, config->duplex); diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index 5a25cec6fd..ff91a65135 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -71,6 +71,7 @@ struct link_config { Duplex duplex; int autonegotiation; WakeOnLan wol; + NetDevPort port; NetDevFeature features[_NET_DEV_FEAT_MAX]; LIST_FIELDS(link_config, links); diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c index 4655691642..3c3d7a6b33 100644 --- a/src/udev/scsi_id/scsi_id.c +++ b/src/udev/scsi_id/scsi_id.c @@ -391,7 +391,7 @@ static int set_options(struct udev *udev, break; case 'V': - printf("%s\n", VERSION); + printf("%s\n", PACKAGE_VERSION); exit(0); case 'x': @@ -577,6 +577,8 @@ int main(int argc, char **argv) int newargc; char **newargv = NULL; + log_set_target(LOG_TARGET_AUTO); + udev_parse_config(); log_parse_environment(); log_open(); diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c index 9037aa1304..11d7085153 100644 --- a/src/udev/udev-builtin-blkid.c +++ b/src/udev/udev-builtin-blkid.c @@ -18,7 +18,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <blkid/blkid.h> +#include <blkid.h> #include <errno.h> #include <fcntl.h> #include <getopt.h> @@ -30,6 +30,7 @@ #include "sd-id128.h" #include "alloc-util.h" +#include "blkid-util.h" #include "efivars.h" #include "fd-util.h" #include "gpt.h" @@ -225,10 +226,9 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t int64_t offset = 0; bool noraid = false; _cleanup_close_ int fd = -1; - blkid_probe pr; + _cleanup_blkid_free_probe_ blkid_probe pr = NULL; const char *data; const char *name; - const char *prtype = NULL; int nvals; int i; int err = 0; @@ -264,8 +264,7 @@ 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_BADCSUM); + BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); if (noraid) blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); @@ -287,15 +286,6 @@ 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; - } /* If we are a partition then our parent passed on the root * partition UUID to us */ @@ -321,7 +311,6 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t if (is_gpt) find_gpt_root(dev, pr, test); - blkid_free_probe(pr); out: if (err < 0) return EXIT_FAILURE; diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c index 51f364bf94..60f760ef77 100644 --- a/src/udev/udev-builtin-input_id.c +++ b/src/udev/udev-builtin-input_id.c @@ -31,6 +31,7 @@ #include <linux/input.h> #include "fd-util.h" +#include "missing.h" #include "stdio-util.h" #include "string-util.h" #include "udev.h" @@ -44,6 +45,17 @@ #define LONG(x) ((x)/BITS_PER_LONG) #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) +struct range { + unsigned start; + unsigned end; +}; + +/* key code ranges above BTN_MISC (start is inclusive, stop is exclusive)*/ +static const struct range high_key_blocks[] = { + { KEY_OK, BTN_DPAD_UP }, + { KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY } +}; + 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; @@ -137,6 +149,7 @@ static bool test_pointers(struct udev_device *dev, const unsigned long* bitmask_rel, const unsigned long* bitmask_props, bool test) { + int button, axis; bool has_abs_coordinates = false; bool has_rel_coordinates = false; bool has_mt_coordinates = false; @@ -172,7 +185,8 @@ static bool test_pointers(struct udev_device *dev, is_pointing_stick = test_bit(INPUT_PROP_POINTING_STICK, bitmask_props); stylus_or_pen = test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key); finger_but_no_pen = test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key); - has_mouse_button = test_bit(BTN_LEFT, bitmask_key); + for (button = BTN_MOUSE; button < BTN_JOYSTICK && !has_mouse_button; button++) + has_mouse_button = test_bit(button, bitmask_key); has_rel_coordinates = test_bit(EV_REL, bitmask_ev) && test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel); has_mt_coordinates = test_bit(ABS_MT_POSITION_X, bitmask_abs) && test_bit(ABS_MT_POSITION_Y, bitmask_abs); @@ -183,18 +197,15 @@ static bool test_pointers(struct udev_device *dev, has_touch = test_bit(BTN_TOUCH, bitmask_key); /* joysticks don't necessarily have buttons; e. g. * rudders/pedals are joystick-like, but buttonless; they have - * other fancy axes */ - has_joystick_axes_or_buttons = test_bit(BTN_TRIGGER, bitmask_key) || - test_bit(BTN_A, bitmask_key) || - test_bit(BTN_1, bitmask_key) || - test_bit(ABS_RX, bitmask_abs) || - test_bit(ABS_RY, bitmask_abs) || - test_bit(ABS_RZ, bitmask_abs) || - test_bit(ABS_THROTTLE, bitmask_abs) || - test_bit(ABS_RUDDER, bitmask_abs) || - test_bit(ABS_WHEEL, bitmask_abs) || - test_bit(ABS_GAS, bitmask_abs) || - test_bit(ABS_BRAKE, bitmask_abs); + * other fancy axes. Others have buttons only but no axes. */ + for (button = BTN_JOYSTICK; button < BTN_DIGI && !has_joystick_axes_or_buttons; button++) + has_joystick_axes_or_buttons = test_bit(button, bitmask_key); + for (button = BTN_TRIGGER_HAPPY1; button <= BTN_TRIGGER_HAPPY40 && !has_joystick_axes_or_buttons; button++) + has_joystick_axes_or_buttons = test_bit(button, bitmask_key); + for (button = BTN_DPAD_UP; button <= BTN_DPAD_RIGHT && !has_joystick_axes_or_buttons; button++) + has_joystick_axes_or_buttons = test_bit(button, bitmask_key); + for (axis = ABS_RX; axis < ABS_PRESSURE && !has_joystick_axes_or_buttons; axis++) + has_joystick_axes_or_buttons = test_bit(axis, bitmask_abs); if (has_abs_coordinates) { if (stylus_or_pen) @@ -209,7 +220,10 @@ static bool test_pointers(struct udev_device *dev, is_touchscreen = true; else if (has_joystick_axes_or_buttons) is_joystick = true; + } else if (has_joystick_axes_or_buttons) { + is_joystick = true; } + if (has_mt_coordinates) { if (stylus_or_pen) is_tablet = true; @@ -219,7 +233,9 @@ static bool test_pointers(struct udev_device *dev, is_touchscreen = true; } - if (has_rel_coordinates && has_mouse_button) + if (has_mouse_button && + (has_rel_coordinates || + !has_abs_coordinates)) /* mouse buttons and no axis */ is_mouse = true; if (is_pointing_stick) @@ -260,13 +276,16 @@ static bool test_key(struct udev_device *dev, found |= bitmask_key[i]; log_debug("test_key: checking bit block %lu for any keys; found=%i", (unsigned long)i*BITS_PER_LONG, found > 0); } - /* If there are no keys in the lower block, check the higher block */ + /* If there are no keys in the lower block, check the higher blocks */ if (!found) { - for (i = KEY_OK; i < BTN_TRIGGER_HAPPY; ++i) { - if (test_bit(i, bitmask_key)) { - log_debug("test_key: Found key %x in high block", i); - found = 1; - break; + unsigned block; + for (block = 0; block < (sizeof(high_key_blocks) / sizeof(struct range)); ++block) { + for (i = high_key_blocks[block].start; i < high_key_blocks[block].end; ++i) { + if (test_bit(i, bitmask_key)) { + log_debug("test_key: Found key %x in high block", i); + found = 1; + break; + } } } } diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c index 09024116f2..e316bb93ba 100644 --- a/src/udev/udev-builtin-keyboard.c +++ b/src/udev/udev-builtin-keyboard.c @@ -29,7 +29,7 @@ #include "string-util.h" #include "udev.h" -static const struct key *keyboard_lookup_key(const char *str, GPERF_LEN_TYPE len); +static const struct key_name *keyboard_lookup_key(const char *str, GPERF_LEN_TYPE len); #include "keyboard-keys-from-name.h" static int install_force_release(struct udev_device *dev, const unsigned *release, unsigned release_count) { @@ -76,7 +76,7 @@ static void map_keycode(int fd, const char *devnode, int scancode, const char *k unsigned key; } map; char *endptr; - const struct key *k; + const struct key_name *k; unsigned keycode_num; /* translate identifier to key code */ @@ -173,6 +173,9 @@ static void set_trackpoint_sensitivity(struct udev_device *dev, const char *valu if (r < 0) { log_error("Unable to parse POINTINGSTICK_SENSITIVITY '%s' for '%s'", value, udev_device_get_devnode(dev)); return; + } else if (val_i < 0 || val_i > 255) { + log_error("POINTINGSTICK_SENSITIVITY %d outside range [0..255] for '%s' ", val_i, udev_device_get_devnode(dev)); + return; } xsprintf(val_s, "%d", val_i); @@ -198,6 +201,7 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo unsigned release_count = 0; _cleanup_close_ int fd = -1; const char *node; + int has_abs = -1; node = udev_device_get_devnode(dev); if (!node) { @@ -258,6 +262,24 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo return EXIT_FAILURE; } + if (has_abs == -1) { + unsigned long bits; + int rc; + + rc = ioctl(fd, EVIOCGBIT(0, sizeof(bits)), &bits); + if (rc < 0) { + log_error_errno(errno, "Unable to EVIOCGBIT device \"%s\"", node); + return EXIT_FAILURE; + } + + has_abs = !!(bits & (1 << EV_ABS)); + if (!has_abs) + log_warning("EVDEV_ABS override set but no EV_ABS present on device \"%s\"", node); + } + + if (!has_abs) + continue; + override_abs(fd, node, evcode, udev_list_entry_get_value(entry)); } else if (streq(key, "POINTINGSTICK_SENSITIVITY")) set_trackpoint_sensitivity(dev, udev_list_entry_get_value(entry)); diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index bd7b789cad..46eb6114ff 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -45,6 +45,8 @@ * — PCI geographical location * [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>] * — USB port number chain + * v<slot> - VIO slot number (IBM PowerVM) + * a<vendor><model>i<instance> — Platform bus ACPI instance id * * All multi-function PCI devices will carry the [f<function>] number in the * device name, including the function 0 device. @@ -122,6 +124,8 @@ enum netname_type{ NET_BCMA, NET_VIRTIO, NET_CCW, + NET_VIO, + NET_PLATFORM, }; struct netnames { @@ -139,6 +143,8 @@ struct netnames { char usb_ports[IFNAMSIZ]; char bcma_core[IFNAMSIZ]; char ccw_busid[IFNAMSIZ]; + char vio_slot[IFNAMSIZ]; + char platform_path[IFNAMSIZ]; }; /* skip intermediate virtio devices */ @@ -319,6 +325,87 @@ out: return err; } +static int names_vio(struct udev_device *dev, struct netnames *names) { + struct udev_device *parent; + unsigned busid, slotid, ethid; + const char *syspath; + + /* check if our direct parent is a VIO device with no other bus in-between */ + parent = udev_device_get_parent(dev); + if (!parent) + return -ENOENT; + + if (!streq_ptr("vio", udev_device_get_subsystem(parent))) + return -ENOENT; + + /* The devices' $DEVPATH number is tied to (virtual) hardware (slot id + * selected in the HMC), thus this provides a reliable naming (e.g. + * "/devices/vio/30000002/net/eth1"); we ignore the bus number, as + * there should only ever be one bus, and then remove leading zeros. */ + syspath = udev_device_get_syspath(dev); + + if (sscanf(syspath, "/sys/devices/vio/%4x%4x/net/eth%u", &busid, &slotid, ðid) != 3) + return -EINVAL; + + xsprintf(names->vio_slot, "v%u", slotid); + names->type = NET_VIO; + return 0; +} + +#define _PLATFORM_TEST "/sys/devices/platform/vvvvPPPP" +#define _PLATFORM_PATTERN4 "/sys/devices/platform/%4s%4x:%2x/net/eth%u" +#define _PLATFORM_PATTERN3 "/sys/devices/platform/%3s%4x:%2x/net/eth%u" + +static int names_platform(struct udev_device *dev, struct netnames *names, bool test) { + struct udev_device *parent; + char vendor[5]; + unsigned model, instance, ethid; + const char *syspath, *pattern, *validchars; + + /* check if our direct parent is a platform device with no other bus in-between */ + parent = udev_device_get_parent(dev); + if (!parent) + return -ENOENT; + + if (!streq_ptr("platform", udev_device_get_subsystem(parent))) + return -ENOENT; + + syspath = udev_device_get_syspath(dev); + + /* syspath is too short, to have a valid ACPI instance */ + if (strlen(syspath) < sizeof _PLATFORM_TEST) + return -EINVAL; + + /* Vendor ID can be either PNP ID (3 chars A-Z) or ACPI ID (4 chars A-Z and numerals) */ + if (syspath[sizeof _PLATFORM_TEST - 1] == ':') { + pattern = _PLATFORM_PATTERN4; + validchars = UPPERCASE_LETTERS DIGITS; + } else { + pattern = _PLATFORM_PATTERN3; + validchars = UPPERCASE_LETTERS; + } + + /* Platform devices are named after ACPI table match, and instance id + * eg. "/sys/devices/platform/HISI00C2:00"); + * The Vendor (3 or 4 char), followed by hexdecimal model number : instance id. + */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + if (sscanf(syspath, pattern, vendor, &model, &instance, ðid) != 4) + return -EINVAL; +#pragma GCC diagnostic pop + + if (!in_charset(vendor, validchars)) + return -ENOENT; + + ascii_strlower(vendor); + + xsprintf(names->platform_path, "a%s%xi%u", vendor, model, instance); + names->type = NET_PLATFORM; + return 0; +} + static int names_pci(struct udev_device *dev, struct netnames *names) { struct udev_device *parent; @@ -591,6 +678,26 @@ static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool goto out; } + /* get ibmveth/ibmvnic slot-based names. */ + err = names_vio(dev, &names); + if (err >= 0 && names.type == NET_VIO) { + char str[IFNAMSIZ]; + + if (snprintf(str, sizeof(str), "%s%s", prefix, names.vio_slot) < (int)sizeof(str)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); + goto out; + } + + /* get ACPI path names for ARM64 platform devices */ + err = names_platform(dev, &names, test); + if (err >= 0 && names.type == NET_PLATFORM) { + char str[IFNAMSIZ]; + + if (snprintf(str, sizeof(str), "%s%s", prefix, names.platform_path) < (int)sizeof(str)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); + goto out; + } + /* get PCI based path names, we compose only PCI based paths */ err = names_pci(dev, &names); if (err < 0) diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index dbefbbe175..92e4f8d9c0 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -239,7 +239,7 @@ static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int int err = 0; memzero(&ctrl_msg_wire, sizeof(struct udev_ctrl_msg_wire)); - strcpy(ctrl_msg_wire.version, "udev-" VERSION); + strcpy(ctrl_msg_wire.version, "udev-" PACKAGE_VERSION); ctrl_msg_wire.magic = UDEV_CTRL_MAGIC; ctrl_msg_wire.type = type; diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index 3f9c3ed0cf..601f0ee13d 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -58,7 +58,7 @@ struct udev_event *udev_event_new(struct udev_device *dev) { event->udev = udev; udev_list_init(udev, &event->run_list, false); udev_list_init(udev, &event->seclabel_list, false); - event->birth_usec = clock_boottime_or_monotonic(); + event->birth_usec = now(CLOCK_MONOTONIC); return event; } @@ -520,7 +520,7 @@ static void spawn_read(struct udev_event *event, if (timeout_usec > 0) { usec_t age_usec; - age_usec = clock_boottime_or_monotonic() - event->birth_usec; + age_usec = now(CLOCK_MONOTONIC) - event->birth_usec; if (age_usec >= timeout_usec) { log_error("timeout '%s'", cmd); return; @@ -671,13 +671,13 @@ static int spawn_wait(struct udev_event *event, if (timeout_usec > 0) { usec_t usec, age_usec; - usec = now(clock_boottime_or_monotonic()); + usec = now(CLOCK_MONOTONIC); age_usec = usec - event->birth_usec; if (age_usec < timeout_usec) { if (timeout_warn_usec > 0 && timeout_warn_usec < timeout_usec && age_usec < timeout_warn_usec) { spawn.timeout_warn = timeout_warn_usec - age_usec; - r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(), + r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC, usec + spawn.timeout_warn, USEC_PER_SEC, on_spawn_timeout_warning, &spawn); if (r < 0) @@ -686,7 +686,7 @@ static int spawn_wait(struct udev_event *event, spawn.timeout = timeout_usec - age_usec; - r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(), + r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC, usec + spawn.timeout, USEC_PER_SEC, on_spawn_timeout, &spawn); if (r < 0) return r; diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 4d07b8fce0..294a322547 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -474,6 +474,13 @@ static int add_token(struct udev_rules *rules, struct token *token) { return 0; } +static void log_unknown_owner(int error, const char *entity, const char *owner) { + if (IN_SET(abs(error), ENOENT, ESRCH)) + log_error("Specified %s '%s' unknown", entity, owner); + else + log_error_errno(error, "Error resolving %s '%s': %m", entity, owner); +} + static uid_t add_uid(struct udev_rules *rules, const char *owner) { unsigned int i; uid_t uid = 0; @@ -489,12 +496,8 @@ 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) - log_error("specified user '%s' unknown", owner); - else - log_error_errno(r, "error resolving user '%s': %m", owner); - } + if (r < 0) + log_unknown_owner(r, "user", owner); /* grow buffer if needed */ if (rules->uids_cur+1 >= rules->uids_max) { @@ -536,12 +539,8 @@ 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) - log_error("specified group '%s' unknown", group); - else - log_error_errno(r, "error resolving group '%s': %m", group); - } + if (r < 0) + log_unknown_owner(r, "group", group); /* grow buffer if needed */ if (rules->gids_cur+1 >= rules->gids_max) { @@ -814,7 +813,7 @@ static const char *get_key_attribute(struct udev *udev, char *str) { attr++; pos = strchr(attr, '}'); if (pos == NULL) { - log_error("missing closing brace for format"); + log_error("Missing closing brace for format"); return NULL; } pos[0] = '\0'; @@ -2119,11 +2118,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules, event->owner_set = true; r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL); if (r < 0) { - if (r == -ENOENT || r == -ESRCH) - log_error("specified user '%s' unknown", owner); - else - log_error_errno(r, "error resolving user '%s': %m", owner); - + log_unknown_owner(r, "user", owner); event->uid = 0; } log_debug("OWNER %u %s:%u", @@ -2145,11 +2140,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules, event->group_set = true; r = get_group_creds(&gr, &event->gid); if (r < 0) { - if (r == -ENOENT || r == -ESRCH) - log_error("specified group '%s' unknown", group); - else - log_error_errno(r, "error resolving group '%s': %m", group); - + log_unknown_owner(r, "group", group); event->gid = 0; } log_debug("GROUP %u %s:%u", @@ -2536,19 +2527,19 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules) { } if (mode != (stats.st_mode & 01777)) { r = chmod(device_node, mode); - if (r < 0) { - log_error("failed to chmod '%s' %#o", device_node, mode); - return -errno; - } else + if (r < 0) + return log_error_errno(errno, "Failed to chmod '%s' %#o: %m", + device_node, mode); + else log_debug("chmod '%s' %#o", device_node, mode); } if ((uid != 0 && uid != stats.st_uid) || (gid != 0 && gid != stats.st_gid)) { r = chown(device_node, uid, gid); - if (r < 0) { - log_error("failed to chown '%s' %u %u ", device_node, uid, gid); - return -errno; - } else + if (r < 0) + return log_error_errno(errno, "Failed to chown '%s' %u %u: %m", + device_node, uid, gid); + else log_debug("chown '%s' %u %u", device_node, uid, gid); } diff --git a/src/udev/udev.pc.in b/src/udev/udev.pc.in index a0c2e82d47..e384a6f7c9 100644 --- a/src/udev/udev.pc.in +++ b/src/udev/udev.pc.in @@ -1,5 +1,5 @@ Name: udev Description: udev -Version: @VERSION@ +Version: @PACKAGE_VERSION@ udevdir=@udevlibexecdir@ diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index 70a5fa4d7a..69b0b9025c 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -352,7 +352,7 @@ static int trie_store(struct trie *trie, const char *filename) { int64_t size; struct trie_header_f h = { .signature = HWDB_SIG, - .tool_version = htole64(atoi(VERSION)), + .tool_version = htole64(atoi(PACKAGE_VERSION)), .header_size = htole64(sizeof(struct trie_header_f)), .node_size = htole64(sizeof(struct trie_node_f)), .child_entry_size = htole64(sizeof(struct trie_child_entry_f)), diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 90cdfa16c7..16b2aab0a1 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -376,7 +376,7 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) { export_prefix = optarg; break; case 'V': - printf("%s\n", VERSION); + printf("%s\n", PACKAGE_VERSION); return 0; case 'h': help(); diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c index f631834341..94a59186ed 100644 --- a/src/udev/udevadm-monitor.c +++ b/src/udev/udevadm-monitor.c @@ -41,9 +41,9 @@ static void print_device(struct udev_device *device, const char *source, int pro struct timespec ts; assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); - printf("%-6s[%"PRI_TIME".%06ld] %-8s %s (%s)\n", + printf("%-6s[%"PRI_TIME".%06"PRI_NSEC"] %-8s %s (%s)\n", source, - ts.tv_sec, ts.tv_nsec/1000, + ts.tv_sec, (nsec_t)ts.tv_nsec/1000, udev_device_get_action(device), udev_device_get_devpath(device), udev_device_get_subsystem(device)); diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c index 07b667f131..e8ffe2f309 100644 --- a/src/udev/udevadm-test.c +++ b/src/udev/udevadm-test.c @@ -59,7 +59,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) { {} }; - log_debug("version %s", VERSION); + log_debug("version %s", PACKAGE_VERSION); while ((c = getopt_long(argc, argv, "a:N:h", options, NULL)) >= 0) switch (c) { diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c index a6a873e5de..befc3bad7b 100644 --- a/src/udev/udevadm.c +++ b/src/udev/udevadm.c @@ -23,9 +23,10 @@ #include "selinux-util.h" #include "string-util.h" #include "udev.h" +#include "udev-util.h" static int adm_version(struct udev *udev, int argc, char *argv[]) { - printf("%s\n", VERSION); + printf("%s\n", PACKAGE_VERSION); return 0; } @@ -87,14 +88,16 @@ int main(int argc, char *argv[]) { unsigned int i; int rc = 1, c; - udev = udev_new(); - if (udev == NULL) - goto out; - + udev_parse_config(); log_parse_environment(); log_open(); + mac_selinux_init(); + udev = udev_new(); + if (udev == NULL) + goto out; + while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0) switch (c) { diff --git a/src/udev/udevd.c b/src/udev/udevd.c index ce2ff89b85..acbddd4180 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -284,12 +284,12 @@ static void worker_attach_event(struct worker *worker, struct event *event) { e = worker->manager->event; - assert_se(sd_event_now(e, clock_boottime_or_monotonic(), &usec) >= 0); + assert_se(sd_event_now(e, CLOCK_MONOTONIC, &usec) >= 0); - (void) sd_event_add_time(e, &event->timeout_warning, clock_boottime_or_monotonic(), + (void) sd_event_add_time(e, &event->timeout_warning, CLOCK_MONOTONIC, usec + arg_event_timeout_warn_usec, USEC_PER_SEC, on_event_timeout_warning, event); - (void) sd_event_add_time(e, &event->timeout, clock_boottime_or_monotonic(), + (void) sd_event_add_time(e, &event->timeout, CLOCK_MONOTONIC, usec + arg_event_timeout_usec, USEC_PER_SEC, on_event_timeout, event); } @@ -755,9 +755,9 @@ static void manager_exit(Manager *manager) { event_queue_cleanup(manager, EVENT_QUEUED); manager_kill_workers(manager); - assert_se(sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec) >= 0); + assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0); - r = sd_event_add_time(manager->event, NULL, clock_boottime_or_monotonic(), + r = sd_event_add_time(manager->event, NULL, CLOCK_MONOTONIC, usec + 30 * USEC_PER_SEC, USEC_PER_SEC, on_exit_timeout, manager); if (r < 0) return; @@ -791,7 +791,7 @@ static void event_queue_start(Manager *manager) { manager->exit || manager->stop_exec_queue) return; - assert_se(sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec) >= 0); + assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0); /* check for changed config, every 3 seconds at most */ if (manager->last_usec == 0 || (usec - manager->last_usec) > 3 * USEC_PER_SEC) { @@ -1492,7 +1492,7 @@ static int parse_argv(int argc, char *argv[]) { help(); return 0; case 'V': - printf("%s\n", VERSION); + printf("%s\n", PACKAGE_VERSION); return 0; case '?': return -EINVAL; @@ -1663,6 +1663,7 @@ int main(int argc, char *argv[]) { int r; log_set_target(LOG_TARGET_AUTO); + udev_parse_config(); log_parse_environment(); log_open(); @@ -1740,7 +1741,7 @@ int main(int argc, char *argv[]) { if (arg_daemonize) { pid_t pid; - log_info("starting version " VERSION); + log_info("starting version " PACKAGE_VERSION); /* connect /dev/null to stdin, stdout, stderr */ if (log_get_max_level() < LOG_DEBUG) { |