12 #include <mrpt/config.h>
14 #ifdef MRPT_OS_WINDOWS
16 # define _WIN32_WINNT 0x0400
21 #include <sys/inotify.h>
42 m_watchedDirectory(path)
50 #ifdef MRPT_OS_WINDOWS
52 HANDLE hDir = CreateFileA(
55 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
58 FILE_FLAG_BACKUP_SEMANTICS,
60 if( hDir == INVALID_HANDLE_VALUE )
66 m_hNotif =
static_cast<void*
>(hDir);
75 m_fd = inotify_init();
80 m_wd = inotify_add_watch(
83 IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM | IN_CREATE | IN_ACCESS
99 #ifdef MRPT_OS_WINDOWS
104 if (!m_watchThread.isClear())
106 CloseHandle(HANDLE(m_hNotif));
110 # if MRPT_HAS_INOTIFY
117 inotify_rm_watch(m_fd, m_wd);
130 #ifdef MRPT_OS_WINDOWS
132 ASSERTMSG_(m_hNotif!=NULL,
"CFileSystemWatcher was not initialized correctly.")
136 while (!m_queue_events_win32.empty())
141 out_list.push_back(*
obj);
148 # if MRPT_HAS_INOTIFY
167 FD_SET (m_fd, &rfds);
169 ret = select (m_fd + 1, &rfds, NULL, NULL, &time);
172 perror (
"[CFileSystemWatcher::getChanges] select");
180 else if (FD_ISSET (m_fd, &rfds))
185 #define EVENT_SIZE (sizeof (struct inotify_event))
188 #define BUF_LEN (1024 * (EVENT_SIZE + 16))
193 len = read (m_fd, buf, BUF_LEN);
201 perror (
"[CFileSystemWatcher::getChanges] read");
210 struct inotify_event event_val;
211 ::memcpy(&event_val, &buf[i],
sizeof(event_val));
212 struct inotify_event *
event = &event_val;
214 i += EVENT_SIZE +
event->len;
219 if (event->len) eventName =
event->name;
223 if ( 0==(event->mask & IN_UNMOUNT) &&
224 0==(event->mask & IN_Q_OVERFLOW) &&
225 0==(event->mask & IN_IGNORED) )
230 newEntry.
isDir =
event->mask & IN_ISDIR;
239 out_list.push_back( newEntry );
250 #ifdef MRPT_OS_WINDOWS
252 void CFileSystemWatcher::thread_win32_watch()
258 while(ReadDirectoryChangesW(
263 FILE_NOTIFY_CHANGE_FILE_NAME |
264 FILE_NOTIFY_CHANGE_DIR_NAME |
265 FILE_NOTIFY_CHANGE_ATTRIBUTES |
266 FILE_NOTIFY_CHANGE_SIZE |
267 FILE_NOTIFY_CHANGE_LAST_WRITE |
268 FILE_NOTIFY_CHANGE_LAST_ACCESS |
269 FILE_NOTIFY_CHANGE_CREATION,
280 FILE_NOTIFY_INFORMATION *fni =
reinterpret_cast<FILE_NOTIFY_INFORMATION*
>(&buf[idx]);
283 ASSERTMSG_(fni->FileNameLength<10000,
"Name length >10K... this is probably an error")
285 int reqLen = WideCharToMultiByte(CP_UTF8,0,fni->FileName,fni->FileNameLength >> 1,NULL,0,NULL, NULL);
286 std::vector<
char> tmpBuf(reqLen);
287 int actLen = WideCharToMultiByte(CP_UTF8,0,fni->FileName,fni->FileNameLength >> 1,&tmpBuf[0],tmpBuf.
size(),NULL, NULL);
288 ASSERTMSG_(actLen>0,"Error converting filename from WCHAR* to UTF8")
290 const std::
string filName(&tmpBuf[0],actLen);
292 TFileSystemChange newEntry;
299 case FILE_ACTION_ADDED:
301 newEntry.eventCreated =
true;
302 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
304 case FILE_ACTION_REMOVED:
306 newEntry.eventDeleted =
true;
307 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
309 case FILE_ACTION_MODIFIED:
311 newEntry.eventModified =
true;
312 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
314 case FILE_ACTION_RENAMED_OLD_NAME:
316 newEntry.eventMovedFrom =
true;
317 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
319 case FILE_ACTION_RENAMED_NEW_NAME:
321 newEntry.eventMovedTo =
true;
322 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
327 if (fni->NextEntryOffset>0)
328 idx+=fni->NextEntryOffset;
virtual ~CFileSystemWatcher()
Destructor.
CFileSystemWatcher(const std::string &path)
Creates the subscription to a specified path.
std::string m_watchedDirectory
Ended in "/".
std::deque< TFileSystemChange > TFileSystemChangeList
void getChanges(TFileSystemChangeList &out_list)
Call this method sometimes to get the list of changes in the watched directory.
GLsizei GLsizei GLuint * obj
GLsizei const GLchar ** string
bool BASE_IMPEXP directoryExists(const std::string &fileName)
Test if a given directory exists (it fails if the given path refers to an existing file).
void BASE_IMPEXP memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) MRPT_NO_THROWS
An OS and compiler independent version of "memcpy".
TThreadHandle createThreadFromObjectMethod(CLASS *obj, void(CLASS::*func)(PARAM), PARAM param)
Creates a new thread running a non-static method (so it will have access to "this") from another meth...
void BASE_IMPEXP terminateThread(TThreadHandle &threadHandle) MRPT_NO_THROWS
Terminate a thread, giving it no choice to delete objects, etc (use only as a last resource)
#define THROW_EXCEPTION(msg)
#define ASSERTMSG_(f, __ERROR_MSG)
This namespace provides a OS-independent interface to many useful functions: filenames manipulation,...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
Each of the changes detected by utils::CFileSystemWatcher.
bool isDir
Whether the event happened to a file or a directory.
std::string path
Complete path of the file/directory that has changed.