Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions udev-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <assert.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
Expand Down Expand Up @@ -267,6 +268,7 @@ create_evdev_handler(struct udev_device *ud)
unsigned long sw_bits[NLONGS(SW_CNT)];
unsigned long prp_bits[NLONGS(INPUT_PROP_CNT)];
struct input_id id;
uint64_t devnum = 0;
#ifdef HAVE_SYSCTLBYNAME
const char *unit;
char mib[32];
Expand Down Expand Up @@ -316,6 +318,16 @@ create_evdev_handler(struct udev_device *ud)
if (sysctlbyname(mib, prp_bits, &len, NULL, 0) < 0)
goto use_ioctl;

/*
* devnum sysctl is optional: sysctlbyname on kernels predacting its
* introduction will fail but that does not mean we should fall back to
* ioctl. We just leave devnum untouched, with its initialization value
* of zero.
*/
snprintf(mib, sizeof(mib), "kern.evdev.input.%s.devnum", unit);
len = sizeof(devnum);
(void)sysctlbyname(mib, &devnum, &len, NULL, 0);

goto found_values;

use_ioctl:
Expand Down Expand Up @@ -346,6 +358,11 @@ create_evdev_handler(struct udev_device *ud)
#ifdef HAVE_SYSCTLBYNAME
found_values:
#endif
if (devnum != 0) {
udev_list_insertf(udev_device_get_properties_list(ud),
"DEVNUM", "%" PRIu64, devnum);
}

/* Derived from EvdevProbe() function of xf86-input-evdev driver */
has_keys = bit_find(key_bits, 0, BTN_MISC);
has_buttons = bit_find(key_bits, BTN_MISC, BTN_JOYSTICK);
Expand Down
12 changes: 12 additions & 0 deletions udev-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,20 @@ udev_device_get_devnum(struct udev_device *ud)
{
const char *devpath;
struct stat st;
const char *dn;

TRC("(%p) %s", ud, ud->syspath);

/*
* If a DEVNUM udev property is set (populated from a kernel
* sysctl by the evdev create handler), trust it. This avoids a
* stat(2) that would fail when the device node is not visible, such as
* in a jail without devfs.
*/
dn = udev_device_get_property_value(ud, "DEVNUM");
if (dn != NULL)
return ((dev_t)strtoull(dn, NULL, 10));

devpath = get_devpath_by_syspath(ud->syspath);
if (devpath == NULL ||
stat(devpath, &st) < 0 ||
Expand Down