Files
overlord/Overlord-Client/cmd/agent/filesearch/lookup.go
T

115 lines
2.2 KiB
Go

package filesearch
import (
"log"
"os"
"path/filepath"
"runtime/debug"
"strings"
"sync"
)
var SkipDirs = map[string]bool{
"$recycle.bin": true,
"windows": true,
"system volume information": true,
}
type ResultFunc func(path string)
func LookupExe(exeName string, workers int, onResult ResultFunc) {
//garble:controlflow block_splits=10 junk_jumps=10 flatten_passes=2
if workers <= 0 {
workers = 8
}
lowerExe := strings.ToLower(exeName)
roots := driveRoots()
dirs := make(chan string, 256)
var inflight sync.WaitGroup
var wg sync.WaitGroup
for i := 0; i < workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
defer func() {
if r := recover(); r != nil {
log.Printf("[filesearch] worker panic: %v\n%s", r, debug.Stack())
}
}()
for dir := range dirs {
walkDir(dir, lowerExe, dirs, &inflight, onResult)
inflight.Done()
}
}()
}
for _, root := range roots {
entries, err := os.ReadDir(root)
if err != nil {
continue
}
for _, e := range entries {
if e.IsDir() {
if SkipDirs[strings.ToLower(e.Name())] {
continue
}
inflight.Add(1)
dirs <- filepath.Join(root, e.Name())
} else if strings.ToLower(e.Name()) == lowerExe {
onResult(filepath.Join(root, e.Name()))
}
}
}
go func() {
inflight.Wait()
close(dirs)
}()
wg.Wait()
}
func walkDir(root, lowerExe string, dirs chan<- string, inflight *sync.WaitGroup, onResult ResultFunc) {
entries, err := os.ReadDir(root)
if err != nil {
return
}
for _, e := range entries {
full := filepath.Join(root, e.Name())
if e.IsDir() {
if SkipDirs[strings.ToLower(e.Name())] {
continue
}
inflight.Add(1)
select {
case dirs <- full:
default:
inflight.Done()
walkDir(full, lowerExe, dirs, inflight, onResult)
}
} else if strings.ToLower(e.Name()) == lowerExe {
onResult(full)
}
}
}
func driveRoots() []string {
if os.PathSeparator == '\\' {
var roots []string
for c := 'A'; c <= 'Z'; c++ {
root := string(c) + ":\\"
if info, err := os.Stat(root); err == nil && info.IsDir() {
roots = append(roots, root)
}
}
if len(roots) == 0 {
roots = append(roots, "C:\\")
}
return roots
}
return []string{"/"}
}