void Setup () { var initialFds = new List<int> (); // fsw.FullPath may end in '/', see https://bugzilla.xamarin.com/show_bug.cgi?id=5747 if (fsw.FullPath != "/" && fsw.FullPath.EndsWith ("/", StringComparison.Ordinal)) fullPathNoLastSlash = fsw.FullPath.Substring (0, fsw.FullPath.Length - 1); else fullPathNoLastSlash = fsw.FullPath; // GetFilenameFromFd() returns the *realpath* which can be different than fsw.FullPath because symlinks. // If so, introduce a fixup step. int fd = open (fullPathNoLastSlash, O_EVTONLY, 0); var resolvedFullPath = GetFilenameFromFd (fd); close (fd); if (resolvedFullPath != fullPathNoLastSlash) fixupPath = resolvedFullPath; else fixupPath = null; Scan (fullPathNoLastSlash, false, ref initialFds); var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)0 }; var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point var changes = CreateChangeList (ref initialFds); int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout); if (numEvents == -1) { var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", Marshal.GetLastWin32Error ()); throw new IOException (errMsg); } }
private void Monitor() { while (!KeventWatcher.stop) { kevent ev = default(kevent); ev.udata = IntPtr.Zero; kevent kevent = default(kevent); kevent.udata = IntPtr.Zero; timespec timespec = default(timespec); timespec.tv_sec = 0; timespec.tv_usec = 0; int num; lock (this) { num = KeventWatcher.kevent(KeventWatcher.conn, ref kevent, 0, ref ev, 1, ref timespec); } if (num > 0) { KeventData data = (KeventData)KeventWatcher.requests[ev.ident]; KeventWatcher.StopMonitoringDirectory(data); KeventWatcher.StartMonitoringDirectory(data); this.ProcessEvent(ev); } else { Thread.Sleep(500); } } lock (this) { KeventWatcher.thread = null; KeventWatcher.stop = false; } }
void Monitor() { while (!stop) { kevent ev = new kevent(); ev.udata = IntPtr.Zero; kevent nullev = new kevent(); nullev.udata = IntPtr.Zero; timespec ts = new timespec(); ts.tv_sec = 0; ts.tv_usec = 0; int haveEvents; lock (this) { haveEvents = kevent(conn, ref nullev, 0, ref ev, 1, ref ts); } if (haveEvents > 0) { // Restart monitoring KeventData data = (KeventData)requests [ev.ident]; StopMonitoringDirectory(data); StartMonitoringDirectory(data); ProcessEvent(ev); } else { System.Threading.Thread.Sleep(500); } } lock (this) { thread = null; stop = false; } }
private void Monitor() { while (!stop) { kevent evtlist = default(kevent); evtlist.udata = IntPtr.Zero; kevent ev = default(kevent); ev.udata = IntPtr.Zero; timespec ts = default(timespec); ts.tv_sec = 0; ts.tv_usec = 0; int num; lock (this) { num = kevent(conn, ref ev, 0, ref evtlist, 1, ref ts); } if (num > 0) { KeventData data = (KeventData)requests[evtlist.ident]; StopMonitoringDirectory(data); StartMonitoringDirectory(data); ProcessEvent(evtlist); } else { Thread.Sleep(500); } } lock (this) { thread = null; stop = false; } }
void Setup() { var initialFds = new List <int> (); // fsw.FullPath may end in '/', see https://bugzilla.xamarin.com/show_bug.cgi?id=5747 if (fsw.FullPath != "/" && fsw.FullPath.EndsWith("/", StringComparison.Ordinal)) { fullPathNoLastSlash = fsw.FullPath.Substring(0, fsw.FullPath.Length - 1); } else { fullPathNoLastSlash = fsw.FullPath; } // realpath() returns the *realpath* which can be different than fsw.FullPath because symlinks. // If so, introduce a fixup step. var sb = new StringBuilder(__DARWIN_MAXPATHLEN); if (realpath(fsw.FullPath, sb) == IntPtr.Zero) { var errMsg = String.Format("realpath({0}) failed, error code = '{1}'", fsw.FullPath, Marshal.GetLastWin32Error()); throw new IOException(errMsg); } var resolvedFullPath = sb.ToString(); if (resolvedFullPath != fullPathNoLastSlash) { fixupPath = resolvedFullPath; } else { fixupPath = null; } Scan(fullPathNoLastSlash, false, ref initialFds); var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_nsec = (IntPtr)0 }; var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point var changes = CreateChangeList(ref initialFds); int numEvents; int errno = 0; do { numEvents = kevent(conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout); if (numEvents == -1) { errno = Marshal.GetLastWin32Error(); } } while (numEvents == -1 && errno == EINTR); if (numEvents == -1) { var errMsg = String.Format("kevent() error at initial event registration, error code = '{0}'", errno); throw new IOException(errMsg); } }
static void StartMonitoringDirectory(KeventData data) { DirectoryInfo dir = new DirectoryInfo(data.Directory); if (data.DirEntries == null) { data.DirEntries = new Hashtable(); foreach (FileSystemInfo fsi in dir.GetFileSystemInfos()) { data.DirEntries.Add(fsi.FullName, new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime)); } } int fd = open(data.Directory, 0, 0); kevent ev = new kevent(); ev.udata = IntPtr.Zero; timespec nullts = new timespec(); nullts.tv_sec = 0; nullts.tv_usec = 0; if (fd > 0) { ev.ident = fd; ev.filter = EventFilter.Vnode; ev.flags = EventFlags.Add | EventFlags.Enable | EventFlags.OneShot; ev.fflags = // 20 | 2 | 1 | 8; FilterFlags.VNodeDelete | FilterFlags.VNodeWrite | FilterFlags.VNodeAttrib | // The following two values are the equivalent of the original value "20", but we suspect the original author meant // 0x20, we will review later with some test cases FilterFlags.VNodeLink | FilterFlags.VNodeExtend; ev.data = 0; ev.udata = Marshal.StringToHGlobalAuto(data.Directory); kevent outev = new kevent(); outev.udata = IntPtr.Zero; kevent(conn, ref ev, 1, ref outev, 0, ref nullts); data.ev = ev; requests [fd] = data; } if (!data.IncludeSubdirs) { return; } }
static void StartMonitoringDirectory(KeventData data) { DirectoryInfo dir = new DirectoryInfo(data.Directory); if (data.DirEntries == null) { data.DirEntries = new Hashtable(); foreach (FileSystemInfo fsi in dir.GetFileSystemInfos()) { data.DirEntries.Add(fsi.FullName, new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime)); } } int fd = open(data.Directory, 0, 0); kevent ev = new kevent(); ev.udata = IntPtr.Zero; timespec nullts = new timespec(); nullts.tv_sec = 0; nullts.tv_usec = 0; if (fd > 0) { ev.ident = fd; ev.filter = -4; ev.flags = 1 | 4 | 20; ev.fflags = 20 | 2 | 1 | 8; ev.data = 0; ev.udata = Marshal.StringToHGlobalAuto(data.Directory); kevent outev = new kevent(); outev.udata = IntPtr.Zero; kevent(conn, ref ev, 1, ref outev, 0, ref nullts); data.ev = ev; requests [fd] = data; } if (!data.IncludeSubdirs) { return; } }
private static void StartMonitoringDirectory(KeventData data) { DirectoryInfo directoryInfo = new DirectoryInfo(data.Directory); if (data.DirEntries == null) { data.DirEntries = new Hashtable(); FileSystemInfo[] fileSystemInfos = directoryInfo.GetFileSystemInfos(); foreach (FileSystemInfo fileSystemInfo in fileSystemInfos) { data.DirEntries.Add(fileSystemInfo.FullName, new KeventFileData(fileSystemInfo, fileSystemInfo.LastAccessTime, fileSystemInfo.LastWriteTime)); } } int num = open(data.Directory, 0, 0); kevent ev = default(kevent); ev.udata = IntPtr.Zero; timespec ts = default(timespec); ts.tv_sec = 0; ts.tv_usec = 0; if (num > 0) { ev.ident = num; ev.filter = -4; ev.flags = 21; ev.fflags = 31u; ev.data = 0; ev.udata = Marshal.StringToHGlobalAuto(data.Directory); kevent evtlist = default(kevent); evtlist.udata = IntPtr.Zero; kevent(conn, ref ev, 1, ref evtlist, 0, ref ts); data.ev = ev; requests[num] = data; } if (data.IncludeSubdirs) { } }
void Setup() { var initialFds = new List <int> (); // GetFilenameFromFd() returns the *realpath* which can be different than fsw.FullPath because symlinks. // If so, introduce a fixup step. int fd = open(fsw.FullPath, O_EVTONLY, 0); var resolvedFullPath = GetFilenameFromFd(fd); close(fd); if (resolvedFullPath != fsw.FullPath) { fixupPath = resolvedFullPath; } else { fixupPath = null; } Scan(fsw.FullPath, false, ref initialFds); var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)0 }; var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point var changes = CreateChangeList(ref initialFds); int numEvents = kevent(conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout); if (numEvents == -1) { var errMsg = String.Format("kevent() error at initial event registration, error code = '{0}'", Marshal.GetLastWin32Error()); throw new IOException(errMsg); } }
void Setup () { var initialFds = new List<int> (); // fsw.FullPath may end in '/', see https://bugzilla.xamarin.com/show_bug.cgi?id=5747 if (fsw.FullPath != "/" && fsw.FullPath.EndsWith ("/", StringComparison.Ordinal)) fullPathNoLastSlash = fsw.FullPath.Substring (0, fsw.FullPath.Length - 1); else fullPathNoLastSlash = fsw.FullPath; // realpath() returns the *realpath* which can be different than fsw.FullPath because symlinks. // If so, introduce a fixup step. var sb = new StringBuilder (__DARWIN_MAXPATHLEN); if (realpath(fsw.FullPath, sb) == IntPtr.Zero) { var errMsg = String.Format ("realpath({0}) failed, error code = '{1}'", fsw.FullPath, Marshal.GetLastWin32Error ()); throw new IOException (errMsg); } var resolvedFullPath = sb.ToString(); if (resolvedFullPath != fullPathNoLastSlash) fixupPath = resolvedFullPath; else fixupPath = null; Scan (fullPathNoLastSlash, false, ref initialFds); var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_nsec = (IntPtr)0 }; var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point var changes = CreateChangeList (ref initialFds); int numEvents; int errno = 0; do { numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout); if (numEvents == -1) { errno = Marshal.GetLastWin32Error (); } } while (numEvents == -1 && errno == EINTR); if (numEvents == -1) { var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", errno); throw new IOException (errMsg); } }
extern static int kevent(int kqueue, ref kevent ev, int nchanges, ref kevent evtlist, int nevents, ref timespec ts);
void Monitor () { while (!stop) { kevent ev = new kevent(); ev.udata = IntPtr.Zero; kevent nullev = new kevent(); nullev.udata = IntPtr.Zero; timespec ts = new timespec(); ts.tv_sec = 0; ts.tv_usec = 0; int haveEvents; lock (this) { haveEvents = kevent (conn, ref nullev, 0, ref ev, 1, ref ts); } if (haveEvents > 0) { // Restart monitoring KeventData data = (KeventData) requests [ev.ident]; StopMonitoringDirectory (data); StartMonitoringDirectory (data); ProcessEvent (ev); } else { System.Threading.Thread.Sleep (500); } } lock (this) { thread = null; stop = false; } }
static void StartMonitoringDirectory (KeventData data) { DirectoryInfo dir = new DirectoryInfo (data.Directory); if(data.DirEntries == null) { data.DirEntries = new Hashtable(); foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() ) data.DirEntries.Add(fsi.FullName, new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime)); } int fd = open(data.Directory, 0, 0); kevent ev = new kevent(); ev.udata = IntPtr.Zero; timespec nullts = new timespec(); nullts.tv_sec = 0; nullts.tv_usec = 0; if (fd > 0) { ev.ident = fd; ev.filter = -4; ev.flags = 1 | 4 | 20; ev.fflags = 20 | 2 | 1 | 8; ev.data = 0; ev.udata = Marshal.StringToHGlobalAuto (data.Directory); kevent outev = new kevent(); outev.udata = IntPtr.Zero; kevent (conn, ref ev, 1, ref outev, 0, ref nullts); data.ev = ev; requests [fd] = data; } if (!data.IncludeSubdirs) return; }
void Setup () { var initialFds = new List<int> (); // fsw.FullPath may end in '/', see https://bugzilla.xamarin.com/show_bug.cgi?id=5747 if (fsw.FullPath != "/" && fsw.FullPath.EndsWith ("/", StringComparison.Ordinal)) fullPathNoLastSlash = fsw.FullPath.Substring (0, fsw.FullPath.Length - 1); else fullPathNoLastSlash = fsw.FullPath; // GetFilenameFromFd() returns the *realpath* which can be different than fsw.FullPath because symlinks. // If so, introduce a fixup step. int fd = open (fullPathNoLastSlash, O_EVTONLY, 0); var resolvedFullPath = GetFilenameFromFd (fd); close (fd); if (resolvedFullPath != fullPathNoLastSlash) fixupPath = resolvedFullPath; else fixupPath = null; Scan (fullPathNoLastSlash, false, ref initialFds); var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_nsec = (IntPtr)0 }; var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point var changes = CreateChangeList (ref initialFds); int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout); if (numEvents == -1) { var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", Marshal.GetLastWin32Error ()); throw new IOException (errMsg); } }
void Monitor () { var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 }; var eventBuffer = new kevent[32]; var newFds = new List<int> (); List<PathData> removeQueue = new List<PathData> (); List<string> rescanQueue = new List<string> (); int retries = 0; while (!requestStop) { var changes = CreateChangeList (ref newFds); int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout); if (numEvents == -1) { if (++retries == 3) throw new IOException (String.Format ( "persistent kevent() error, error code = '{0}'", Marshal.GetLastWin32Error ())); continue; } retries = 0; for (var i = 0; i < numEvents; i++) { var kevt = eventBuffer [i]; var pathData = fdsDict [(int)kevt.ident]; if ((kevt.flags & EventFlags.Error) == EventFlags.Error) { var errMsg = String.Format ("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data); fsw.DispatchErrorEvents (new ErrorEventArgs (new IOException (errMsg))); continue; } if ((kevt.fflags & FilterFlags.VNodeDelete) == FilterFlags.VNodeDelete || (kevt.fflags & FilterFlags.VNodeRevoke) == FilterFlags.VNodeRevoke) { removeQueue.Add (pathData); continue; } if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) { UpdatePath (pathData); } if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) { if (pathData.IsDirectory) //TODO: Check if dirs trigger Changed events on .NET rescanQueue.Add (pathData.Path); else PostEvent (FileAction.Modified, pathData.Path); } if ((kevt.fflags & FilterFlags.VNodeAttrib) == FilterFlags.VNodeAttrib || (kevt.fflags & FilterFlags.VNodeExtend) == FilterFlags.VNodeExtend) PostEvent (FileAction.Modified, pathData.Path); } removeQueue.ForEach (Remove); removeQueue.Clear (); rescanQueue.ForEach (path => { Scan (path, true, ref newFds); }); rescanQueue.Clear (); } }
void Monitor () { var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 }; var eventBuffer = new kevent[32]; var newFds = new List<int> (); List<PathData> removeQueue = new List<PathData> (); List<string> rescanQueue = new List<string> (); while (!requestStop) { var changes = CreateChangeList (ref newFds); int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout); if (numEvents == -1) { var errMsg = String.Format ("kevent() error, error code = '{0}'", Marshal.GetLastWin32Error ()); fsw.OnError (new ErrorEventArgs (new IOException (errMsg))); } if (numEvents == 0) continue; for (var i = 0; i < numEvents; i++) { var kevt = eventBuffer [i]; var pathData = fdsDict [(int)kevt.ident]; if ((kevt.flags & EventFlags.Error) == EventFlags.Error) { var errMsg = String.Format ("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data); fsw.OnError (new ErrorEventArgs (new IOException (errMsg))); continue; } if ((kevt.fflags & FilterFlags.VNodeDelete) == FilterFlags.VNodeDelete || (kevt.fflags & FilterFlags.VNodeRevoke) == FilterFlags.VNodeRevoke) removeQueue.Add (pathData); else if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) { if (pathData.IsDirectory) rescanQueue.Add (pathData.Path); else PostEvent (FileAction.Modified, pathData.Path); } else if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) { var newFilename = GetFilenameFromFd (pathData.Fd); if (newFilename.StartsWith (fsw.FullPath)) Rename (pathData, newFilename); else //moved outside of our watched dir so stop watching RemoveTree (pathData); } else if ((kevt.fflags & FilterFlags.VNodeAttrib) == FilterFlags.VNodeAttrib || (kevt.fflags & FilterFlags.VNodeExtend) == FilterFlags.VNodeExtend) PostEvent (FileAction.Modified, pathData.Path); } removeQueue.ForEach (Remove); removeQueue.Clear (); rescanQueue.ForEach (path => { Scan (path, true, ref newFds); }); rescanQueue.Clear (); } }
void Setup () { var initialFds = new List<int> (); // GetFilenameFromFd() returns the *realpath* which can be different than fsw.FullPath because symlinks. // If so, introduce a fixup step. int fd = open (fsw.FullPath, O_EVTONLY, 0); var resolvedFullPath = GetFilenameFromFd (fd); close (fd); if (resolvedFullPath != fsw.FullPath) fixupPath = resolvedFullPath; else fixupPath = null; Scan (fsw.FullPath, false, ref initialFds); var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)0 }; var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point var changes = CreateChangeList (ref initialFds); int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout); if (numEvents == -1) { var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", Marshal.GetLastWin32Error ()); throw new IOException (errMsg); } }
void Monitor() { var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 }; var eventBuffer = new kevent[32]; var newFds = new List <int> (); List <PathData> removeQueue = new List <PathData> (); List <string> rescanQueue = new List <string> (); int retries = 0; while (!requestStop) { var changes = CreateChangeList(ref newFds); int numEvents = kevent(conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout); if (numEvents == -1) { if (++retries == 3) { throw new IOException(String.Format( "persistent kevent() error, error code = '{0}'", Marshal.GetLastWin32Error())); } continue; } retries = 0; for (var i = 0; i < numEvents; i++) { var kevt = eventBuffer [i]; var pathData = fdsDict [(int)kevt.ident]; if ((kevt.flags & EventFlags.Error) == EventFlags.Error) { var errMsg = String.Format("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data); fsw.DispatchErrorEvents(new ErrorEventArgs(new IOException(errMsg))); continue; } if ((kevt.fflags & FilterFlags.VNodeDelete) == FilterFlags.VNodeDelete || (kevt.fflags & FilterFlags.VNodeRevoke) == FilterFlags.VNodeRevoke) { removeQueue.Add(pathData); continue; } if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) { UpdatePath(pathData); } if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) { if (pathData.IsDirectory) //TODO: Check if dirs trigger Changed events on .NET { rescanQueue.Add(pathData.Path); } else { PostEvent(FileAction.Modified, pathData.Path); } } if ((kevt.fflags & FilterFlags.VNodeAttrib) == FilterFlags.VNodeAttrib || (kevt.fflags & FilterFlags.VNodeExtend) == FilterFlags.VNodeExtend) { PostEvent(FileAction.Modified, pathData.Path); } } removeQueue.ForEach(Remove); removeQueue.Clear(); rescanQueue.ForEach(path => { Scan(path, true, ref newFds); }); rescanQueue.Clear(); } }
void Monitor() { var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 }; var eventBuffer = new kevent[32]; var newFds = new List <int> (); List <PathData> removeQueue = new List <PathData> (); List <string> rescanQueue = new List <string> (); while (!requestStop) { var changes = CreateChangeList(ref newFds); int numEvents = kevent(conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout); if (numEvents == -1) { var errMsg = String.Format("kevent() error, error code = '{0}'", Marshal.GetLastWin32Error()); fsw.OnError(new ErrorEventArgs(new IOException(errMsg))); } if (numEvents == 0) { continue; } for (var i = 0; i < numEvents; i++) { var kevt = eventBuffer [i]; var pathData = fdsDict [(int)kevt.ident]; if ((kevt.flags & EventFlags.Error) == EventFlags.Error) { var errMsg = String.Format("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data); fsw.OnError(new ErrorEventArgs(new IOException(errMsg))); continue; } if ((kevt.fflags & FilterFlags.VNodeDelete) == FilterFlags.VNodeDelete || (kevt.fflags & FilterFlags.VNodeRevoke) == FilterFlags.VNodeRevoke) { removeQueue.Add(pathData); } else if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) { if (pathData.IsDirectory) { rescanQueue.Add(pathData.Path); } else { PostEvent(FileAction.Modified, pathData.Path); } } else if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) { var newFilename = GetFilenameFromFd(pathData.Fd); if (newFilename.StartsWith(fsw.FullPath)) { Rename(pathData, newFilename); } else //moved outside of our watched dir so stop watching { RemoveTree(pathData); } } else if ((kevt.fflags & FilterFlags.VNodeAttrib) == FilterFlags.VNodeAttrib || (kevt.fflags & FilterFlags.VNodeExtend) == FilterFlags.VNodeExtend) { PostEvent(FileAction.Modified, pathData.Path); } } removeQueue.ForEach(Remove); removeQueue.Clear(); rescanQueue.ForEach(path => { Scan(path, true, ref newFds); }); rescanQueue.Clear(); } }
static void StartMonitoringDirectory (KeventData data) { DirectoryInfo dir = new DirectoryInfo (data.Directory); if(data.DirEntries == null) { data.DirEntries = new Hashtable(); foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() ) data.DirEntries.Add(fsi.FullName, new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime)); } int fd = open(data.Directory, 0, 0); kevent ev = new kevent(); ev.udata = IntPtr.Zero; timespec nullts = new timespec(); nullts.tv_sec = 0; nullts.tv_usec = 0; if (fd > 0) { ev.ident = fd; ev.filter = EventFilter.Vnode; ev.flags = EventFlags.Add | EventFlags.Enable | EventFlags.OneShot; ev.fflags = // 20 | 2 | 1 | 8; FilterFlags.VNodeDelete | FilterFlags.VNodeWrite | FilterFlags.VNodeAttrib | // The following two values are the equivalent of the original value "20", but we suspect the original author meant // 0x20, we will review later with some test cases FilterFlags.VNodeLink | FilterFlags.VNodeExtend; ev.data = 0; ev.udata = Marshal.StringToHGlobalAuto (data.Directory); kevent outev = new kevent(); outev.udata = IntPtr.Zero; kevent (conn, ref ev, 1, ref outev, 0, ref nullts); data.ev = ev; requests [fd] = data; } if (!data.IncludeSubdirs) return; }
static int kevent(int kqueue, ref kevent ev, int nchanges, ref kevent evtlist, int nevents, ref timespec ts) { throw new System.NotImplementedException(); }
extern static int kevent(int kq, [In] kevent[] ev, int nchanges, [Out] kevent[] evtlist, int nevents, [In] ref timespec time);