diff --git a/src/evdev.c b/src/evdev.c index cac971f4..ac633cac 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -2095,23 +2095,21 @@ static bool evdev_device_have_same_syspath(struct udev_device *udev_device, int fd) { struct udev *udev = udev_device_get_udev(udev_device); - struct udev_device *udev_device_new = NULL; + _unref_(udev_device) *udev_device_new = NULL; struct stat st; - bool rc = false; if (fstat(fd, &st) < 0) - goto out; + return false; udev_device_new = udev_device_new_from_devnum(udev, 'c', st.st_rdev); + /* In a jail/container where devfs doesn't expose the device, we + * cannot verify the syspath. Trust the fd provider (e.g. seatd). + */ if (!udev_device_new) - goto out; + return true; - rc = streq(udev_device_get_syspath(udev_device_new), - udev_device_get_syspath(udev_device)); -out: - if (udev_device_new) - udev_device_unref(udev_device_new); - return rc; + return streq(udev_device_get_syspath(udev_device_new), + udev_device_get_syspath(udev_device)); } static bool diff --git a/src/path-seat.c b/src/path-seat.c index d76bea0a..6c496d47 100644 --- a/src/path-seat.c +++ b/src/path-seat.c @@ -332,8 +332,20 @@ udev_device_from_devnode(struct libinput *libinput, struct stat st; size_t count = 0; - if (stat(devnode, &st) < 0) + if (stat(devnode, &st) < 0) { +#ifdef __FreeBSD__ + /* + * If stat fails (e.g. device node not visible in a jail), fall + * back to creating a udev device directly from the devnode + * path. This works in FreeBSD because libudev-devd constructs + * devices using the information exposed by the kernel through + * the sysctl interface. + */ + return udev_device_new_from_syspath(udev, devnode); +#else return NULL; +#endif + } dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev);