github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/subsystem/entities.go (about)

     1  // Copyright 2023 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package subsystem
     5  
     6  type Subsystem struct {
     7  	Name        string
     8  	PathRules   []PathRule
     9  	Syscalls    []string
    10  	Lists       []string
    11  	Maintainers []string
    12  	Parents     []*Subsystem
    13  	// If NoReminders is true, there should be no monthly reports for the subsystem.
    14  	NoReminders bool
    15  	// If NoIndirectCc is true, the subsystem lists are not tagged in sub-subsystem reports.
    16  	NoIndirectCc bool
    17  }
    18  
    19  // ReachableParents returns the set of subsystems reachable from the current one.
    20  func (subsystem *Subsystem) ReachableParents() map[*Subsystem]struct{} {
    21  	ret := make(map[*Subsystem]struct{})
    22  	var dfs func(node *Subsystem)
    23  	dfs = func(node *Subsystem) {
    24  		for _, p := range node.Parents {
    25  			if p == subsystem {
    26  				panic("loop in the parents relation")
    27  			}
    28  			if _, visited := ret[p]; !visited {
    29  				ret[p] = struct{}{}
    30  				dfs(p)
    31  			}
    32  		}
    33  	}
    34  	dfs(subsystem)
    35  	return ret
    36  }
    37  
    38  // Emails returns the list of emails related to the subsystem.
    39  func (subsystem *Subsystem) Emails() []string {
    40  	ret := []string{}
    41  	// For the subsystem itself, we take both lists and maintainers.
    42  	ret = append(ret, subsystem.Lists...)
    43  	ret = append(ret, subsystem.Maintainers...)
    44  	// For its parent subsystems, we only take lists.
    45  	for parent := range subsystem.ReachableParents() {
    46  		if !parent.NoIndirectCc {
    47  			ret = append(ret, parent.Lists...)
    48  		}
    49  	}
    50  	return ret
    51  }
    52  
    53  func FilterList(list []*Subsystem, filter func(*Subsystem) bool) []*Subsystem {
    54  	keep := map[*Subsystem]bool{}
    55  	for _, item := range list {
    56  		keep[item] = filter(item)
    57  	}
    58  	newList := []*Subsystem{}
    59  	for _, item := range list {
    60  		if !keep[item] {
    61  			continue
    62  		}
    63  		newParents := []*Subsystem{}
    64  		for _, p := range item.Parents {
    65  			if keep[p] {
    66  				newParents = append(newParents, p)
    67  			}
    68  		}
    69  		item.Parents = newParents
    70  		newList = append(newList, item)
    71  	}
    72  	return newList
    73  }
    74  
    75  // PathRule describes the part of the directory tree belonging to a single subsystem.
    76  type PathRule struct {
    77  	IncludeRegexp string
    78  	// ExcludeRegexps are tested before IncludeRegexp.
    79  	ExcludeRegexp string
    80  }
    81  
    82  func (pr *PathRule) IsEmpty() bool {
    83  	return pr.IncludeRegexp == "" && pr.ExcludeRegexp == ""
    84  }