aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/kobject/event.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/kobject/event.go')
-rw-r--r--internal/kobject/event.go90
1 files changed, 90 insertions, 0 deletions
diff --git a/internal/kobject/event.go b/internal/kobject/event.go
new file mode 100644
index 00000000..33cb91b8
--- /dev/null
+++ b/internal/kobject/event.go
@@ -0,0 +1,90 @@
+package kobject
+
+import (
+ "errors"
+ "strconv"
+ "strings"
+ "unsafe"
+
+ "hakurei.app/internal/uevent"
+)
+
+// Event is a [uevent.Message] with known environment variables processed.
+type Event struct {
+ // alloc_uevent_skb: action_string
+ Action uevent.KobjectAction `json:"action"`
+ // alloc_uevent_skb: devpath
+ DevPath string `json:"devpath"`
+
+ // Uninterpreted environment variable pairs. An entry missing a separator
+ // gains the value "\x00".
+ Env map[string]string `json:"env"`
+
+ // SEQNUM value set by the kernel.
+ Sequence uint64 `json:"seqnum"`
+ // SYNTH_UUID value set on trigger, nil denotes a non-synthetic event.
+ Synth *uevent.UUID `json:"synth_uuid,omitempty"`
+ // SUBSYSTEM value set by the kernel.
+ Subsystem string `json:"subsystem"`
+}
+
+// Populate populates e with the contents of a [uevent.Message].
+//
+// The ACTION and DEVPATH environment variables are ignored and assumed to be
+// consistent with the header.
+func (e *Event) Populate(reportErr func(error), m *uevent.Message) {
+ if reportErr == nil {
+ reportErr = func(error) {}
+ }
+
+ *e = Event{
+ Action: m.Action,
+ DevPath: m.DevPath,
+ Env: make(map[string]string),
+ }
+
+ for _, s := range m.Env {
+ k, v, ok := strings.Cut(s, "=")
+ if !ok {
+ if _, ok = e.Env[s]; !ok {
+ e.Env[s] = "\x00"
+ }
+ continue
+ }
+
+ switch k {
+ case "ACTION", "DEVPATH":
+ continue
+
+ case "SEQNUM":
+ seq, err := strconv.ParseUint(v, 10, 64)
+ if err != nil {
+ if _e := errors.Unwrap(err); _e != nil {
+ err = _e
+ }
+ reportErr(err)
+
+ e.Env[k] = v
+ continue
+ }
+ e.Sequence = seq
+
+ case "SYNTH_UUID":
+ var uuid uevent.UUID
+ err := uuid.UnmarshalText(unsafe.Slice(unsafe.StringData(v), len(v)))
+ if err != nil {
+ reportErr(err)
+
+ e.Env[k] = v
+ continue
+ }
+ e.Synth = &uuid
+
+ case "SUBSYSTEM":
+ e.Subsystem = v
+
+ default:
+ e.Env[k] = v
+ }
+ }
+}