From bb69e9c613a2af5f4a6f388c76551dfc6d1aeb63 Mon Sep 17 00:00:00 2001 From: vilmibm Date: Thu, 18 Jun 2020 21:36:07 +0000 Subject: [PATCH] watch home dirs of logged in users --- cmd/bustled/main.go | 66 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/cmd/bustled/main.go b/cmd/bustled/main.go index d3ecb96..9b2a8b5 100644 --- a/cmd/bustled/main.go +++ b/cmd/bustled/main.go @@ -1,33 +1,73 @@ package main import ( + "bufio" + "bytes" "fmt" "log" "os" + "os/exec" + "path/filepath" + "strings" "github.com/fsnotify/fsnotify" ) +// TODO flesh out event handling with an eye towards eventual sampling + func initHomeWatcher() (*fsnotify.Watcher, error) { + fmt.Fprintf(os.Stderr, "setting up home watcher...\n") watcher, err := fsnotify.NewWatcher() if err != nil { return nil, err } - // TODO filepath.Walk over /home, adding to watcher - paths := []string{"/home/vilmibm", "/home/wren"} - - for _, path := range paths { - err = watcher.Add(path) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to watch path %s: %w", path, err) - continue - } + out, err := exec.Command("sh", "-c", "stats | jq .active_users[] | tr -d '\"'").Output() + if err != nil { + return nil, fmt.Errorf("failed to call and process stats: %w", err) } + + scanner := bufio.NewScanner(bytes.NewReader(out)) + for scanner.Scan() { + username := strings.TrimSpace(scanner.Text()) + home := filepath.Join("/home", username) + addHome(watcher, home) + } + return watcher, nil } -func watchHome(watcher *fsnotify.Watcher) { +func addHome(watcher *fsnotify.Watcher, homePath string) error { + fileCount := 0 + filepath.Walk(homePath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil + } + if info.IsDir() && strings.HasPrefix(info.Name(), ".") { + return filepath.SkipDir + } + fileCount++ + if info.Mode()&os.ModeSymlink != 0 { + return nil + } + + err = watcher.Add(path) + if err != nil && err.Error() != "permission denied" && err.Error() != "no such file or directory" { + fmt.Printf("%#v\n", err) + fmt.Println("Died at ", fileCount) + fmt.Printf("%#v\n", info) + panic(err.Error()) + } else { + fmt.Fprintf(os.Stderr, "watching %s\n", path) + } + return nil + }) + + return nil +} + +func watchHomes(watcher *fsnotify.Watcher) { + fmt.Fprintf(os.Stderr, "starting poll\n") for { select { case event, ok := <-watcher.Events: @@ -48,9 +88,11 @@ func watchHome(watcher *fsnotify.Watcher) { } func cli(args []string) int { + fmt.Fprintf(os.Stderr, "starting\n") watcher, err := initHomeWatcher() + fmt.Fprintf(os.Stderr, "watcher initialized\n") if err != nil { - fmt.Fprintf(os.Stderr, "failed to create watcher: %w", err) + fmt.Fprintf(os.Stderr, "failed to create watcher: %w\n", err) return 1 } defer watcher.Close() @@ -58,7 +100,7 @@ func cli(args []string) int { // TODO have an event bus to write to // TODO what is this done for do i need this done done := make(chan bool) - go watchHome(watcher) + go watchHomes(watcher) <-done return 0