backend_inotify.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. //go:build linux && !appengine
  2. // +build linux,!appengine
  3. // Note: the documentation on the Watcher type and methods is generated from
  4. // mkdoc.zsh
  5. package fsnotify
  6. import (
  7. "errors"
  8. "fmt"
  9. "io"
  10. "os"
  11. "path/filepath"
  12. "strings"
  13. "sync"
  14. "unsafe"
  15. "golang.org/x/sys/unix"
  16. )
  17. // Watcher watches a set of paths, delivering events on a channel.
  18. //
  19. // A watcher should not be copied (e.g. pass it by pointer, rather than by
  20. // value).
  21. //
  22. // # Linux notes
  23. //
  24. // When a file is removed a Remove event won't be emitted until all file
  25. // descriptors are closed, and deletes will always emit a Chmod. For example:
  26. //
  27. // fp := os.Open("file")
  28. // os.Remove("file") // Triggers Chmod
  29. // fp.Close() // Triggers Remove
  30. //
  31. // This is the event that inotify sends, so not much can be changed about this.
  32. //
  33. // The fs.inotify.max_user_watches sysctl variable specifies the upper limit
  34. // for the number of watches per user, and fs.inotify.max_user_instances
  35. // specifies the maximum number of inotify instances per user. Every Watcher you
  36. // create is an "instance", and every path you add is a "watch".
  37. //
  38. // These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
  39. // /proc/sys/fs/inotify/max_user_instances
  40. //
  41. // To increase them you can use sysctl or write the value to the /proc file:
  42. //
  43. // # Default values on Linux 5.18
  44. // sysctl fs.inotify.max_user_watches=124983
  45. // sysctl fs.inotify.max_user_instances=128
  46. //
  47. // To make the changes persist on reboot edit /etc/sysctl.conf or
  48. // /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
  49. // your distro's documentation):
  50. //
  51. // fs.inotify.max_user_watches=124983
  52. // fs.inotify.max_user_instances=128
  53. //
  54. // Reaching the limit will result in a "no space left on device" or "too many open
  55. // files" error.
  56. //
  57. // # kqueue notes (macOS, BSD)
  58. //
  59. // kqueue requires opening a file descriptor for every file that's being watched;
  60. // so if you're watching a directory with five files then that's six file
  61. // descriptors. You will run in to your system's "max open files" limit faster on
  62. // these platforms.
  63. //
  64. // The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
  65. // control the maximum number of open files, as well as /etc/login.conf on BSD
  66. // systems.
  67. //
  68. // # Windows notes
  69. //
  70. // Paths can be added as "C:\path\to\dir", but forward slashes
  71. // ("C:/path/to/dir") will also work.
  72. //
  73. // When a watched directory is removed it will always send an event for the
  74. // directory itself, but may not send events for all files in that directory.
  75. // Sometimes it will send events for all times, sometimes it will send no
  76. // events, and often only for some files.
  77. //
  78. // The default ReadDirectoryChangesW() buffer size is 64K, which is the largest
  79. // value that is guaranteed to work with SMB filesystems. If you have many
  80. // events in quick succession this may not be enough, and you will have to use
  81. // [WithBufferSize] to increase the value.
  82. type Watcher struct {
  83. // Events sends the filesystem change events.
  84. //
  85. // fsnotify can send the following events; a "path" here can refer to a
  86. // file, directory, symbolic link, or special file like a FIFO.
  87. //
  88. // fsnotify.Create A new path was created; this may be followed by one
  89. // or more Write events if data also gets written to a
  90. // file.
  91. //
  92. // fsnotify.Remove A path was removed.
  93. //
  94. // fsnotify.Rename A path was renamed. A rename is always sent with the
  95. // old path as Event.Name, and a Create event will be
  96. // sent with the new name. Renames are only sent for
  97. // paths that are currently watched; e.g. moving an
  98. // unmonitored file into a monitored directory will
  99. // show up as just a Create. Similarly, renaming a file
  100. // to outside a monitored directory will show up as
  101. // only a Rename.
  102. //
  103. // fsnotify.Write A file or named pipe was written to. A Truncate will
  104. // also trigger a Write. A single "write action"
  105. // initiated by the user may show up as one or multiple
  106. // writes, depending on when the system syncs things to
  107. // disk. For example when compiling a large Go program
  108. // you may get hundreds of Write events, and you may
  109. // want to wait until you've stopped receiving them
  110. // (see the dedup example in cmd/fsnotify).
  111. //
  112. // Some systems may send Write event for directories
  113. // when the directory content changes.
  114. //
  115. // fsnotify.Chmod Attributes were changed. On Linux this is also sent
  116. // when a file is removed (or more accurately, when a
  117. // link to an inode is removed). On kqueue it's sent
  118. // when a file is truncated. On Windows it's never
  119. // sent.
  120. Events chan Event
  121. // Errors sends any errors.
  122. //
  123. // ErrEventOverflow is used to indicate there are too many events:
  124. //
  125. // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl)
  126. // - windows: The buffer size is too small; WithBufferSize() can be used to increase it.
  127. // - kqueue, fen: Not used.
  128. Errors chan error
  129. // Store fd here as os.File.Read() will no longer return on close after
  130. // calling Fd(). See: https://github.com/golang/go/issues/26439
  131. fd int
  132. inotifyFile *os.File
  133. watches *watches
  134. done chan struct{} // Channel for sending a "quit message" to the reader goroutine
  135. closeMu sync.Mutex
  136. doneResp chan struct{} // Channel to respond to Close
  137. }
  138. type (
  139. watches struct {
  140. mu sync.RWMutex
  141. wd map[uint32]*watch // wd → watch
  142. path map[string]uint32 // pathname → wd
  143. }
  144. watch struct {
  145. wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
  146. flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
  147. path string // Watch path.
  148. }
  149. )
  150. func newWatches() *watches {
  151. return &watches{
  152. wd: make(map[uint32]*watch),
  153. path: make(map[string]uint32),
  154. }
  155. }
  156. func (w *watches) len() int {
  157. w.mu.RLock()
  158. defer w.mu.RUnlock()
  159. return len(w.wd)
  160. }
  161. func (w *watches) add(ww *watch) {
  162. w.mu.Lock()
  163. defer w.mu.Unlock()
  164. w.wd[ww.wd] = ww
  165. w.path[ww.path] = ww.wd
  166. }
  167. func (w *watches) remove(wd uint32) {
  168. w.mu.Lock()
  169. defer w.mu.Unlock()
  170. delete(w.path, w.wd[wd].path)
  171. delete(w.wd, wd)
  172. }
  173. func (w *watches) removePath(path string) (uint32, bool) {
  174. w.mu.Lock()
  175. defer w.mu.Unlock()
  176. wd, ok := w.path[path]
  177. if !ok {
  178. return 0, false
  179. }
  180. delete(w.path, path)
  181. delete(w.wd, wd)
  182. return wd, true
  183. }
  184. func (w *watches) byPath(path string) *watch {
  185. w.mu.RLock()
  186. defer w.mu.RUnlock()
  187. return w.wd[w.path[path]]
  188. }
  189. func (w *watches) byWd(wd uint32) *watch {
  190. w.mu.RLock()
  191. defer w.mu.RUnlock()
  192. return w.wd[wd]
  193. }
  194. func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error {
  195. w.mu.Lock()
  196. defer w.mu.Unlock()
  197. var existing *watch
  198. wd, ok := w.path[path]
  199. if ok {
  200. existing = w.wd[wd]
  201. }
  202. upd, err := f(existing)
  203. if err != nil {
  204. return err
  205. }
  206. if upd != nil {
  207. w.wd[upd.wd] = upd
  208. w.path[upd.path] = upd.wd
  209. if upd.wd != wd {
  210. delete(w.wd, wd)
  211. }
  212. }
  213. return nil
  214. }
  215. // NewWatcher creates a new Watcher.
  216. func NewWatcher() (*Watcher, error) {
  217. return NewBufferedWatcher(0)
  218. }
  219. // NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events
  220. // channel.
  221. //
  222. // The main use case for this is situations with a very large number of events
  223. // where the kernel buffer size can't be increased (e.g. due to lack of
  224. // permissions). An unbuffered Watcher will perform better for almost all use
  225. // cases, and whenever possible you will be better off increasing the kernel
  226. // buffers instead of adding a large userspace buffer.
  227. func NewBufferedWatcher(sz uint) (*Watcher, error) {
  228. // Need to set nonblocking mode for SetDeadline to work, otherwise blocking
  229. // I/O operations won't terminate on close.
  230. fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  231. if fd == -1 {
  232. return nil, errno
  233. }
  234. w := &Watcher{
  235. fd: fd,
  236. inotifyFile: os.NewFile(uintptr(fd), ""),
  237. watches: newWatches(),
  238. Events: make(chan Event, sz),
  239. Errors: make(chan error),
  240. done: make(chan struct{}),
  241. doneResp: make(chan struct{}),
  242. }
  243. go w.readEvents()
  244. return w, nil
  245. }
  246. // Returns true if the event was sent, or false if watcher is closed.
  247. func (w *Watcher) sendEvent(e Event) bool {
  248. select {
  249. case w.Events <- e:
  250. return true
  251. case <-w.done:
  252. return false
  253. }
  254. }
  255. // Returns true if the error was sent, or false if watcher is closed.
  256. func (w *Watcher) sendError(err error) bool {
  257. select {
  258. case w.Errors <- err:
  259. return true
  260. case <-w.done:
  261. return false
  262. }
  263. }
  264. func (w *Watcher) isClosed() bool {
  265. select {
  266. case <-w.done:
  267. return true
  268. default:
  269. return false
  270. }
  271. }
  272. // Close removes all watches and closes the Events channel.
  273. func (w *Watcher) Close() error {
  274. w.closeMu.Lock()
  275. if w.isClosed() {
  276. w.closeMu.Unlock()
  277. return nil
  278. }
  279. close(w.done)
  280. w.closeMu.Unlock()
  281. // Causes any blocking reads to return with an error, provided the file
  282. // still supports deadline operations.
  283. err := w.inotifyFile.Close()
  284. if err != nil {
  285. return err
  286. }
  287. // Wait for goroutine to close
  288. <-w.doneResp
  289. return nil
  290. }
  291. // Add starts monitoring the path for changes.
  292. //
  293. // A path can only be watched once; watching it more than once is a no-op and will
  294. // not return an error. Paths that do not yet exist on the filesystem cannot be
  295. // watched.
  296. //
  297. // A watch will be automatically removed if the watched path is deleted or
  298. // renamed. The exception is the Windows backend, which doesn't remove the
  299. // watcher on renames.
  300. //
  301. // Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
  302. // filesystems (/proc, /sys, etc.) generally don't work.
  303. //
  304. // Returns [ErrClosed] if [Watcher.Close] was called.
  305. //
  306. // See [Watcher.AddWith] for a version that allows adding options.
  307. //
  308. // # Watching directories
  309. //
  310. // All files in a directory are monitored, including new files that are created
  311. // after the watcher is started. Subdirectories are not watched (i.e. it's
  312. // non-recursive).
  313. //
  314. // # Watching files
  315. //
  316. // Watching individual files (rather than directories) is generally not
  317. // recommended as many programs (especially editors) update files atomically: it
  318. // will write to a temporary file which is then moved to to destination,
  319. // overwriting the original (or some variant thereof). The watcher on the
  320. // original file is now lost, as that no longer exists.
  321. //
  322. // The upshot of this is that a power failure or crash won't leave a
  323. // half-written file.
  324. //
  325. // Watch the parent directory and use Event.Name to filter out files you're not
  326. // interested in. There is an example of this in cmd/fsnotify/file.go.
  327. func (w *Watcher) Add(name string) error { return w.AddWith(name) }
  328. // AddWith is like [Watcher.Add], but allows adding options. When using Add()
  329. // the defaults described below are used.
  330. //
  331. // Possible options are:
  332. //
  333. // - [WithBufferSize] sets the buffer size for the Windows backend; no-op on
  334. // other platforms. The default is 64K (65536 bytes).
  335. func (w *Watcher) AddWith(name string, opts ...addOpt) error {
  336. if w.isClosed() {
  337. return ErrClosed
  338. }
  339. name = filepath.Clean(name)
  340. _ = getOptions(opts...)
  341. var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM |
  342. unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY |
  343. unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF
  344. return w.watches.updatePath(name, func(existing *watch) (*watch, error) {
  345. if existing != nil {
  346. flags |= existing.flags | unix.IN_MASK_ADD
  347. }
  348. wd, err := unix.InotifyAddWatch(w.fd, name, flags)
  349. if wd == -1 {
  350. return nil, err
  351. }
  352. if existing == nil {
  353. return &watch{
  354. wd: uint32(wd),
  355. path: name,
  356. flags: flags,
  357. }, nil
  358. }
  359. existing.wd = uint32(wd)
  360. existing.flags = flags
  361. return existing, nil
  362. })
  363. }
  364. // Remove stops monitoring the path for changes.
  365. //
  366. // Directories are always removed non-recursively. For example, if you added
  367. // /tmp/dir and /tmp/dir/subdir then you will need to remove both.
  368. //
  369. // Removing a path that has not yet been added returns [ErrNonExistentWatch].
  370. //
  371. // Returns nil if [Watcher.Close] was called.
  372. func (w *Watcher) Remove(name string) error {
  373. if w.isClosed() {
  374. return nil
  375. }
  376. return w.remove(filepath.Clean(name))
  377. }
  378. func (w *Watcher) remove(name string) error {
  379. wd, ok := w.watches.removePath(name)
  380. if !ok {
  381. return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
  382. }
  383. success, errno := unix.InotifyRmWatch(w.fd, wd)
  384. if success == -1 {
  385. // TODO: Perhaps it's not helpful to return an error here in every case;
  386. // The only two possible errors are:
  387. //
  388. // - EBADF, which happens when w.fd is not a valid file descriptor
  389. // of any kind.
  390. // - EINVAL, which is when fd is not an inotify descriptor or wd
  391. // is not a valid watch descriptor. Watch descriptors are
  392. // invalidated when they are removed explicitly or implicitly;
  393. // explicitly by inotify_rm_watch, implicitly when the file they
  394. // are watching is deleted.
  395. return errno
  396. }
  397. return nil
  398. }
  399. // WatchList returns all paths explicitly added with [Watcher.Add] (and are not
  400. // yet removed).
  401. //
  402. // Returns nil if [Watcher.Close] was called.
  403. func (w *Watcher) WatchList() []string {
  404. if w.isClosed() {
  405. return nil
  406. }
  407. entries := make([]string, 0, w.watches.len())
  408. w.watches.mu.RLock()
  409. for pathname := range w.watches.path {
  410. entries = append(entries, pathname)
  411. }
  412. w.watches.mu.RUnlock()
  413. return entries
  414. }
  415. // readEvents reads from the inotify file descriptor, converts the
  416. // received events into Event objects and sends them via the Events channel
  417. func (w *Watcher) readEvents() {
  418. defer func() {
  419. close(w.doneResp)
  420. close(w.Errors)
  421. close(w.Events)
  422. }()
  423. var (
  424. buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
  425. errno error // Syscall errno
  426. )
  427. for {
  428. // See if we have been closed.
  429. if w.isClosed() {
  430. return
  431. }
  432. n, err := w.inotifyFile.Read(buf[:])
  433. switch {
  434. case errors.Unwrap(err) == os.ErrClosed:
  435. return
  436. case err != nil:
  437. if !w.sendError(err) {
  438. return
  439. }
  440. continue
  441. }
  442. if n < unix.SizeofInotifyEvent {
  443. var err error
  444. if n == 0 {
  445. err = io.EOF // If EOF is received. This should really never happen.
  446. } else if n < 0 {
  447. err = errno // If an error occurred while reading.
  448. } else {
  449. err = errors.New("notify: short read in readEvents()") // Read was too short.
  450. }
  451. if !w.sendError(err) {
  452. return
  453. }
  454. continue
  455. }
  456. var offset uint32
  457. // We don't know how many events we just read into the buffer
  458. // While the offset points to at least one whole event...
  459. for offset <= uint32(n-unix.SizeofInotifyEvent) {
  460. var (
  461. // Point "raw" to the event in the buffer
  462. raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
  463. mask = uint32(raw.Mask)
  464. nameLen = uint32(raw.Len)
  465. )
  466. if mask&unix.IN_Q_OVERFLOW != 0 {
  467. if !w.sendError(ErrEventOverflow) {
  468. return
  469. }
  470. }
  471. // If the event happened to the watched directory or the watched file, the kernel
  472. // doesn't append the filename to the event, but we would like to always fill the
  473. // the "Name" field with a valid filename. We retrieve the path of the watch from
  474. // the "paths" map.
  475. watch := w.watches.byWd(uint32(raw.Wd))
  476. // inotify will automatically remove the watch on deletes; just need
  477. // to clean our state here.
  478. if watch != nil && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF {
  479. w.watches.remove(watch.wd)
  480. }
  481. // We can't really update the state when a watched path is moved;
  482. // only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove
  483. // the watch.
  484. if watch != nil && mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF {
  485. err := w.remove(watch.path)
  486. if err != nil && !errors.Is(err, ErrNonExistentWatch) {
  487. if !w.sendError(err) {
  488. return
  489. }
  490. }
  491. }
  492. var name string
  493. if watch != nil {
  494. name = watch.path
  495. }
  496. if nameLen > 0 {
  497. // Point "bytes" at the first byte of the filename
  498. bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen]
  499. // The filename is padded with NULL bytes. TrimRight() gets rid of those.
  500. name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
  501. }
  502. event := w.newEvent(name, mask)
  503. // Send the events that are not ignored on the events channel
  504. if mask&unix.IN_IGNORED == 0 {
  505. if !w.sendEvent(event) {
  506. return
  507. }
  508. }
  509. // Move to the next event in the buffer
  510. offset += unix.SizeofInotifyEvent + nameLen
  511. }
  512. }
  513. }
  514. // newEvent returns an platform-independent Event based on an inotify mask.
  515. func (w *Watcher) newEvent(name string, mask uint32) Event {
  516. e := Event{Name: name}
  517. if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
  518. e.Op |= Create
  519. }
  520. if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE {
  521. e.Op |= Remove
  522. }
  523. if mask&unix.IN_MODIFY == unix.IN_MODIFY {
  524. e.Op |= Write
  525. }
  526. if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
  527. e.Op |= Rename
  528. }
  529. if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
  530. e.Op |= Chmod
  531. }
  532. return e
  533. }