...

Source file src/edge-infra.dev/pkg/lib/kernel/udev/uevent.go

Documentation: edge-infra.dev/pkg/lib/kernel/udev

     1  package udev
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  	"strings"
     8  	"time"
     9  )
    10  
    11  // uevent buffer size https://elixir.bootlin.com/linux/latest/source/include/linux/kobject.h#L33
    12  const MaxSize = 4096
    13  
    14  // uevent field enums
    15  type Event string
    16  
    17  const (
    18  	Action         Event = "ACTION"
    19  	SequenceNumber Event = "SEQNUM"
    20  	SubSystem      Event = "SUBSYSTEM"
    21  	SysPath        Event = "DEVPATH"
    22  	DevName        Event = "DEVNAME"
    23  	Major          Event = "MAJOR"
    24  	Minor          Event = "MINOR"
    25  )
    26  
    27  // uevent action enums
    28  type ActionType string
    29  
    30  const (
    31  	AddAction    ActionType = "add"
    32  	RemoveAction ActionType = "remove"
    33  	ChangeAction ActionType = "change"
    34  	BindAction   ActionType = "bind"
    35  	UnbindAction ActionType = "unbind"
    36  )
    37  
    38  const (
    39  	UdevEvent   = "UDEV"
    40  	KernelEvent = "KERNEL"
    41  	magicNumber = "libudev\x00"
    42  )
    43  
    44  type EventType string
    45  
    46  type UEvent struct {
    47  	Action         ActionType
    48  	SequenceNumber string
    49  	EventType      string
    50  	SubSystem      string
    51  	SysPath        string
    52  	DevName        string
    53  	Major          string
    54  	Minor          string
    55  	Timestamp      time.Time
    56  
    57  	// map of uevent key-value pairs
    58  	EnvVars map[string]string
    59  	data    *[]byte
    60  }
    61  
    62  // FromBuffer returns uevent from bytes data passed into it
    63  func FromBuffer(b *bytes.Buffer) *UEvent {
    64  	data := b.Bytes()
    65  	return &UEvent{
    66  		EnvVars:   map[string]string{},
    67  		data:      &data,
    68  		Timestamp: time.Now(),
    69  	}
    70  }
    71  
    72  func (ue *UEvent) FromBytes(kvBytes []byte) *UEvent {
    73  	kv := strings.Replace(string(kvBytes), "\u0001", "", -1) // remove start of heading
    74  	kv = strings.Replace(kv, "\u0010", "", -1)               // remove data link escape
    75  
    76  	i := strings.Index(kv, "=")
    77  	if i < 0 {
    78  		// drop if key:value unknown
    79  		return ue
    80  	}
    81  
    82  	// splits the string into key, pair values
    83  	k, v := kv[:i], kv[i+1:len(kv)-1]
    84  	ue.EnvVars[k] = v
    85  
    86  	// map uevent key and value to uevent struct
    87  	switch Event(k) {
    88  	case Action:
    89  		ue.Action = ActionType(v)
    90  	case SubSystem:
    91  		ue.SubSystem = v
    92  	case SysPath:
    93  		ue.SysPath = v
    94  	case Major:
    95  		ue.Major = v
    96  	case Minor:
    97  		ue.Minor = v
    98  	case DevName:
    99  		ue.DevName = v
   100  	case SequenceNumber:
   101  		ue.SequenceNumber = v
   102  	}
   103  	return ue
   104  }
   105  
   106  func (ue *UEvent) ToBytes() *[]byte {
   107  	return ue.data
   108  }
   109  
   110  // Parses the buffer and converts the stream to a UEvent object
   111  func Decode(buf []byte) (ue *UEvent, err error) {
   112  	dataBuffer := bytes.NewBuffer(bytes.Clone(buf))
   113  	ue = FromBuffer(dataBuffer)
   114  	ue.EventType = KernelEvent
   115  
   116  loop:
   117  	for {
   118  		kvBytes, err := dataBuffer.ReadBytes(0x00)
   119  		if errors.Is(err, io.EOF) || len(kvBytes) == 0 {
   120  			break loop
   121  		}
   122  		if err != nil {
   123  			return ue, err
   124  		}
   125  
   126  		// identify udev events as opposed to kernel events
   127  		if string(kvBytes) == magicNumber {
   128  			ue.EventType = UdevEvent
   129  		}
   130  
   131  		// convert the bytes to uevent object
   132  		ue = ue.FromBytes(kvBytes)
   133  	}
   134  	return ue, nil
   135  }
   136  

View as plain text