github.com/jaypipes/ghw@v0.21.1/pkg/snapshot/clonetree_linux.go (about)

     1  //
     2  // Use and distribution licensed under the Apache license version 2.
     3  //
     4  // See the COPYING file in the root project directory for full text.
     5  //
     6  
     7  package snapshot
     8  
     9  import (
    10  	"os"
    11  	"path/filepath"
    12  )
    13  
    14  func setupScratchDir(scratchDir string) error {
    15  	var createPaths = []string{
    16  		"sys/block",
    17  	}
    18  
    19  	for _, path := range createPaths {
    20  		if err := os.MkdirAll(filepath.Join(scratchDir, path), os.ModePerm); err != nil {
    21  			return err
    22  		}
    23  	}
    24  
    25  	return createBlockDevices(scratchDir)
    26  }
    27  
    28  // ExpectedCloneStaticContent return a slice of glob patterns which represent the pseudofiles
    29  // ghw cares about, and which are independent from host specific topology or configuration,
    30  // thus are safely represented by a static slice - e.g. they don't need to be discovered at runtime.
    31  func ExpectedCloneStaticContent() []string {
    32  	return []string{
    33  		"/proc/cpuinfo",
    34  		"/proc/meminfo",
    35  		"/proc/self/mounts",
    36  		"/sys/devices/system/cpu/cpu*/cache/index*/*",
    37  		"/sys/devices/system/cpu/cpu*/topology/*",
    38  		"/sys/devices/system/memory/block_size_bytes",
    39  		"/sys/devices/system/memory/memory*/online",
    40  		"/sys/devices/system/memory/memory*/state",
    41  		"/sys/devices/system/node/has_*",
    42  		"/sys/devices/system/node/online",
    43  		"/sys/devices/system/node/possible",
    44  		"/sys/devices/system/node/node*/cpu*",
    45  		"/sys/devices/system/node/node*/cpu*/online",
    46  		"/sys/devices/system/node/node*/distance",
    47  		"/sys/devices/system/node/node*/meminfo",
    48  		"/sys/devices/system/node/node*/memory*",
    49  		"/sys/devices/system/node/node*/hugepages/hugepages-*/*",
    50  	}
    51  }
    52  
    53  type filterFunc func(string) bool
    54  
    55  // cloneContentByClass copies all the content related to a given device class
    56  // (devClass), possibly filtering out devices whose name does NOT pass a
    57  // filter (filterName). Each entry in `/sys/class/$CLASS` is actually a
    58  // symbolic link. We can filter out entries depending on the link target.
    59  // Each filter is a simple function which takes the entry name or the link
    60  // target and must return true if the entry should be collected, false
    61  // otherwise. Last, explicitly collect a list of attributes for each entry,
    62  // given as list of glob patterns as `subEntries`.
    63  // Return the final list of glob patterns to be collected.
    64  func cloneContentByClass(devClass string, subEntries []string, filterName filterFunc, filterLink filterFunc) []string {
    65  	var fileSpecs []string
    66  
    67  	// warning: don't use the context package here, this means not even the linuxpath package.
    68  	// TODO(fromani) remove the path duplication
    69  	sysClass := filepath.Join("sys", "class", devClass)
    70  	entries, err := os.ReadDir(sysClass)
    71  	if err != nil {
    72  		// we should not import context, hence we can't Warn()
    73  		return fileSpecs
    74  	}
    75  	for _, entry := range entries {
    76  		devName := entry.Name()
    77  
    78  		if !filterName(devName) {
    79  			continue
    80  		}
    81  
    82  		devPath := filepath.Join(sysClass, devName)
    83  		dest, err := os.Readlink(devPath)
    84  		if err != nil {
    85  			continue
    86  		}
    87  
    88  		if !filterLink(dest) {
    89  			continue
    90  		}
    91  
    92  		// so, first copy the symlink itself
    93  		fileSpecs = append(fileSpecs, devPath)
    94  		// now we have to clone the content of the actual entry
    95  		// related (and found into a subdir of) the backing hardware
    96  		// device
    97  		devData := filepath.Clean(filepath.Join(sysClass, dest))
    98  		for _, subEntry := range subEntries {
    99  			fileSpecs = append(fileSpecs, filepath.Join(devData, subEntry))
   100  		}
   101  	}
   102  
   103  	return fileSpecs
   104  }
   105  
   106  // filterNone allows all content, filtering out none of it
   107  func filterNone(_ string) bool {
   108  	return true
   109  }