Documentation ¶
Overview ¶
Package notify implements access to filesystem events.
Notify is a high-level abstraction over filesystem watchers like inotify, kqueue, FSEvents, FEN or ReadDirectoryChangesW. Watcher implementations are split into two groups: ones that natively support recursive notifications (FSEvents and ReadDirectoryChangesW) and ones that do not (inotify, kqueue, FEN). For more details see watcher and recursiveWatcher interfaces in watcher.go source file.
On top of filesystem watchers notify maintains a watchpoint tree, which provides strategy for creating and closing filesystem watches and dispatching filesystem events to user channels.
An event set is just an event list joint using bitwise OR operator into a single event value.
A filesystem watch or just a watch is platform-specific entity which represents a single path registered for notifications for specific event set. Setting a watch means using platform-specific API calls for creating / initializing said watch. For each watcher the API call is:
- FSEvents: FSEventStreamCreate
- inotify: notify_add_watch
- kqueue: kevent
- ReadDirectoryChangesW: CreateFile+ReadDirectoryChangesW
- FEN: port_get
To rewatch means to either shrink or expand an event set that was previously registered during watch operation for particular filesystem watch.
A watchpoint is a list of user channel and event set pairs for particular path (watchpoint tree's node). A single watchpoint can contain multiple different user channels registered to listen for one or more events. A single user channel can be registered in one or more watchpoints, recurisve and non-recursive ones as well.
Index ¶
Constants ¶
const ( Create = osSpecificCreate Remove = osSpecificRemove Write = osSpecificWrite Rename = osSpecificRename // All is handful alias for all platform-independent event values. All = Create | Remove | Write | Rename )
Create, Remove, Write and Rename are the only event values guaranteed to be present on all platforms.
const ( InAccess = Event(syscall.IN_ACCESS) // File was accessed InModify = Event(syscall.IN_MODIFY) // File was modified InAttrib = Event(syscall.IN_ATTRIB) // Metadata changed InCloseWrite = Event(syscall.IN_CLOSE_WRITE) // Writtable file was closed InCloseNowrite = Event(syscall.IN_CLOSE_NOWRITE) // Unwrittable file closed InOpen = Event(syscall.IN_OPEN) // File was opened InMovedFrom = Event(syscall.IN_MOVED_FROM) // File was moved from X InMovedTo = Event(syscall.IN_MOVED_TO) // File was moved to Y InCreate = Event(syscall.IN_CREATE) // Subfile was created InDelete = Event(syscall.IN_DELETE) // Subfile was deleted InDeleteSelf = Event(syscall.IN_DELETE_SELF) // Self was deleted InMoveSelf = Event(syscall.IN_MOVE_SELF) // Self was moved )
Inotify specific masks are legal, implemented events that are guaranteed to work with notify package on linux-based systems.
Variables ¶
This section is empty.
Functions ¶
func Stop ¶
func Stop(c chan<- EventInfo)
Stop removes all watchpoints registered for c. All underlying watches are also removed, for which c was the last channel listening for events.
Stop does not close c. When Stop returns, it is guranteed that c will receive no more signals.
func Watch ¶
Watch sets up a watchpoint on path listening for events given by the events argument.
File or directory given by the path must exist, otherwise Watch will fail with non-nil error. Notify resolves, for its internal purpose, any symlinks the provided path may contain, so it may fail if the symlinks form a cycle. It does so, since not all watcher implementations treat passed paths as-is. E.g. FSEvents reports a real path for every event, setting a watchpoint on /tmp will report events with paths rooted at /private/tmp etc.
The c almost always is a buffered channel. Watch will not block sending to c - the caller must ensure that c has sufficient buffer space to keep up with the expected event rate.
It is allowed to pass the same channel multiple times with different event list or different paths. Calling Watch with different event lists for a single watchpoint expands its event set. The only way to shrink it, is to call Stop on its channel.
Calling Watch with empty event list does expand nor shrink watchpoint's event set. If c is the first channel to listen for events on the given path, Watch will seamlessly create a watch on the filesystem.
Notify dispatches copies of single filesystem event to all channels registered for each path. If a single filesystem event contains multiple coalesced events, each of them is dispatched separately. E.g. the following filesystem change:
~ $ echo Hello > Notify.txt
dispatches two events - notify.Create and notify.Write. However, it may depend on the underlying watcher implementation whether OS reports both of them.
Windows and recursive watches ¶
If a directory which path was used to create recursive watch under Windows gets deleted, the OS will not report such event. It is advised to keep in mind this limitation while setting recursive watchpoints for your application, e.g. use persistant paths like %userprofile% or watch additionally parent directory of a recursive watchpoint in order to receive delete events for it.
Types ¶
type Event ¶
type Event uint32
Event represents the type of filesystem action.
Number of available event values is dependent on the target system or the watcher implmenetation used (e.g. it's possible to use either kqueue or FSEvents on Darwin).
Please consult documentation for your target platform to see list of all available events.
type EventInfo ¶
type EventInfo interface { Event() Event // event value for the filesystem action Path() string // real path of the file or directory Sys() interface{} // underlying data source (can return nil) }
EventInfo describes an event reported by the underlying filesystem notification subsystem.
It always describes single event, even if the OS reported a coalesced action. Reported path is absolute and clean.
For non-recursive watchpoints its base is always equal to the path passed to corresponding Watch call.
The value of Sys if system-dependent and can be nil.
Sys ¶
Under Darwin (FSEvents) Sys() always returns a non-nil *notify.FSEvent value, which is defined as:
type FSEvent struct { Path string // real path of the file or directory ID uint64 // ID of the event (FSEventStreamEventId) Flags uint32 // joint FSEvents* flags (FSEventStreamEventFlags) }
For possible values of Flags see Darwin godoc for notify or FSEvents documentation for FSEventStreamEventFlags constants:
https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/index.html#//apple_ref/doc/constant_group/FSEventStreamEventFlags
Under Linux (inotify) Sys() always returns a non-nil *syscall.InotifyEvent value, defined as:
type InotifyEvent struct { Wd int32 // Watch descriptor Mask uint32 // Mask describing event Cookie uint32 // Unique cookie associating related events (for rename(2)) Len uint32 // Size of name field Name [0]uint8 // Optional null-terminated name }
More information about inotify masks and the usage of inotify_event structure can be found at:
http://man7.org/linux/man-pages/man7/inotify.7.html
Under Darwin, DragonFlyBSD, FreeBSD, NetBSD, OpenBSD (kqueue) Sys() always returns a non-nil *notify.Kevent value, which is defined as:
type Kevent struct { Kevent *syscall.Kevent_t // Kevent is a kqueue specific structure FI os.FileInfo // FI describes file/dir }
More information about syscall.Kevent_t can be found at:
https://www.freebsd.org/cgi/man.cgi?query=kqueue
Under Windows (ReadDirectoryChangesW) Sys() always returns nil. The documentation of watcher's WinAPI function can be found at:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx
Notes ¶
Bugs ¶
Notify does not collect watchpoints, when underlying watches were removed by their os-specific watcher implementations. Instead users are advised to listen on persistant paths to have guarantee they receive events for the whole lifetime of their applications (to discuss see #69).
Linux (inotify) does not support watcher behavior masks like InOneshot, InOnlydir etc. Instead users are advised to perform the filtering themselves (to discuss see #71).
Notify was not tested for short path name support under Windows (ReadDirectoryChangesW).
Windows (ReadDirectoryChangesW) cannot recognize which notification triggers FileActionModified event. (to discuss see #75).