int DoAddInotify(wxFSWatchEntry* watch) { int flags = Watcher2NativeFlags(watch->GetFlags()); int wd = inotify_add_watch(m_ifd, watch->GetPath().fn_str(), flags); // finally we can set watch descriptor watch->SetWatchDescriptor(wd); return wd; }
virtual bool DoAdd(wxSharedPtr<wxFSWatchEntryKq> watch) { wxCHECK_MSG( IsOk(), false, "Kqueue not initialized or invalid kqueue descriptor" ); struct kevent event; int action = EV_ADD | EV_ENABLE | EV_CLEAR | EV_ERROR; int flags = Watcher2NativeFlags(watch->GetFlags()); EV_SET( &event, watch->GetFileDescriptor(), EVFILT_VNODE, action, flags, 0, watch.get() ); // TODO more error conditions according to man // TODO best deal with the error here int ret = kevent(m_kfd, &event, 1, NULL, 0, NULL); if (ret == -1) { wxLogSysError(_("Unable to add kqueue watch")); return false; } return true; }
bool wxFSWatcherImplMSW::DoSetUpWatch(wxFSWatchEntryMSW& watch) { BOOL bWatchSubtree wxDUMMY_INITIALIZE(FALSE); switch ( watch.GetType() ) { case wxFSWPath_File: wxLogError(_("Monitoring individual files for changes is not " "supported currently.")); return false; case wxFSWPath_Dir: bWatchSubtree = FALSE; break; case wxFSWPath_Tree: bWatchSubtree = TRUE; break; case wxFSWPath_None: wxFAIL_MSG( "Invalid watch type." ); return false; } int flags = Watcher2NativeFlags(watch.GetFlags()); int ret = ReadDirectoryChangesW(watch.GetHandle(), watch.GetBuffer(), wxFSWatchEntryMSW::BUFFER_SIZE, bWatchSubtree, flags, NULL, watch.GetOverlapped(), NULL); if (!ret) { wxLogSysError(_("Unable to set up watch for '%s'"), watch.GetPath()); } return ret != 0; }
void ProcessNativeEvent(const inotify_event& inevt) { wxLogTrace(wxTRACE_FSWATCHER, InotifyEventToString(inevt)); // after removing inotify watch we get IN_IGNORED for it, but the watch // will be already removed from our list at that time if (inevt.mask & IN_IGNORED) { return; } // get watch entry for this event wxFSWatchEntryDescriptors::iterator it = m_watchMap.find(inevt.wd); wxCHECK_RET(it != m_watchMap.end(), "Watch descriptor not present in the watch map!"); wxFSWatchEntry& watch = *(it->second); int nativeFlags = inevt.mask; int flags = Native2WatcherFlags(nativeFlags); // check out for error/warning condition if (flags & wxFSW_EVENT_WARNING || flags & wxFSW_EVENT_ERROR) { wxString errMsg = GetErrorDescription(Watcher2NativeFlags(flags)); wxFileSystemWatcherEvent event(flags, errMsg); SendEvent(event); } // filter out ignored events and those not asked for. // we never filter out warnings or exceptions else if ((flags == 0) || !(flags & watch.GetFlags())) { return; } // renames else if (nativeFlags & IN_MOVE) { wxInotifyCookies::iterator it = m_cookies.find(inevt.cookie); if ( it == m_cookies.end() ) { int size = sizeof(inevt) + inevt.len; inotify_event* e = (inotify_event*) operator new (size); memcpy(e, &inevt, size); wxInotifyCookies::value_type val(e->cookie, e); m_cookies.insert(val); } else { inotify_event& oldinevt = *(it->second); wxFileSystemWatcherEvent event(flags); if ( inevt.mask & IN_MOVED_FROM ) { event.SetPath(GetEventPath(watch, inevt)); event.SetNewPath(GetEventPath(watch, oldinevt)); } else { event.SetPath(GetEventPath(watch, oldinevt)); event.SetNewPath(GetEventPath(watch, inevt)); } SendEvent(event); m_cookies.erase(it); delete &oldinevt; } } // every other kind of event else { wxFileName path = GetEventPath(watch, inevt); wxFileSystemWatcherEvent event(flags, path, path); SendEvent(event); } }
void ProcessNativeEvent(const inotify_event& inevt) { wxLogTrace(wxTRACE_FSWATCHER, InotifyEventToString(inevt)); // after removing inotify watch we get IN_IGNORED for it, but the watch // will be already removed from our list at that time if (inevt.mask & IN_IGNORED) { // It is now safe to remove it from the stale descriptors too, we // won't get any more events for it. // However if we're here because a dir that we're still watching // has just been deleted, its wd won't be on this list const int pos = m_staleDescriptors.Index(inevt.wd); if ( pos != wxNOT_FOUND ) { m_staleDescriptors.RemoveAt(static_cast<size_t>(pos)); wxLogTrace(wxTRACE_FSWATCHER, "Removed wd %i from the stale-wd cache", inevt.wd); } return; } // get watch entry for this event wxFSWatchEntryDescriptors::iterator it = m_watchMap.find(inevt.wd); if (it == m_watchMap.end()) { // It's not in the map; check if was recently removed from it. if (m_staleDescriptors.Index(inevt.wd) != wxNOT_FOUND) { wxLogTrace(wxTRACE_FSWATCHER, "Got an event for stale wd %i", inevt.wd); } else { wxFAIL_MSG("Event for unknown watch descriptor."); } // In any case, don't process this event: it's either for an // already removed entry, or for a completely unknown one. return; } wxFSWatchEntry& watch = *(it->second); int nativeFlags = inevt.mask; int flags = Native2WatcherFlags(nativeFlags); // check out for error/warning condition if (flags & wxFSW_EVENT_WARNING || flags & wxFSW_EVENT_ERROR) { wxString errMsg = GetErrorDescription(Watcher2NativeFlags(flags)); wxFileSystemWatcherEvent event(flags, errMsg); SendEvent(event); } // filter out ignored events and those not asked for. // we never filter out warnings or exceptions else if ((flags == 0) || !(flags & watch.GetFlags())) { return; } // Creation // We need do something here only if the original watch was recursive; // we don't watch a child dir itself inside a non-tree watch. // We watch only dirs explicitly, so we don't want file IN_CREATEs. // Distinguish by whether nativeFlags contain IN_ISDIR else if ((nativeFlags & IN_CREATE) && (watch.GetType() == wxFSWPath_Tree) && (inevt.mask & IN_ISDIR)) { wxFileName fn = GetEventPath(watch, inevt); // Though it's a dir, fn treats it as a file. So: fn.AssignDir(fn.GetFullPath()); if (m_watcher->AddAny(fn, wxFSW_EVENT_ALL, wxFSWPath_Tree, watch.GetFilespec())) { // Tell the owner, in case it's interested // If there's a filespec, assume he's not if (watch.GetFilespec().empty()) { wxFileSystemWatcherEvent event(flags, fn, fn); SendEvent(event); } } } // Deletion // We watch only dirs explicitly, so we don't want file IN_DELETEs. // We obviously can't check using DirExists() as the object has been // deleted; and nativeFlags here doesn't contain IN_ISDIR, even for // a dir. Fortunately IN_DELETE_SELF doesn't happen for files. We need // to do something here only inside a tree watch, or if it's the parent // dir that's deleted. Otherwise let the parent dir cope else if ((nativeFlags & IN_DELETE_SELF) && ((watch.GetType() == wxFSWPath_Dir) || (watch.GetType() == wxFSWPath_Tree))) { // We must remove the deleted directory from the map, so that // DoRemoveInotify() isn't called on it in the future. Don't assert // if the wd isn't found: repeated IN_DELETE_SELFs can occur wxFileName fn = GetEventPath(watch, inevt); wxString path(fn.GetPathWithSep()); if (m_watchMap.erase(inevt.wd) == 1) { // Delete from wxFileSystemWatcher wxDynamicCast(m_watcher, wxInotifyFileSystemWatcher)-> OnDirDeleted(path); // Now remove from our local list of watched items wxFSWatchEntries::iterator wit = m_watches.find(path); if (wit != m_watches.end()) { m_watches.erase(wit); } // Cache the wd in case any events arrive late m_staleDescriptors.Add(inevt.wd); } // Tell the owner, in case it's interested // If there's a filespec, assume he's not if (watch.GetFilespec().empty()) { wxFileSystemWatcherEvent event(flags, fn, fn); SendEvent(event); } } // renames else if (nativeFlags & IN_MOVE) { wxInotifyCookies::iterator it2 = m_cookies.find(inevt.cookie); if ( it2 == m_cookies.end() ) { int size = sizeof(inevt) + inevt.len; inotify_event* e = (inotify_event*) operator new (size); memcpy(e, &inevt, size); wxInotifyCookies::value_type val(e->cookie, e); m_cookies.insert(val); } else { inotify_event& oldinevt = *(it2->second); // Tell the owner, in case it's interested // If there's a filespec, assume he's not if ( watch.GetFilespec().empty() ) { wxFileSystemWatcherEvent event(flags); if ( inevt.mask & IN_MOVED_FROM ) { event.SetPath(GetEventPath(watch, inevt)); event.SetNewPath(GetEventPath(watch, oldinevt)); } else { event.SetPath(GetEventPath(watch, oldinevt)); event.SetNewPath(GetEventPath(watch, inevt)); } SendEvent(event); } m_cookies.erase(it2); delete &oldinevt; } } // every other kind of event else { wxFileName path = GetEventPath(watch, inevt); // For files, check that it matches any filespec if ( MatchesFilespec(path, watch.GetFilespec()) ) { wxFileSystemWatcherEvent event(flags, path, path); SendEvent(event); } } }