blob: ad5d3a25744aa597a3bfd31e7d5485e2bb6b751d [file] [log] [blame]
// Copyright 2023 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package subsystem
import (
"regexp"
"strings"
)
type PathMatcher struct {
matches []*match
}
type match struct {
include *regexp.Regexp
exclude *regexp.Regexp
object *Subsystem
}
func MakePathMatcher(list []*Subsystem) *PathMatcher {
m := &PathMatcher{}
for _, item := range list {
m.register(item)
}
return m
}
func (p *PathMatcher) register(item *Subsystem) {
onlyInclude := []string{}
list := []PathRule{}
for _, r := range item.PathRules {
if r.ExcludeRegexp == "" {
// It's expected that almost everything will go to this branch.
onlyInclude = append(onlyInclude, r.IncludeRegexp)
} else {
list = append(list, r)
}
}
if len(onlyInclude) > 0 {
list = append(list, PathRule{
IncludeRegexp: strings.Join(onlyInclude, "|"),
})
}
for _, rule := range list {
p.matches = append(p.matches, buildMatch(rule, item))
}
}
func (p *PathMatcher) Match(path string) []*Subsystem {
ret := []*Subsystem{}
for _, m := range p.matches {
if m.exclude != nil && m.exclude.MatchString(path) {
continue
}
if m.include != nil && !m.include.MatchString(path) {
continue
}
ret = append(ret, m.object)
}
return ret
}
func buildMatch(rule PathRule, item *Subsystem) *match {
m := &match{object: item}
if rule.IncludeRegexp != "" {
m.include = regexp.MustCompile(rule.IncludeRegexp)
}
if rule.ExcludeRegexp != "" {
m.exclude = regexp.MustCompile(rule.ExcludeRegexp)
}
return m
}