fsnotify
fsnotify copied to clipboard
Support additional event types
We only have Create, Remove, Rename, Write, and Chmod now, but many watchers support additional events. This has come up a few times:
- #24 - Extend, Link, Revoke
- #297 - Unmount
- #346 - Read
- #504 - Open, Close
- Probably some others?
Instead of creating a bunch of issues for every possible event, track them here.
All of this depends on #7; we don't want to spam people with e.g. Open and Close events when they're not interested in them (which is most of the time), and some events aren't supported on all platforms.
I looked around a bit, and:
-
Linux has OPEN and CLOSE events, FreeBSD has NOTE_OPEN, NOTE_CLOSE, NOTE_CLOSE_WRITE, but none of the other kqueue platforms do; Windows and FEN doesn't have it either.
-
Unmount is available on inotify and FEN, but none of the kqueue platforms or Windows.
-
Read is on FreeBSD, Linux (as ACCESS), FEN (as ACCESS), Windows (LAST_ACCESS), but none of the other kqueue platforms.
As far as I can see, there are no events that are shared by all platforms.
Need to think about how to best deal with this; #67 would be okay for some rare operations, but things like Read is available on quite a few platforms, and using a new .Sys() would be awkward.
One way might be creating a new UnportableOp type:
// UnportableOp are file operations that are not available on all platforms.
type UnportableOp uint32
const (
Read OP = 1 << iota
Open
Close
// ...
)
type Event struct {
Name string
Op Op
Unportable UnportableOp
}
func (e Event) HasUnportable(op UnportableOp) bool {
return e.Unportable.Has(op)
}
This way it's always clear you're using unportable operations and can't accidentally do e.Has(fsnotify.Read) and expecting it to work on all platforms; I don't trust people to read the documentation because experience has proven many don't (plus, it's easy to forget). On the other hand, having two types is a bit of a pain.
@arp242 What about leveraging GOOS build tags to limit which events can be used?
You could have a file or package for windows specific events, one for inotify specific events, etc
If each platform's non-portable bits had their own package, their usage limitations would be self documenting (eg inotify.Close, defined in github.com/fsnotify/fsnotify/pkg/inotify)
Would there be a problem with making this seamlessly handled by go build, without any kind of explicit opt-in?
With non-portable events guarded by build flags, if someone tried to build the following code for darwin, they'd get a compilation error:
event := <-watcher.Events
if event.Has(inotify.Close) {
fmt.Println("File was closed")
}
The problem with that is that many unportable events are supported by more than one platform. And even for events on one platform it's awkward to have fallbacks – I suppose you could make special handling for every platform, but that somewhat defeats the purpose of this library.
Anyway, proposal at: #629
Overview of additional event types:
inotify
IN_ACCESS File was accessed (e.g., read(2), execve(2)).
IN_CLOSE_NOWRITE File or directory not opened for writing was closed.
IN_CLOSE_WRITE File opened for writing was closed.
IN_OPEN File or directory was opened.
fanotify
FAN_ACCESS file or a directory (but see BUGS) was accessed (read).
FAN_CLOSE_NOWRITE file or directory that was opened read-only (O_RDONLY) was closed.
FAN_CLOSE_WRITE file that was opened for writing (O_WRONLY or O_RDWR) was closed.
FAN_FS_ERROR filesystem error was detected.
FAN_OPEN file or a directory was opened.
FAN_OPEN_EXEC file was opened with the intent to be executed.
FreeBSD
NOTE_CLOSE A file descriptor referencing the monitored file, was closed. The closed file de scriptor did not have write access.
NOTE_CLOSE_WRITE A file descriptor referencing the monitored file, was closed. The closed file descriptor had write access.
NOTE_EXTEND For regular file, the file referenced by the descriptor was extended.
NOTE_LINK The link count on the file changed.
NOTE_OPEN The file referenced by the descriptor was opened.
NOTE_READ A read occurred on the file referenced by the descriptor.
NOTE_REVOKE Access to the file was revoked via revoke(2) or the underlying file system was unmounted.
OpenBSD
NOTE_EXTEND The file referenced by the descriptor was extended.
NOTE_LINK The link count on the file changed.
NOTE_TRUNCATE The file referenced by the descriptor was truncated.
NetBSD
NOTE_EXTEND The file referenced by the descriptor was extended.
NOTE_LINK The link count on the file changed.
NOTE_REVOKE Access to the file was revoked via revoke(2) or the underlying file system was unmounted.
Added in NetBSD 10 (March 2024, needs update to x/sys)
NOTE_CLOSE A file descriptor without write access referencing the file was closed.
NOTE_CLOSE_WRITE A file descriptor with write access referencing the file was closed.
NOTE_OPEN The file referenced by the descriptor was opened.
NOTE_READ A read occurred on the file referenced by the descriptor.
DragonflyBSD
NOTE_EXTEND The file referenced by the descriptor was extended.
NOTE_LINK The link count on the file changed.
NOTE_REVOKE Access to the file was revoked via revoke(2) or the underlying fileystem was unmounted.
FEN
FILE_ACCESS fo_atime change
FILE_TRUNC op that induced the time stamp update also truncated the file
MOUNTEDOVER /* Monitored file/directory was mounted over */
UNMOUNTED /* Monitored file system got unmounted */
Windows
CHANGE_LAST_ACCESS Any change to the last access time
CHANGE_SIZE Any file-size change in the watched directory or subtree (might reasonably emulate CloseWrite?)
fsevents
?