Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# libudev
Golang native implementation Udev library

[![Go Report Card](https://goreportcard.com/badge/github.com/qubesome/libudev)](https://goreportcard.com/report/github.com/qubesome/libudev)
[![GoDoc](https://godoc.org/github.com/qubesome/libudev?status.svg)](https://godoc.org/github.com/qubesome/libudev)
[![GitHub release](https://img.shields.io/github/release/qubesome/libudev.svg)](https://github.com/qubesome/libudev/releases)
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/qubesome/libudev/badge)](https://scorecard.dev/viewer/?uri=github.com/qubesome/libudev)

Installation
Expand Down
26 changes: 17 additions & 9 deletions matcher/matcher.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
/*
Package matcher implements a service for filtering devices.

Matcher allows you to add multiple filter rules by using the method `AddRule`
and effectively filter the list of devices in a single pass.

By default, Matcher uses the `AND` comparison strategy, but you can set the filtering strategy to` OR`.
*/
// Package matcher implements a mechanism for filtering devices.
//
// Matcher allows you to add multiple filter rules by using the method `AddRule`
// and effectively filter the list of devices in a single pass.
//
// By default, Matcher uses the `AND` comparison strategy, but you can set the filtering strategy to` OR`.
package matcher

import (
Expand Down Expand Up @@ -50,7 +48,17 @@ func (m *Matcher) AddRule(rule Rule) {
m.rules = append(m.rules, rule)
}

func (m *Matcher) Match(devices []*types.Device) []*types.Device {
func (m *Matcher) Match(devices ...*types.Device) bool {
for _, v := range devices {
if m.matchDevice(v) {
return true
}
}

return false
}

func (m *Matcher) Matches(devices []*types.Device) []*types.Device {
var ret []*types.Device
for _, v := range devices {
if !m.matchDevice(v) {
Expand Down
24 changes: 12 additions & 12 deletions matcher/matcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,19 @@ func TestMatchDefault(t *testing.T) {
m := NewMatcher()
m.AddRule(NewRuleDevpath("devpaht-1"))
m.AddRule(NewRuleDevpath("devpaht-2"))
if len(m.Match(devices)) != 0 {
if len(m.Matches(devices)) != 0 {
t.Fatal("Devices was found incorrectly")
}

m2 := NewMatcher()
m2.AddRule(NewRuleDevpath("devpaht-.+"))
m2.AddRule(NewRuleDevpath("devpaht-[0-9]+"))
if len(m2.Match(devices)) != 2 {
if len(m2.Matches(devices)) != 2 {
t.Fatal("Not found two devices")
}

m3 := NewMatcher()
if len(m3.Match(devices)) != 0 {
if len(m3.Matches(devices)) != 0 {
t.Fatal("Empty rules Matcher finded not 0 devices")
}
}
Expand All @@ -68,34 +68,34 @@ func TestMatchAnd(t *testing.T) {
m.SetStrategy(StrategyAnd)
m.AddRule(NewRuleDevpath("devpaht-1"))
m.AddRule(NewRuleDevpath("devpaht-2"))
if len(m.Match(devices)) != 0 {
if len(m.Matches(devices)) != 0 {
t.Fatal("Devices was found incorrectly")
}

m2 := NewMatcher()
m2.SetStrategy(StrategyAnd)
m2.AddRule(NewRuleDevpath("devpaht-.+"))
m2.AddRule(NewRuleDevpath("devpaht-[0-9]+"))
if len(m2.Match(devices)) != 2 {
if len(m2.Matches(devices)) != 2 {
t.Fatal("Not found two devices")
}

m2.AddRule(NewRuleEnv("ENV-1", "[a-z]+"))
m2.AddRule(NewRuleEnv("ENV-2", "[0-9]+"))
m2.AddRule(NewRuleAttr("ATTR-1", "[a-z]+"))
m2.AddRule(NewRuleAttr("ATTR-2", "[0-9]+"))
if len(m2.Match(devices)) != 2 {
if len(m2.Matches(devices)) != 2 {
t.Fatal("Not found two devices")
}

m2.AddRule(NewRuleAttr("ATTR-2", "123"))
if len(m.Match(devices)) != 0 {
if len(m.Matches(devices)) != 0 {
t.Fatal("Devices was found incorrectly")
}

m3 := NewMatcher()
m3.SetStrategy(StrategyAnd)
if len(m3.Match(devices)) != 0 {
if len(m3.Matches(devices)) != 0 {
t.Fatal("Empty rules Matcher finded not 0 devices")
}
}
Expand All @@ -107,12 +107,12 @@ func TestMatchOr(t *testing.T) {
m.SetStrategy(StrategyOr)
m.AddRule(NewRuleDevpath("devpaht-1"))
m.AddRule(NewRuleDevpath("devpaht-3"))
if len(m.Match(devices)) != 1 {
if len(m.Matches(devices)) != 1 {
t.Fatal("Not found one device")
}

m.AddRule(NewRuleDevpath("devpaht-2"))
if len(m.Match(devices)) != 2 {
if len(m.Matches(devices)) != 2 {
t.Fatal("Not found two devices")
}

Expand All @@ -123,13 +123,13 @@ func TestMatchOr(t *testing.T) {
m2.AddRule(NewRuleEnv("ENV-2", "NOT_FOUND"))
m2.AddRule(NewRuleAttr("ATTR-1", "ghi456jkl"))
m2.AddRule(NewRuleAttr("ATTR-2", "NOT_FOUND"))
if len(m2.Match(devices)) != 2 {
if len(m2.Matches(devices)) != 2 {
t.Fatal("Not found two devices")
}

m3 := NewMatcher()
m3.SetStrategy(StrategyOr)
if len(m3.Match(devices)) != 0 {
if len(m3.Matches(devices)) != 0 {
t.Fatal("Empty rules Matcher finded not 0 devices")
}
}
Expand Down
58 changes: 58 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package libudev

import (
"os"
"regexp"

"github.com/qubesome/libudev/matcher"
)

type Option func(*scanner)

type options struct {
matcher *matcher.Matcher

pathFilterPattern *regexp.Regexp

devicesRoot *os.Root
udevDataRoot *os.Root
}

// WithPathFilterPattern sets a pattern to filter out device paths that
// are irrelevant to the query. This speeds up the scanning process, as
// the scanner won't deal with files (and devices) that do not match the
// regex.
//
// For example, when querying USB devices, this could be used:
// libudev.WithPathFilterPattern(regexp.MustCompile("(?i)^.*pci0000:00.*usb.*"))
func WithPathFilterPattern(p *regexp.Regexp) Option {
return func(o *scanner) {
o.opts.pathFilterPattern = p
}
}

// WithMatcher sets a matcher to the scanner, so that only devices matching
// the rules are returned.
func WithMatcher(m *matcher.Matcher) Option {
return func(o *scanner) {
o.opts.matcher = m
}
}

// WithDevicesRoot provides a way to set a different os.Root to be used
// as the Devices dir. When not provided, defaults to an os.Root pointing
// to /sys/devices.
func WithDevicesRoot(r *os.Root) Option {
return func(o *scanner) {
o.opts.devicesRoot = r
}
}

// WithUDevDataRoot provides a way to set a different os.Root to be used
// as the udev data dir. When not provided, defaults to an os.Root pointing
// to /run/udev/data.
func WithUDevDataRoot(r *os.Root) Option {
return func(o *scanner) {
o.opts.udevDataRoot = r
}
}
Loading
Loading