podman

Форк
0
136 строк · 2.8 Кб
1
// Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail
2
// Copyright (c) 2015 HPE Software Inc. All rights reserved.
3
// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.
4

5
package watch
6

7
import (
8
	"fmt"
9
	"os"
10
	"path/filepath"
11

12
	"github.com/nxadm/tail/util"
13

14
    "github.com/fsnotify/fsnotify"
15
	"gopkg.in/tomb.v1"
16
)
17

18
// InotifyFileWatcher uses inotify to monitor file changes.
19
type InotifyFileWatcher struct {
20
	Filename string
21
	Size     int64
22
}
23

24
func NewInotifyFileWatcher(filename string) *InotifyFileWatcher {
25
	fw := &InotifyFileWatcher{filepath.Clean(filename), 0}
26
	return fw
27
}
28

29
func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error {
30
	err := WatchCreate(fw.Filename)
31
	if err != nil {
32
		return err
33
	}
34
	defer RemoveWatchCreate(fw.Filename)
35

36
	// Do a real check now as the file might have been created before
37
	// calling `WatchFlags` above.
38
	if _, err = os.Stat(fw.Filename); !os.IsNotExist(err) {
39
		// file exists, or stat returned an error.
40
		return err
41
	}
42

43
	events := Events(fw.Filename)
44

45
	for {
46
		select {
47
		case evt, ok := <-events:
48
			if !ok {
49
				return fmt.Errorf("inotify watcher has been closed")
50
			}
51
			evtName, err := filepath.Abs(evt.Name)
52
			if err != nil {
53
				return err
54
			}
55
			fwFilename, err := filepath.Abs(fw.Filename)
56
			if err != nil {
57
				return err
58
			}
59
			if evtName == fwFilename {
60
				return nil
61
			}
62
		case <-t.Dying():
63
			return tomb.ErrDying
64
		}
65
	}
66
	panic("unreachable")
67
}
68

69
func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) {
70
	err := Watch(fw.Filename)
71
	if err != nil {
72
		return nil, err
73
	}
74

75
	changes := NewFileChanges()
76
	fw.Size = pos
77

78
	go func() {
79

80
		events := Events(fw.Filename)
81

82
		for {
83
			prevSize := fw.Size
84

85
			var evt fsnotify.Event
86
			var ok bool
87

88
			select {
89
			case evt, ok = <-events:
90
				if !ok {
91
					RemoveWatch(fw.Filename)
92
					return
93
				}
94
			case <-t.Dying():
95
				RemoveWatch(fw.Filename)
96
				return
97
			}
98

99
			switch {
100
			case evt.Op&fsnotify.Remove == fsnotify.Remove:
101
				fallthrough
102

103
			case evt.Op&fsnotify.Rename == fsnotify.Rename:
104
				RemoveWatch(fw.Filename)
105
				changes.NotifyDeleted()
106
				return
107

108
			//With an open fd, unlink(fd) - inotify returns IN_ATTRIB (==fsnotify.Chmod)
109
			case evt.Op&fsnotify.Chmod == fsnotify.Chmod:
110
				fallthrough
111

112
			case evt.Op&fsnotify.Write == fsnotify.Write:
113
				fi, err := os.Stat(fw.Filename)
114
				if err != nil {
115
					if os.IsNotExist(err) {
116
						RemoveWatch(fw.Filename)
117
						changes.NotifyDeleted()
118
						return
119
					}
120
					// XXX: report this error back to the user
121
					util.Fatal("Failed to stat file %v: %v", fw.Filename, err)
122
				}
123
				fw.Size = fi.Size()
124

125
				if prevSize > 0 && prevSize > fw.Size {
126
					changes.NotifyTruncated()
127
				} else {
128
					changes.NotifyModified()
129
				}
130
				prevSize = fw.Size
131
			}
132
		}
133
	}()
134

135
	return changes, nil
136
}
137

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.