internal unsafe RunningInstance( FileSystemWatcher watcher, string directory, bool includeChildren, FSEventStreamEventFlags filter) { Debug.Assert(!string.IsNullOrEmpty(directory)); // Make sure _fullPath doesn't contain a link or alias since the OS will give back the actual, // non link'd or alias'd paths. _fullDirectory = System.IO.Path.GetFullPath(directory); _fullDirectory = Interop.Sys.RealPath(_fullDirectory); if (_fullDirectory is null) { throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, isDirectory: true); } // Also ensure it has a trailing slash. if (!_fullDirectory.EndsWith('/')) { _fullDirectory += "/"; } _callback = new Interop.EventStream.FSEventStreamCallback(FileSystemEventCallback); _weakWatcher = new WeakReference <FileSystemWatcher>(watcher); _includeChildren = includeChildren; _filterFlags = filter; }
private static Interop.EventStream.FSEventStreamEventFlags TranslateFlags(NotifyFilters flagsToTranslate) { Interop.EventStream.FSEventStreamEventFlags flags = 0; // Always re-create the filter flags when start is called since they could have changed if ((flagsToTranslate & (NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Size)) != 0) { flags = Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemInodeMetaMod | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemFinderInfoMod | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemModified | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemChangeOwner; } if ((flagsToTranslate & NotifyFilters.Security) != 0) { flags |= Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemChangeOwner | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemXattrMod; } if ((flagsToTranslate & NotifyFilters.DirectoryName) != 0) { flags |= Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsDir | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsSymlink | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemCreated | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemRemoved | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemRenamed; } if ((flagsToTranslate & NotifyFilters.FileName) != 0) { flags |= Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsSymlink | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemCreated | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemRemoved | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemRenamed; } return(flags); }
/// <summary> /// Compares the given event flags to the filter flags and returns which event (if any) corresponds /// to those flags. /// </summary> private WatcherChangeTypes FilterEvents(Interop.EventStream.FSEventStreamEventFlags eventFlags, string fullPath) { const Interop.EventStream.FSEventStreamEventFlags changedFlags = Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemInodeMetaMod | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemFinderInfoMod | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemModified | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemChangeOwner | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemXattrMod; // If any of the Changed flags are set in both Filter and Event then a Changed event has occurred. if (((_filterFlags & changedFlags) & (eventFlags & changedFlags)) > 0) { return(WatcherChangeTypes.Changed); } // Disallow event coalescing. OSX likes to add a Created event to everything, particularly Changed events. if ((eventFlags & changedFlags) > 0) { return(0); } // Notify created/deleted/renamed events if they pass through the filters bool allowDirs = (_filterFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsDir) > 0; bool allowFiles = (_filterFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile) > 0; bool isDir = (eventFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsDir) > 0; bool isFile = (eventFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile) > 0; bool eventIsCorrectType = (isDir && allowDirs) || (isFile && allowFiles); bool eventIsLink = (eventFlags & (Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsHardlink | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsSymlink | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsLastHardlink)) > 0; if (eventIsCorrectType || ((allowDirs || allowFiles) && (eventIsLink))) { // Notify Renamed events. if (IsFlagSet(eventFlags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemRenamed)) { return(WatcherChangeTypes.Renamed); } else { // Notify Created/Deleted events. if ((IsFlagSet(eventFlags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemCreated)) && (IsFlagSet(eventFlags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemRemoved))) { // OS X is wonky where it can give back kFSEventStreamEventFlagItemCreated and kFSEventStreamEventFlagItemRemoved // for the same item. The only option we have is to stat and see if the item exists; if so send created, otherwise send deleted. WatcherChangeTypes wct = DoesItemExist(fullPath, IsFlagSet(eventFlags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile)) ? WatcherChangeTypes.Created : WatcherChangeTypes.Deleted; return(wct); } else if (IsFlagSet(eventFlags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemCreated)) { return(WatcherChangeTypes.Created); } else if (IsFlagSet(eventFlags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemRemoved)) { return(WatcherChangeTypes.Deleted); } } } return(0); }
private bool ShouldRescanOccur(Interop.EventStream.FSEventStreamEventFlags flags) { // Check if any bit is set that signals that the caller should rescan return(IsFlagSet(flags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagMustScanSubDirs) || IsFlagSet(flags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagUserDropped) || IsFlagSet(flags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagKernelDropped) || IsFlagSet(flags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagRootChanged) || IsFlagSet(flags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagMount) || IsFlagSet(flags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagUnmount)); }
internal RunningInstance( FileSystemWatcher watcher, string directory, bool includeChildren, Interop.EventStream.FSEventStreamEventFlags filter, CancellationToken cancelToken) { Debug.Assert(string.IsNullOrEmpty(directory) == false); Debug.Assert(!cancelToken.IsCancellationRequested); _weakWatcher = new WeakReference <FileSystemWatcher>(watcher); _fullDirectory = System.IO.Path.GetFullPath(directory); _includeChildren = includeChildren; _filterFlags = filter; _cancellationToken = cancelToken; _cancellationToken.Register(obj => ((RunningInstance)obj).CancellationCallback(), this); _stopping = false; }
/// <summary> /// Compares the given event flags to the filter flags and returns which event (if any) corresponds /// to those flags. /// </summary> private WatcherChangeTypes FilterEvents(Interop.EventStream.FSEventStreamEventFlags eventFlags, string fullPath) { const Interop.EventStream.FSEventStreamEventFlags changedFlags = Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemInodeMetaMod | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemFinderInfoMod | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemModified | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemChangeOwner | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemXattrMod; WatcherChangeTypes eventType = 0; // If any of the Changed flags are set in both Filter and Event then a Changed event has occurred. if (((_filterFlags & changedFlags) & (eventFlags & changedFlags)) > 0) { eventType |= WatcherChangeTypes.Changed; } // Notify created/deleted/renamed events if they pass through the filters bool allowDirs = (_filterFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsDir) > 0; bool allowFiles = (_filterFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile) > 0; bool isDir = (eventFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsDir) > 0; bool isFile = (eventFlags & Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsFile) > 0; bool eventIsCorrectType = (isDir && allowDirs) || (isFile && allowFiles); bool eventIsLink = (eventFlags & (Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsHardlink | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsSymlink | Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemIsLastHardlink)) > 0; if (eventIsCorrectType || ((allowDirs || allowFiles) && (eventIsLink))) { // Notify Created/Deleted/Renamed events. if (IsFlagSet(eventFlags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemRenamed)) { eventType |= WatcherChangeTypes.Renamed; } if (IsFlagSet(eventFlags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemCreated)) { eventType |= WatcherChangeTypes.Created; } if (IsFlagSet(eventFlags, Interop.EventStream.FSEventStreamEventFlags.kFSEventStreamEventFlagItemRemoved)) { eventType |= WatcherChangeTypes.Deleted; } } return(eventType); }
private static bool IsFlagSet(Interop.EventStream.FSEventStreamEventFlags flags, Interop.EventStream.FSEventStreamEventFlags value) { return((value & flags) == value); }
private static bool IsFlagSet(FSEventStreamEventFlags flags, FSEventStreamEventFlags value) { return((value & flags) == value); }