vendor/github.com/fsnotify/fsnotify/backend_kqueue.go
author Mikael Berthe <mikael@lilotux.net>
Sat, 04 Feb 2023 12:58:35 +0100
changeset 265 05c40b36d3b2
permissions -rw-r--r--
Bump to version 3.0.0-dev, using madon v3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
265
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     1
//go:build freebsd || openbsd || netbsd || dragonfly || darwin
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     2
// +build freebsd openbsd netbsd dragonfly darwin
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     3
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     4
package fsnotify
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     5
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     6
import (
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     7
	"errors"
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     8
	"fmt"
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     9
	"io/ioutil"
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    10
	"os"
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    11
	"path/filepath"
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    12
	"sync"
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    13
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    14
	"golang.org/x/sys/unix"
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    15
)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    16
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    17
// Watcher watches a set of paths, delivering events on a channel.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    18
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    19
// A watcher should not be copied (e.g. pass it by pointer, rather than by
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    20
// value).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    21
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    22
// # Linux notes
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    23
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    24
// When a file is removed a Remove event won't be emitted until all file
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    25
// descriptors are closed, and deletes will always emit a Chmod. For example:
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    26
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    27
//     fp := os.Open("file")
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    28
//     os.Remove("file")        // Triggers Chmod
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    29
//     fp.Close()               // Triggers Remove
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    30
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    31
// This is the event that inotify sends, so not much can be changed about this.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    32
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    33
// The fs.inotify.max_user_watches sysctl variable specifies the upper limit
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    34
// for the number of watches per user, and fs.inotify.max_user_instances
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    35
// specifies the maximum number of inotify instances per user. Every Watcher you
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    36
// create is an "instance", and every path you add is a "watch".
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    37
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    38
// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    39
// /proc/sys/fs/inotify/max_user_instances
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    40
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    41
// To increase them you can use sysctl or write the value to the /proc file:
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    42
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    43
//     # Default values on Linux 5.18
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    44
//     sysctl fs.inotify.max_user_watches=124983
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    45
//     sysctl fs.inotify.max_user_instances=128
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    46
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    47
// To make the changes persist on reboot edit /etc/sysctl.conf or
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    48
// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    49
// your distro's documentation):
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    50
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    51
//     fs.inotify.max_user_watches=124983
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    52
//     fs.inotify.max_user_instances=128
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    53
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    54
// Reaching the limit will result in a "no space left on device" or "too many open
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    55
// files" error.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    56
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    57
// # kqueue notes (macOS, BSD)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    58
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    59
// kqueue requires opening a file descriptor for every file that's being watched;
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    60
// so if you're watching a directory with five files then that's six file
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    61
// descriptors. You will run in to your system's "max open files" limit faster on
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    62
// these platforms.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    63
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    64
// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    65
// control the maximum number of open files, as well as /etc/login.conf on BSD
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    66
// systems.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    67
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    68
// # macOS notes
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    69
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    70
// Spotlight indexing on macOS can result in multiple events (see [#15]). A
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    71
// temporary workaround is to add your folder(s) to the "Spotlight Privacy
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    72
// Settings" until we have a native FSEvents implementation (see [#11]).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    73
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    74
// [#11]: https://github.com/fsnotify/fsnotify/issues/11
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    75
// [#15]: https://github.com/fsnotify/fsnotify/issues/15
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    76
type Watcher struct {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    77
	// Events sends the filesystem change events.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    78
	//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    79
	// fsnotify can send the following events; a "path" here can refer to a
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    80
	// file, directory, symbolic link, or special file like a FIFO.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    81
	//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    82
	//   fsnotify.Create    A new path was created; this may be followed by one
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    83
	//                      or more Write events if data also gets written to a
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    84
	//                      file.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    85
	//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    86
	//   fsnotify.Remove    A path was removed.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    87
	//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    88
	//   fsnotify.Rename    A path was renamed. A rename is always sent with the
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    89
	//                      old path as Event.Name, and a Create event will be
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    90
	//                      sent with the new name. Renames are only sent for
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    91
	//                      paths that are currently watched; e.g. moving an
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    92
	//                      unmonitored file into a monitored directory will
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    93
	//                      show up as just a Create. Similarly, renaming a file
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    94
	//                      to outside a monitored directory will show up as
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    95
	//                      only a Rename.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    96
	//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    97
	//   fsnotify.Write     A file or named pipe was written to. A Truncate will
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    98
	//                      also trigger a Write. A single "write action"
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    99
	//                      initiated by the user may show up as one or multiple
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   100
	//                      writes, depending on when the system syncs things to
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   101
	//                      disk. For example when compiling a large Go program
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   102
	//                      you may get hundreds of Write events, so you
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   103
	//                      probably want to wait until you've stopped receiving
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   104
	//                      them (see the dedup example in cmd/fsnotify).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   105
	//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   106
	//   fsnotify.Chmod     Attributes were changed. On Linux this is also sent
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   107
	//                      when a file is removed (or more accurately, when a
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   108
	//                      link to an inode is removed). On kqueue it's sent
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   109
	//                      and on kqueue when a file is truncated. On Windows
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   110
	//                      it's never sent.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   111
	Events chan Event
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   112
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   113
	// Errors sends any errors.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   114
	Errors chan error
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   115
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   116
	done         chan struct{}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   117
	kq           int                         // File descriptor (as returned by the kqueue() syscall).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   118
	closepipe    [2]int                      // Pipe used for closing.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   119
	mu           sync.Mutex                  // Protects access to watcher data
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   120
	watches      map[string]int              // Watched file descriptors (key: path).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   121
	watchesByDir map[string]map[int]struct{} // Watched file descriptors indexed by the parent directory (key: dirname(path)).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   122
	userWatches  map[string]struct{}         // Watches added with Watcher.Add()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   123
	dirFlags     map[string]uint32           // Watched directories to fflags used in kqueue.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   124
	paths        map[int]pathInfo            // File descriptors to path names for processing kqueue events.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   125
	fileExists   map[string]struct{}         // Keep track of if we know this file exists (to stop duplicate create events).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   126
	isClosed     bool                        // Set to true when Close() is first called
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   127
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   128
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   129
type pathInfo struct {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   130
	name  string
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   131
	isDir bool
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   132
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   133
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   134
// NewWatcher creates a new Watcher.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   135
func NewWatcher() (*Watcher, error) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   136
	kq, closepipe, err := newKqueue()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   137
	if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   138
		return nil, err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   139
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   140
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   141
	w := &Watcher{
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   142
		kq:           kq,
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   143
		closepipe:    closepipe,
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   144
		watches:      make(map[string]int),
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   145
		watchesByDir: make(map[string]map[int]struct{}),
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   146
		dirFlags:     make(map[string]uint32),
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   147
		paths:        make(map[int]pathInfo),
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   148
		fileExists:   make(map[string]struct{}),
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   149
		userWatches:  make(map[string]struct{}),
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   150
		Events:       make(chan Event),
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   151
		Errors:       make(chan error),
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   152
		done:         make(chan struct{}),
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   153
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   154
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   155
	go w.readEvents()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   156
	return w, nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   157
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   158
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   159
// newKqueue creates a new kernel event queue and returns a descriptor.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   160
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   161
// This registers a new event on closepipe, which will trigger an event when
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   162
// it's closed. This way we can use kevent() without timeout/polling; without
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   163
// the closepipe, it would block forever and we wouldn't be able to stop it at
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   164
// all.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   165
func newKqueue() (kq int, closepipe [2]int, err error) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   166
	kq, err = unix.Kqueue()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   167
	if kq == -1 {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   168
		return kq, closepipe, err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   169
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   170
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   171
	// Register the close pipe.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   172
	err = unix.Pipe(closepipe[:])
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   173
	if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   174
		unix.Close(kq)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   175
		return kq, closepipe, err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   176
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   177
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   178
	// Register changes to listen on the closepipe.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   179
	changes := make([]unix.Kevent_t, 1)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   180
	// SetKevent converts int to the platform-specific types.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   181
	unix.SetKevent(&changes[0], closepipe[0], unix.EVFILT_READ,
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   182
		unix.EV_ADD|unix.EV_ENABLE|unix.EV_ONESHOT)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   183
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   184
	ok, err := unix.Kevent(kq, changes, nil, nil)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   185
	if ok == -1 {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   186
		unix.Close(kq)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   187
		unix.Close(closepipe[0])
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   188
		unix.Close(closepipe[1])
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   189
		return kq, closepipe, err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   190
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   191
	return kq, closepipe, nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   192
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   193
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   194
// Returns true if the event was sent, or false if watcher is closed.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   195
func (w *Watcher) sendEvent(e Event) bool {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   196
	select {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   197
	case w.Events <- e:
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   198
		return true
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   199
	case <-w.done:
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   200
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   201
	return false
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   202
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   203
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   204
// Returns true if the error was sent, or false if watcher is closed.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   205
func (w *Watcher) sendError(err error) bool {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   206
	select {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   207
	case w.Errors <- err:
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   208
		return true
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   209
	case <-w.done:
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   210
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   211
	return false
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   212
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   213
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   214
// Close removes all watches and closes the events channel.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   215
func (w *Watcher) Close() error {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   216
	w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   217
	if w.isClosed {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   218
		w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   219
		return nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   220
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   221
	w.isClosed = true
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   222
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   223
	// copy paths to remove while locked
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   224
	pathsToRemove := make([]string, 0, len(w.watches))
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   225
	for name := range w.watches {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   226
		pathsToRemove = append(pathsToRemove, name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   227
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   228
	w.mu.Unlock() // Unlock before calling Remove, which also locks
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   229
	for _, name := range pathsToRemove {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   230
		w.Remove(name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   231
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   232
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   233
	// Send "quit" message to the reader goroutine.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   234
	unix.Close(w.closepipe[1])
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   235
	close(w.done)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   236
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   237
	return nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   238
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   239
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   240
// Add starts monitoring the path for changes.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   241
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   242
// A path can only be watched once; attempting to watch it more than once will
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   243
// return an error. Paths that do not yet exist on the filesystem cannot be
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   244
// added. A watch will be automatically removed if the path is deleted.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   245
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   246
// A path will remain watched if it gets renamed to somewhere else on the same
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   247
// filesystem, but the monitor will get removed if the path gets deleted and
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   248
// re-created, or if it's moved to a different filesystem.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   249
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   250
// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   251
// filesystems (/proc, /sys, etc.) generally don't work.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   252
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   253
// # Watching directories
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   254
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   255
// All files in a directory are monitored, including new files that are created
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   256
// after the watcher is started. Subdirectories are not watched (i.e. it's
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   257
// non-recursive).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   258
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   259
// # Watching files
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   260
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   261
// Watching individual files (rather than directories) is generally not
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   262
// recommended as many tools update files atomically. Instead of "just" writing
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   263
// to the file a temporary file will be written to first, and if successful the
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   264
// temporary file is moved to to destination removing the original, or some
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   265
// variant thereof. The watcher on the original file is now lost, as it no
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   266
// longer exists.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   267
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   268
// Instead, watch the parent directory and use Event.Name to filter out files
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   269
// you're not interested in. There is an example of this in [cmd/fsnotify/file.go].
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   270
func (w *Watcher) Add(name string) error {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   271
	w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   272
	w.userWatches[name] = struct{}{}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   273
	w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   274
	_, err := w.addWatch(name, noteAllEvents)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   275
	return err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   276
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   277
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   278
// Remove stops monitoring the path for changes.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   279
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   280
// Directories are always removed non-recursively. For example, if you added
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   281
// /tmp/dir and /tmp/dir/subdir then you will need to remove both.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   282
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   283
// Removing a path that has not yet been added returns [ErrNonExistentWatch].
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   284
func (w *Watcher) Remove(name string) error {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   285
	name = filepath.Clean(name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   286
	w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   287
	watchfd, ok := w.watches[name]
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   288
	w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   289
	if !ok {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   290
		return fmt.Errorf("%w: %s", ErrNonExistentWatch, name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   291
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   292
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   293
	err := w.register([]int{watchfd}, unix.EV_DELETE, 0)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   294
	if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   295
		return err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   296
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   297
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   298
	unix.Close(watchfd)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   299
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   300
	w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   301
	isDir := w.paths[watchfd].isDir
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   302
	delete(w.watches, name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   303
	delete(w.userWatches, name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   304
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   305
	parentName := filepath.Dir(name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   306
	delete(w.watchesByDir[parentName], watchfd)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   307
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   308
	if len(w.watchesByDir[parentName]) == 0 {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   309
		delete(w.watchesByDir, parentName)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   310
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   311
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   312
	delete(w.paths, watchfd)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   313
	delete(w.dirFlags, name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   314
	delete(w.fileExists, name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   315
	w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   316
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   317
	// Find all watched paths that are in this directory that are not external.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   318
	if isDir {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   319
		var pathsToRemove []string
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   320
		w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   321
		for fd := range w.watchesByDir[name] {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   322
			path := w.paths[fd]
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   323
			if _, ok := w.userWatches[path.name]; !ok {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   324
				pathsToRemove = append(pathsToRemove, path.name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   325
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   326
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   327
		w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   328
		for _, name := range pathsToRemove {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   329
			// Since these are internal, not much sense in propagating error
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   330
			// to the user, as that will just confuse them with an error about
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   331
			// a path they did not explicitly watch themselves.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   332
			w.Remove(name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   333
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   334
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   335
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   336
	return nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   337
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   338
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   339
// WatchList returns all paths added with [Add] (and are not yet removed).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   340
func (w *Watcher) WatchList() []string {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   341
	w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   342
	defer w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   343
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   344
	entries := make([]string, 0, len(w.userWatches))
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   345
	for pathname := range w.userWatches {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   346
		entries = append(entries, pathname)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   347
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   348
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   349
	return entries
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   350
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   351
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   352
// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   353
const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   354
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   355
// addWatch adds name to the watched file set.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   356
// The flags are interpreted as described in kevent(2).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   357
// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   358
func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   359
	var isDir bool
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   360
	// Make ./name and name equivalent
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   361
	name = filepath.Clean(name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   362
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   363
	w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   364
	if w.isClosed {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   365
		w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   366
		return "", errors.New("kevent instance already closed")
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   367
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   368
	watchfd, alreadyWatching := w.watches[name]
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   369
	// We already have a watch, but we can still override flags.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   370
	if alreadyWatching {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   371
		isDir = w.paths[watchfd].isDir
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   372
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   373
	w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   374
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   375
	if !alreadyWatching {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   376
		fi, err := os.Lstat(name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   377
		if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   378
			return "", err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   379
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   380
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   381
		// Don't watch sockets or named pipes
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   382
		if (fi.Mode()&os.ModeSocket == os.ModeSocket) || (fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   383
			return "", nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   384
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   385
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   386
		// Follow Symlinks
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   387
		//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   388
		// Linux can add unresolvable symlinks to the watch list without issue,
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   389
		// and Windows can't do symlinks period. To maintain consistency, we
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   390
		// will act like everything is fine if the link can't be resolved.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   391
		// There will simply be no file events for broken symlinks. Hence the
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   392
		// returns of nil on errors.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   393
		if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   394
			name, err = filepath.EvalSymlinks(name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   395
			if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   396
				return "", nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   397
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   398
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   399
			w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   400
			_, alreadyWatching = w.watches[name]
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   401
			w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   402
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   403
			if alreadyWatching {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   404
				return name, nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   405
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   406
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   407
			fi, err = os.Lstat(name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   408
			if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   409
				return "", nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   410
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   411
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   412
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   413
		// Retry on EINTR; open() can return EINTR in practice on macOS.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   414
		// See #354, and go issues 11180 and 39237.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   415
		for {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   416
			watchfd, err = unix.Open(name, openMode, 0)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   417
			if err == nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   418
				break
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   419
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   420
			if errors.Is(err, unix.EINTR) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   421
				continue
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   422
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   423
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   424
			return "", err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   425
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   426
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   427
		isDir = fi.IsDir()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   428
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   429
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   430
	err := w.register([]int{watchfd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   431
	if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   432
		unix.Close(watchfd)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   433
		return "", err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   434
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   435
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   436
	if !alreadyWatching {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   437
		w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   438
		parentName := filepath.Dir(name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   439
		w.watches[name] = watchfd
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   440
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   441
		watchesByDir, ok := w.watchesByDir[parentName]
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   442
		if !ok {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   443
			watchesByDir = make(map[int]struct{}, 1)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   444
			w.watchesByDir[parentName] = watchesByDir
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   445
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   446
		watchesByDir[watchfd] = struct{}{}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   447
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   448
		w.paths[watchfd] = pathInfo{name: name, isDir: isDir}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   449
		w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   450
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   451
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   452
	if isDir {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   453
		// Watch the directory if it has not been watched before,
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   454
		// or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   455
		w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   456
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   457
		watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   458
			(!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   459
		// Store flags so this watch can be updated later
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   460
		w.dirFlags[name] = flags
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   461
		w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   462
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   463
		if watchDir {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   464
			if err := w.watchDirectoryFiles(name); err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   465
				return "", err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   466
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   467
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   468
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   469
	return name, nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   470
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   471
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   472
// readEvents reads from kqueue and converts the received kevents into
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   473
// Event values that it sends down the Events channel.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   474
func (w *Watcher) readEvents() {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   475
	defer func() {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   476
		err := unix.Close(w.kq)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   477
		if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   478
			w.Errors <- err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   479
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   480
		unix.Close(w.closepipe[0])
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   481
		close(w.Events)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   482
		close(w.Errors)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   483
	}()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   484
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   485
	eventBuffer := make([]unix.Kevent_t, 10)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   486
	for closed := false; !closed; {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   487
		kevents, err := w.read(eventBuffer)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   488
		// EINTR is okay, the syscall was interrupted before timeout expired.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   489
		if err != nil && err != unix.EINTR {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   490
			if !w.sendError(fmt.Errorf("fsnotify.readEvents: %w", err)) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   491
				closed = true
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   492
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   493
			continue
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   494
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   495
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   496
		// Flush the events we received to the Events channel
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   497
		for _, kevent := range kevents {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   498
			var (
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   499
				watchfd = int(kevent.Ident)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   500
				mask    = uint32(kevent.Fflags)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   501
			)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   502
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   503
			// Shut down the loop when the pipe is closed, but only after all
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   504
			// other events have been processed.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   505
			if watchfd == w.closepipe[0] {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   506
				closed = true
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   507
				continue
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   508
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   509
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   510
			w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   511
			path := w.paths[watchfd]
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   512
			w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   513
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   514
			event := w.newEvent(path.name, mask)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   515
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   516
			if path.isDir && !event.Has(Remove) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   517
				// Double check to make sure the directory exists. This can
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   518
				// happen when we do a rm -fr on a recursively watched folders
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   519
				// and we receive a modification event first but the folder has
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   520
				// been deleted and later receive the delete event.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   521
				if _, err := os.Lstat(event.Name); os.IsNotExist(err) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   522
					event.Op |= Remove
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   523
				}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   524
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   525
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   526
			if event.Has(Rename) || event.Has(Remove) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   527
				w.Remove(event.Name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   528
				w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   529
				delete(w.fileExists, event.Name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   530
				w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   531
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   532
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   533
			if path.isDir && event.Has(Write) && !event.Has(Remove) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   534
				w.sendDirectoryChangeEvents(event.Name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   535
			} else {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   536
				if !w.sendEvent(event) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   537
					closed = true
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   538
					continue
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   539
				}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   540
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   541
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   542
			if event.Has(Remove) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   543
				// Look for a file that may have overwritten this.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   544
				// For example, mv f1 f2 will delete f2, then create f2.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   545
				if path.isDir {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   546
					fileDir := filepath.Clean(event.Name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   547
					w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   548
					_, found := w.watches[fileDir]
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   549
					w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   550
					if found {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   551
						// make sure the directory exists before we watch for changes. When we
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   552
						// do a recursive watch and perform rm -fr, the parent directory might
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   553
						// have gone missing, ignore the missing directory and let the
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   554
						// upcoming delete event remove the watch from the parent directory.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   555
						if _, err := os.Lstat(fileDir); err == nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   556
							w.sendDirectoryChangeEvents(fileDir)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   557
						}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   558
					}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   559
				} else {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   560
					filePath := filepath.Clean(event.Name)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   561
					if fileInfo, err := os.Lstat(filePath); err == nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   562
						w.sendFileCreatedEventIfNew(filePath, fileInfo)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   563
					}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   564
				}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   565
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   566
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   567
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   568
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   569
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   570
// newEvent returns an platform-independent Event based on kqueue Fflags.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   571
func (w *Watcher) newEvent(name string, mask uint32) Event {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   572
	e := Event{Name: name}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   573
	if mask&unix.NOTE_DELETE == unix.NOTE_DELETE {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   574
		e.Op |= Remove
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   575
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   576
	if mask&unix.NOTE_WRITE == unix.NOTE_WRITE {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   577
		e.Op |= Write
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   578
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   579
	if mask&unix.NOTE_RENAME == unix.NOTE_RENAME {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   580
		e.Op |= Rename
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   581
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   582
	if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   583
		e.Op |= Chmod
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   584
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   585
	return e
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   586
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   587
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   588
// watchDirectoryFiles to mimic inotify when adding a watch on a directory
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   589
func (w *Watcher) watchDirectoryFiles(dirPath string) error {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   590
	// Get all files
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   591
	files, err := ioutil.ReadDir(dirPath)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   592
	if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   593
		return err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   594
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   595
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   596
	for _, fileInfo := range files {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   597
		path := filepath.Join(dirPath, fileInfo.Name())
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   598
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   599
		cleanPath, err := w.internalWatch(path, fileInfo)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   600
		if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   601
			// No permission to read the file; that's not a problem: just skip.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   602
			// But do add it to w.fileExists to prevent it from being picked up
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   603
			// as a "new" file later (it still shows up in the directory
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   604
			// listing).
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   605
			switch {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   606
			case errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM):
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   607
				cleanPath = filepath.Clean(path)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   608
			default:
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   609
				return fmt.Errorf("%q: %w", filepath.Join(dirPath, fileInfo.Name()), err)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   610
			}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   611
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   612
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   613
		w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   614
		w.fileExists[cleanPath] = struct{}{}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   615
		w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   616
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   617
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   618
	return nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   619
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   620
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   621
// Search the directory for new files and send an event for them.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   622
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   623
// This functionality is to have the BSD watcher match the inotify, which sends
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   624
// a create event for files created in a watched directory.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   625
func (w *Watcher) sendDirectoryChangeEvents(dir string) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   626
	// Get all files
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   627
	files, err := ioutil.ReadDir(dir)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   628
	if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   629
		if !w.sendError(fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   630
			return
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   631
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   632
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   633
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   634
	// Search for new files
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   635
	for _, fi := range files {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   636
		err := w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   637
		if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   638
			return
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   639
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   640
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   641
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   642
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   643
// sendFileCreatedEvent sends a create event if the file isn't already being tracked.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   644
func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   645
	w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   646
	_, doesExist := w.fileExists[filePath]
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   647
	w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   648
	if !doesExist {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   649
		if !w.sendEvent(Event{Name: filePath, Op: Create}) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   650
			return
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   651
		}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   652
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   653
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   654
	// like watchDirectoryFiles (but without doing another ReadDir)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   655
	filePath, err = w.internalWatch(filePath, fileInfo)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   656
	if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   657
		return err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   658
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   659
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   660
	w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   661
	w.fileExists[filePath] = struct{}{}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   662
	w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   663
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   664
	return nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   665
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   666
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   667
func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   668
	if fileInfo.IsDir() {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   669
		// mimic Linux providing delete events for subdirectories
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   670
		// but preserve the flags used if currently watching subdirectory
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   671
		w.mu.Lock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   672
		flags := w.dirFlags[name]
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   673
		w.mu.Unlock()
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   674
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   675
		flags |= unix.NOTE_DELETE | unix.NOTE_RENAME
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   676
		return w.addWatch(name, flags)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   677
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   678
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   679
	// watch file to mimic Linux inotify
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   680
	return w.addWatch(name, noteAllEvents)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   681
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   682
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   683
// Register events with the queue.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   684
func (w *Watcher) register(fds []int, flags int, fflags uint32) error {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   685
	changes := make([]unix.Kevent_t, len(fds))
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   686
	for i, fd := range fds {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   687
		// SetKevent converts int to the platform-specific types.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   688
		unix.SetKevent(&changes[i], fd, unix.EVFILT_VNODE, flags)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   689
		changes[i].Fflags = fflags
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   690
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   691
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   692
	// Register the events.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   693
	success, err := unix.Kevent(w.kq, changes, nil, nil)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   694
	if success == -1 {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   695
		return err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   696
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   697
	return nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   698
}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   699
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   700
// read retrieves pending events, or waits until an event occurs.
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   701
func (w *Watcher) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   702
	n, err := unix.Kevent(w.kq, nil, events, nil)
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   703
	if err != nil {
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   704
		return nil, err
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   705
	}
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   706
	return events[0:n], nil
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   707
}