12 #include <mrpt/config.h> 14 #ifdef MRPT_OS_WINDOWS 16 #define _WIN32_WINNT 0x0400 21 #include <sys/inotify.h> 42 : m_watchedDirectory(path)
51 #ifdef MRPT_OS_WINDOWS 53 HANDLE hDir = CreateFileA(
54 path.c_str(), FILE_LIST_DIRECTORY,
55 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
57 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
58 if (hDir == INVALID_HANDLE_VALUE)
64 m_hNotif =
static_cast<void*
>(hDir);
66 m_watchThread = std::thread(&CFileSystemWatcher::thread_win32_watch,
this);
73 m_fd = inotify_init();
77 m_wd = inotify_add_watch(
78 m_fd, path.c_str(), IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO |
79 IN_MOVED_FROM | IN_CREATE | IN_ACCESS);
92 #ifdef MRPT_OS_WINDOWS 97 CloseHandle(HANDLE(m_hNotif));
107 if (m_wd >= 0) inotify_rm_watch(m_fd, m_wd);
120 #ifdef MRPT_OS_WINDOWS 124 "CFileSystemWatcher was not initialized correctly.")
128 while (!m_queue_events_win32.empty())
133 out_list.push_back(*
obj);
140 if (m_fd < 0)
return;
160 ret = select(m_fd + 1, &rfds,
nullptr,
nullptr, &time);
163 perror(
"[CFileSystemWatcher::getChanges] select");
171 else if (FD_ISSET(m_fd, &rfds))
176 #define EVENT_SIZE (sizeof(struct inotify_event)) 179 #define BUF_LEN (1024 * (EVENT_SIZE + 16)) 184 len = read(m_fd, buf, BUF_LEN);
192 perror(
"[CFileSystemWatcher::getChanges] read");
201 struct inotify_event event_val;
205 struct inotify_event*
event = &event_val;
207 i += EVENT_SIZE +
event->len;
213 if (event->len) eventName =
event->name;
217 if (0 == (event->mask & IN_UNMOUNT) &&
218 0 == (event->mask & IN_Q_OVERFLOW) &&
219 0 == (event->mask & IN_IGNORED))
224 newEntry.
isDir =
event->mask & IN_ISDIR;
233 out_list.push_back(newEntry);
241 #ifdef MRPT_OS_WINDOWS 243 void CFileSystemWatcher::thread_win32_watch()
248 while (ReadDirectoryChangesW(
249 HANDLE(m_hNotif), buf,
sizeof(buf),
251 FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
252 FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE |
253 FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS |
254 FILE_NOTIFY_CHANGE_CREATION,
255 &dwRead,
nullptr,
nullptr))
264 FILE_NOTIFY_INFORMATION* fni =
265 reinterpret_cast<FILE_NOTIFY_INFORMATION*
>(&buf[idx]);
269 fni->FileNameLength < 10000,
270 "Name length >10K... this is probably an error")
272 int reqLen = WideCharToMultiByte(
273 CP_UTF8, 0, fni->FileName, fni->FileNameLength >> 1,
nullptr, 0,
275 std::vector<
char> tmpBuf(reqLen);
276 int actLen = WideCharToMultiByte(
277 CP_UTF8, 0, fni->FileName, fni->FileNameLength >> 1, &tmpBuf[0],
278 tmpBuf.
size(),
nullptr,
nullptr);
280 actLen > 0, "Error converting filename from WCHAR* to UTF8")
282 const
std::
string filName(&tmpBuf[0], actLen);
284 TFileSystemChange newEntry;
291 case FILE_ACTION_ADDED:
293 newEntry.eventCreated =
true;
294 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
297 case FILE_ACTION_REMOVED:
299 newEntry.eventDeleted =
true;
300 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
303 case FILE_ACTION_MODIFIED:
305 newEntry.eventModified =
true;
306 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
309 case FILE_ACTION_RENAMED_OLD_NAME:
311 newEntry.eventMovedFrom =
true;
312 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
315 case FILE_ACTION_RENAMED_NEW_NAME:
317 newEntry.eventMovedTo =
true;
318 m_queue_events_win32.push(
new TFileSystemChange(newEntry));
324 if (fni->NextEntryOffset > 0)
325 idx += fni->NextEntryOffset;
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
#define THROW_EXCEPTION(msg)
std::string path
Complete path of the file/directory that has changed.
void getChanges(TFileSystemChangeList &out_list)
Call this method sometimes to get the list of changes in the watched directory.
GLsizei GLsizei GLuint * obj
std::string m_watchedDirectory
Ended in "/".
std::deque< TFileSystemChange > TFileSystemChangeList
GLsizei const GLchar ** string
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool isDir
Whether the event happened to a file or a directory.
virtual ~CFileSystemWatcher()
Destructor.
Each of the changes detected by utils::CFileSystemWatcher.
bool directoryExists(const std::string &fileName)
Test if a given directory exists (it fails if the given path refers to an existing file)...
#define ASSERTMSG_(f, __ERROR_MSG)
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
CFileSystemWatcher(const std::string &path)
Creates the subscription to a specified path.