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 }