mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-30 10:16:33 +08:00
90 lines
1.4 KiB
Go
90 lines
1.4 KiB
Go
package gonotify
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
)
|
|
|
|
// FileWatcher waits for events generated by filesystem for a specific list of file paths, including
|
|
// IN_CREATE for not yet existing files and IN_DELETE for removed.
|
|
type FileWatcher struct {
|
|
C chan FileEvent
|
|
}
|
|
|
|
// NewFileWatcher creates FileWatcher with provided inotify mask and list of files to wait events for.
|
|
func NewFileWatcher(ctx context.Context, mask uint32, files ...string) (*FileWatcher, error) {
|
|
|
|
f := &FileWatcher{
|
|
C: make(chan FileEvent),
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
|
|
inotify, err := NewInotify(ctx)
|
|
if err != nil {
|
|
cancel()
|
|
return nil, err
|
|
}
|
|
|
|
expectedPaths := make(map[string]bool)
|
|
|
|
for _, file := range files {
|
|
err := inotify.AddWatch(filepath.Dir(file), mask)
|
|
if err != nil {
|
|
cancel()
|
|
return nil, err
|
|
}
|
|
expectedPaths[file] = true
|
|
}
|
|
|
|
events := make(chan FileEvent)
|
|
|
|
go func() {
|
|
defer cancel()
|
|
for {
|
|
raw, err := inotify.Read()
|
|
|
|
if err != nil {
|
|
close(events)
|
|
return
|
|
}
|
|
|
|
for _, event := range raw {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case events <- FileEvent{
|
|
InotifyEvent: event,
|
|
}: //noop
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
defer cancel()
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case event, ok := <-events:
|
|
|
|
if !ok {
|
|
f.C <- FileEvent{
|
|
Eof: true,
|
|
}
|
|
return
|
|
}
|
|
|
|
if !expectedPaths[event.Name] {
|
|
continue
|
|
}
|
|
|
|
f.C <- event
|
|
}
|
|
}
|
|
}()
|
|
|
|
return f, nil
|
|
}
|