...

Source file src/edge-infra.dev/pkg/lib/kernel/devices/matcher.go

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

     1  package devices
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  )
     7  
     8  var (
     9  	subsystemProperty = "SUBSYSTEM"
    10  )
    11  
    12  // Matcher is the top-level matcher for devices. Rule sets
    13  // are evaluated using OR operator
    14  type Matcher struct {
    15  	matchAll bool
    16  	rules    []*Rule
    17  }
    18  
    19  // MatchAll will search /sys/devices and match all devices in the tree
    20  func (m *Matcher) MatchAll() *Matcher {
    21  	m.matchAll = true
    22  	return m
    23  }
    24  
    25  // WithRule will add a rule to the matcher
    26  func (m *Matcher) WithRules(newRules ...*Rule) *Matcher {
    27  	m.rules = append(m.rules, newRules...)
    28  	return m
    29  }
    30  
    31  // MatchDevice will iterate the rules and attempt to evaluate if the device
    32  // matches (properties and attributes).
    33  func (m *Matcher) MatchDevice(device Device) bool {
    34  	if m.matchAll {
    35  		return true
    36  	}
    37  	return m.allRulesMatch(device)
    38  }
    39  
    40  // allRulesMatch attempts to evaluate all rules within a rule set against given device
    41  func (m *Matcher) allRulesMatch(device Device) bool {
    42  	for _, r := range m.rules {
    43  		if r.ruleType == attributeRule {
    44  			attrMatched := r.isAttributeEqual(device)
    45  			if !attrMatched {
    46  				return false
    47  			}
    48  		} else {
    49  			propMatched := r.isPropertyEqual(device)
    50  			if !propMatched {
    51  				return false
    52  			}
    53  		}
    54  	}
    55  	return true
    56  }
    57  
    58  // SearchPaths returns list of /sys search paths based on
    59  // the properties and attributes of device i.e. /sys/class/usb is
    60  // search path for devices with usb subsystem.
    61  func (m *Matcher) SearchPaths() []string {
    62  	if m.matchAll {
    63  		return []string{sysDevicePath}
    64  	}
    65  
    66  	searchPaths := []string{}
    67  	for _, r := range m.rules {
    68  		if r.name != subsystemProperty {
    69  			continue
    70  		}
    71  
    72  		// check class path
    73  		classPath := filepath.Join(SysPath, "class", r.subsystem)
    74  		if _, err := os.ReadDir(classPath); err == nil {
    75  			searchPaths = append(searchPaths, classPath)
    76  		}
    77  
    78  		// check bus path
    79  		busPath := filepath.Join(SysPath, "bus", r.subsystem)
    80  		if _, err := os.ReadDir(busPath); err == nil {
    81  			searchPaths = append(searchPaths, busPath)
    82  		}
    83  		return searchPaths
    84  	}
    85  	return []string{}
    86  }
    87  
    88  // New creates a new matcher
    89  func NewMatcher() *Matcher {
    90  	return &Matcher{}
    91  }
    92  

View as plain text