5 Commits
Author SHA1 Message Date
Joachim Wiberg 59945b87f7 keventd: load udev rules in udev's order, with masking
The rules directories were read one after the other, each sorted on
its own.  udev instead sorts all files from all directories together
and lets a file mask one of the same name in a lower priority
directory.  The difference broke both standard override idioms
without a sound: copying a rules file to /etc/udev/rules.d/ to edit
it left the original running too, and symlinking a name to /dev/null
disabled nothing.

Collect everything with glob(), drop entries shadowed by a later
directory, and sort the survivors by filename, same as udev and the
tmpfiles.d handling in Finit itself.  The -r directory sits above
/etc/ so a test ruleset can override anything shipped.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-29 09:26:18 +02:00
Joachim Wiberg 7eb32bc543 keventd: one condition emitter, one file reader, one clock
Three copies of read-first-line-from-a-file (sysfs_read_file, a
static sysfs_read, fgetline), two condition emitters symlinking the
same reconf marker (cond_emit, sys_cond), two seqnum-stable loops,
and five hand-rolled logit() prototypes, none with a printf
attribute, so no format string was ever checked.

Keep one of each: cond_emit() is exported and mkpaths its parents,
which also retires init_dev_condition_dir() and the sys/ directory
priming loop; logit() moves to keventd.h with the format attribute;
the stability test becomes seqnum_stable(), shared by the coldplug
gate and settle; kev_now_ms() serves dbus.c too.  rule_ctx_free()
and kev_seq_baseline() had one caller each in their own files, now
static.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-16 22:03:45 +02:00
Joachim Wiberg e4d9193f06 keventd: skip futile fork for missing /lib/udev/<helper>
When a rule references an absolute helper path (e.g. /lib/udev/fido_id,
/lib/udev/scsi_id) that the system does not ship and we have no matching
builtin either, return 1 from try_builtin_fallback() so the caller does
not fork /bin/sh on a binary that's known to be missing.  Previously
each such uevent left a zombie 127 child for keventd's sigchld_cb to
reap -- harmless but noisy and wasteful at coldplug.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-16 22:03:33 +02:00
Joachim Wiberg 9d5e646e46 keventd: drop SIGCHLD save/restore dance, libuev reaps for us
modprobe_load() and run_program() used to temporarily restore the
default SIGCHLD handler around fork+waitpid because the main loop set
SIGCHLD=SIG_IGN.  With the libuev conversion, sigchld_cb in keventd.c
handles reaping via signalfd -- and signalfd does not interfere with
synchronous waitpid(pid, ...) -- so the dance is dead code.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-16 22:03:33 +02:00
Joachim Wiberg 67d61a8282 keventd: add udev rules engine
Transform keventd from a power-supply monitor + basic hotplug handler into
a full udev-compatible device manager.

Rules engine (rules.c):
- Full .rules file parser covering all udev key types: ACTION, KERNEL,
  SUBSYSTEM, DEVPATH, ENV, ATTR, SYSCTL, TAG, RESULT, PROGRAM, TEST,
  parent-chain KERNELS/SUBSYSTEMS/ATTRS/DRIVERS, and more
- Pattern matching: plain string, fnmatch glob, and pipe-separated alternatives
- Operators: ==, !=, =, +=, -=, :=
- Assignments: NAME=, MODE=, OWNER=, GROUP=, SYMLINK+=, ENV{k}=, TAG+=, RUN+=
- IMPORT{program|file|builtin|parent|cmdline|db}=
- PROGRAM= with stdout capture for subsequent RESULT== matching
- GOTO=/LABEL= flow control
- Loads *.rules from /lib/udev/rules.d, /run/udev/rules.d, /etc/udev/rules.d
  and an optional extra directory (-r DIR); reloads on SIGHUP

Builtin framework (builtin.c):
- kmod:     load module by MODALIAS or explicit alias
- hwdb:     match device against *.hwdb text files in udev hwdb dirs; builds
	    correct lookup key per subsystem — evdev:input:b*v*p*e* for input,
	    usb:v*p* for USB, raw modalias for PCI/platform
- path_id:  build stable ID_PATH / ID_PATH_TAG from sysfs topology (PCI, USB,
	    ATA, NVMe, platform, ACPI, virtio)
- usb_id:   read idVendor/idProduct/bcdDevice/serial from sysfs; look up
	    ID_VENDOR_FROM_DATABASE and ID_MODEL_FROM_DATABASE from usb.ids
	    (hwdata package) when available; silent fallback when absent
- input_id: classify input devices (keyboard, mouse, joystick, touchscreen,
	    touchpad) from evdev capability bitmasks in sysfs
- net_id:   generate predictable names — MAC-based enx<mac> and PCI-slot-based
	    enp<bus>s<dev>[f<func>]
- blkid:    probe filesystem type, UUID, and label via libblkid; sets ID_FS_*
	    and ID_PART_TABLE_* properties

Network interface renaming (uevent.c):
- netdev_add() renames interfaces via SIOCSIFNAME when a NAME= rule matched,
  then sets the Finit dev/ condition on the final name; and any setup using
  persistent interface naming via udev rules

Device node and symlink improvements (uevent.c):
- NAME=, MODE=, OWNER=, GROUP= overrides from matched rules applied at
  mknod/chown time, falling back to the built-in permission table
- SYMLINK+= links from rules applied alongside built-in by-id/by-path links

Device property database (udevdb.c):
- Persist per-device E:/S:/I: records to /run/udev/data/ on ADD/CHANGE,
  delete on REMOVE; IMPORT{db}= restores saved properties into event env

Build:
- libblkid (util-linux) is now required for keventd

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-16 22:03:31 +02:00