|
1 //go:build solaris |
|
2 // +build solaris |
|
3 |
|
4 package fsnotify |
|
5 |
|
6 import ( |
|
7 "errors" |
|
8 ) |
|
9 |
|
10 // Watcher watches a set of paths, delivering events on a channel. |
|
11 // |
|
12 // A watcher should not be copied (e.g. pass it by pointer, rather than by |
|
13 // value). |
|
14 // |
|
15 // # Linux notes |
|
16 // |
|
17 // When a file is removed a Remove event won't be emitted until all file |
|
18 // descriptors are closed, and deletes will always emit a Chmod. For example: |
|
19 // |
|
20 // fp := os.Open("file") |
|
21 // os.Remove("file") // Triggers Chmod |
|
22 // fp.Close() // Triggers Remove |
|
23 // |
|
24 // This is the event that inotify sends, so not much can be changed about this. |
|
25 // |
|
26 // The fs.inotify.max_user_watches sysctl variable specifies the upper limit |
|
27 // for the number of watches per user, and fs.inotify.max_user_instances |
|
28 // specifies the maximum number of inotify instances per user. Every Watcher you |
|
29 // create is an "instance", and every path you add is a "watch". |
|
30 // |
|
31 // These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and |
|
32 // /proc/sys/fs/inotify/max_user_instances |
|
33 // |
|
34 // To increase them you can use sysctl or write the value to the /proc file: |
|
35 // |
|
36 // # Default values on Linux 5.18 |
|
37 // sysctl fs.inotify.max_user_watches=124983 |
|
38 // sysctl fs.inotify.max_user_instances=128 |
|
39 // |
|
40 // To make the changes persist on reboot edit /etc/sysctl.conf or |
|
41 // /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check |
|
42 // your distro's documentation): |
|
43 // |
|
44 // fs.inotify.max_user_watches=124983 |
|
45 // fs.inotify.max_user_instances=128 |
|
46 // |
|
47 // Reaching the limit will result in a "no space left on device" or "too many open |
|
48 // files" error. |
|
49 // |
|
50 // # kqueue notes (macOS, BSD) |
|
51 // |
|
52 // kqueue requires opening a file descriptor for every file that's being watched; |
|
53 // so if you're watching a directory with five files then that's six file |
|
54 // descriptors. You will run in to your system's "max open files" limit faster on |
|
55 // these platforms. |
|
56 // |
|
57 // The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to |
|
58 // control the maximum number of open files, as well as /etc/login.conf on BSD |
|
59 // systems. |
|
60 // |
|
61 // # macOS notes |
|
62 // |
|
63 // Spotlight indexing on macOS can result in multiple events (see [#15]). A |
|
64 // temporary workaround is to add your folder(s) to the "Spotlight Privacy |
|
65 // Settings" until we have a native FSEvents implementation (see [#11]). |
|
66 // |
|
67 // [#11]: https://github.com/fsnotify/fsnotify/issues/11 |
|
68 // [#15]: https://github.com/fsnotify/fsnotify/issues/15 |
|
69 type Watcher struct { |
|
70 // Events sends the filesystem change events. |
|
71 // |
|
72 // fsnotify can send the following events; a "path" here can refer to a |
|
73 // file, directory, symbolic link, or special file like a FIFO. |
|
74 // |
|
75 // fsnotify.Create A new path was created; this may be followed by one |
|
76 // or more Write events if data also gets written to a |
|
77 // file. |
|
78 // |
|
79 // fsnotify.Remove A path was removed. |
|
80 // |
|
81 // fsnotify.Rename A path was renamed. A rename is always sent with the |
|
82 // old path as Event.Name, and a Create event will be |
|
83 // sent with the new name. Renames are only sent for |
|
84 // paths that are currently watched; e.g. moving an |
|
85 // unmonitored file into a monitored directory will |
|
86 // show up as just a Create. Similarly, renaming a file |
|
87 // to outside a monitored directory will show up as |
|
88 // only a Rename. |
|
89 // |
|
90 // fsnotify.Write A file or named pipe was written to. A Truncate will |
|
91 // also trigger a Write. A single "write action" |
|
92 // initiated by the user may show up as one or multiple |
|
93 // writes, depending on when the system syncs things to |
|
94 // disk. For example when compiling a large Go program |
|
95 // you may get hundreds of Write events, so you |
|
96 // probably want to wait until you've stopped receiving |
|
97 // them (see the dedup example in cmd/fsnotify). |
|
98 // |
|
99 // fsnotify.Chmod Attributes were changed. On Linux this is also sent |
|
100 // when a file is removed (or more accurately, when a |
|
101 // link to an inode is removed). On kqueue it's sent |
|
102 // and on kqueue when a file is truncated. On Windows |
|
103 // it's never sent. |
|
104 Events chan Event |
|
105 |
|
106 // Errors sends any errors. |
|
107 Errors chan error |
|
108 } |
|
109 |
|
110 // NewWatcher creates a new Watcher. |
|
111 func NewWatcher() (*Watcher, error) { |
|
112 return nil, errors.New("FEN based watcher not yet supported for fsnotify\n") |
|
113 } |
|
114 |
|
115 // Close removes all watches and closes the events channel. |
|
116 func (w *Watcher) Close() error { |
|
117 return nil |
|
118 } |
|
119 |
|
120 // Add starts monitoring the path for changes. |
|
121 // |
|
122 // A path can only be watched once; attempting to watch it more than once will |
|
123 // return an error. Paths that do not yet exist on the filesystem cannot be |
|
124 // added. A watch will be automatically removed if the path is deleted. |
|
125 // |
|
126 // A path will remain watched if it gets renamed to somewhere else on the same |
|
127 // filesystem, but the monitor will get removed if the path gets deleted and |
|
128 // re-created, or if it's moved to a different filesystem. |
|
129 // |
|
130 // Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special |
|
131 // filesystems (/proc, /sys, etc.) generally don't work. |
|
132 // |
|
133 // # Watching directories |
|
134 // |
|
135 // All files in a directory are monitored, including new files that are created |
|
136 // after the watcher is started. Subdirectories are not watched (i.e. it's |
|
137 // non-recursive). |
|
138 // |
|
139 // # Watching files |
|
140 // |
|
141 // Watching individual files (rather than directories) is generally not |
|
142 // recommended as many tools update files atomically. Instead of "just" writing |
|
143 // to the file a temporary file will be written to first, and if successful the |
|
144 // temporary file is moved to to destination removing the original, or some |
|
145 // variant thereof. The watcher on the original file is now lost, as it no |
|
146 // longer exists. |
|
147 // |
|
148 // Instead, watch the parent directory and use Event.Name to filter out files |
|
149 // you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. |
|
150 func (w *Watcher) Add(name string) error { |
|
151 return nil |
|
152 } |
|
153 |
|
154 // Remove stops monitoring the path for changes. |
|
155 // |
|
156 // Directories are always removed non-recursively. For example, if you added |
|
157 // /tmp/dir and /tmp/dir/subdir then you will need to remove both. |
|
158 // |
|
159 // Removing a path that has not yet been added returns [ErrNonExistentWatch]. |
|
160 func (w *Watcher) Remove(name string) error { |
|
161 return nil |
|
162 } |