github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/lib/fsutil/watchFile_linux.go (about) 1 package fsutil 2 3 import ( 4 "io" 5 "os" 6 "path" 7 "sync" 8 9 "github.com/Cloud-Foundations/Dominator/lib/log" 10 "gopkg.in/fsnotify/fsnotify.v0" 11 ) 12 13 var ( 14 lock sync.RWMutex 15 watchers []*fsnotify.Watcher 16 ) 17 18 func watchFileWithFsNotify(pathname string, channel chan<- io.ReadCloser, 19 logger log.Logger) bool { 20 watcher, err := fsnotify.NewWatcher() 21 if err != nil { 22 logger.Println("Error creating watcher:", err) 23 return false 24 } 25 lock.Lock() 26 defer lock.Unlock() 27 watchers = append(watchers, watcher) 28 pathname = path.Clean(pathname) 29 dirname := path.Dir(pathname) 30 if err := watcher.WatchFlags(dirname, fsnotify.FSN_CREATE); err != nil { 31 logger.Println("Error adding watch:", err) 32 return false 33 } 34 go waitForNotifyEvents(watcher, pathname, channel, logger) 35 return true 36 } 37 38 func watchFileStopWithFsNotify() bool { 39 lock.Lock() 40 defer lock.Unlock() 41 // Send cleanup notification to watchers. 42 for _, watcher := range watchers { 43 watcher.Close() 44 } 45 // Wait for cleanup of each watcher. 46 for _, watcher := range watchers { 47 for { 48 if _, ok := <-watcher.Event; !ok { 49 break 50 } 51 } 52 } 53 watchers = nil 54 return true 55 } 56 57 func waitForNotifyEvents(watcher *fsnotify.Watcher, pathname string, 58 channel chan<- io.ReadCloser, logger log.Logger) { 59 if file, err := os.Open(pathname); err == nil { 60 channel <- file 61 } 62 for { 63 select { 64 case event, ok := <-watcher.Event: 65 if !ok { 66 return 67 } 68 if path.Clean(event.Name) != pathname { 69 continue 70 } 71 if file, err := os.Open(pathname); err != nil { 72 if os.IsNotExist(err) { 73 continue 74 } 75 if logger != nil { 76 logger.Printf("Error opening file: %s: %s\n", pathname, err) 77 } 78 } else { 79 channel <- file 80 } 81 case err, ok := <-watcher.Error: 82 if !ok { 83 return 84 } 85 logger.Println("Error with watcher:", err) 86 } 87 } 88 }