24 #ifdef HAVE_SYS_INOTIFY_H 
   25 #include <sys/inotify.h> 
   29     fd = inotify_init1(IN_CLOEXEC);
 
   30     if (fd == -1) fd = inotify_init();
 
   31     if (fd == -1) 
LogF(
"inotify_init %s", strerror(errno));
 
   42     while (close(fd) == -1 && errno == EINTR) { }
 
   57     int wd = inotify_add_watch(fd, file, IN_CREATE | IN_MODIFY | IN_MOVED_TO | IN_MOVE_SELF | IN_ONLYDIR);
 
   59         LogF(
"inotify_add_watch %s", strerror(errno));
 
   60     watch_descriptors[wd] = file;
 
   65     if ((pfd->revents & pfd->events) != POLLIN || pfd->fd != fd)
 
   66       LogF(
"C4FileMonitor::Execute unexpectedly called %d %d %hd %hd", fd, pfd->fd, pfd->events, pfd->revents);
 
   68     inotify_event* 
event = 
new (buf) inotify_event;
 
   69     if (read(fd, buf, 
sizeof(buf)) > 0)
 
   71         const char * file = watch_descriptors[
event->wd];
 
   72         uint32_t mask = 
event->mask;
 
   78         if (mask & IN_MOVED_TO)
 
   80         if (mask & IN_MOVE_SELF)
 
   86         Log(
"inotify buffer too small");
 
   94     pCallback((
const char *)pEventData, 
nullptr);
 
   99     pollfd pfd = { fd, POLLIN, 0 };
 
  103 #elif defined(_WIN32) 
  107         : fStarted(false), pCallback(pCallback), pWatches(nullptr)
 
  109     hEvent = CreateEvent(
nullptr, 
true, 
false, 
nullptr);
 
  122         CloseHandle(pWatches->hDir);
 
  123         TreeWatch *pDelete = pWatches;
 
  124         pWatches = pWatches->Next;
 
  138 const DWORD C4FileMonitorNotifies = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE;
 
  143     HANDLE hDir = CreateFileW(
GetWideChar(szDir), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 
nullptr);
 
  144     if (hDir == INVALID_HANDLE_VALUE) 
return;
 
  146     TreeWatch *pWatch = 
new TreeWatch();
 
  148     pWatch->DirName = szDir;
 
  150     ZeroMem(&pWatch->ov, 
sizeof(pWatch->ov));
 
  151     pWatch->ov.hEvent = hEvent;
 
  153     pWatch->Next = pWatches;
 
  156     if (!ReadDirectoryChangesW(hDir, pWatch->Buffer, 
sizeof(pWatch->Buffer), 
false, C4FileMonitorNotifies, 
nullptr, &pWatch->ov, 
nullptr))
 
  157         if (GetLastError() != ERROR_IO_PENDING)
 
  167     if (WaitForSingleObject(hEvent, iTimeout) != WAIT_OBJECT_0)
 
  170     for (TreeWatch *pWatch = pWatches; pWatch; pWatch = pWatch->Next)
 
  174         if (GetOverlappedResult(pWatch->hDir, &pWatch->ov, &dwBytes, 
false))
 
  177             const char *pPos = pWatch->Buffer;
 
  180                 const _FILE_NOTIFY_INFORMATION *pNotify = 
reinterpret_cast<const _FILE_NOTIFY_INFORMATION *
>(pPos);
 
  182                 HandleNotify(pWatch->DirName.getData(), pNotify);
 
  184                 if (!pNotify->NextEntryOffset) 
break;
 
  185                 pPos += pNotify->NextEntryOffset;
 
  186                 if (pPos >= pWatch->Buffer + std::min<size_t>(
sizeof(pWatch->Buffer), dwBytes))
 
  191             ReadDirectoryChangesW(pWatch->hDir, pWatch->Buffer, 
sizeof(pWatch->Buffer), 
false, C4FileMonitorNotifies, 
nullptr, &pWatch->ov, 
nullptr);
 
  193             while (GetOverlappedResult(pWatch->hDir, &pWatch->ov, &dwBytes, 
false))
 
  195                 ReadDirectoryChangesW(pWatch->hDir, pWatch->Buffer, 
sizeof(pWatch->Buffer), 
false, C4FileMonitorNotifies, 
nullptr, &pWatch->ov, 
nullptr);
 
  207     pCallback((
const char *)pEventData, 
nullptr);
 
  211 HANDLE C4FileMonitor::GetEvent()
 
  216 void C4FileMonitor::HandleNotify(
const char *szDir, 
const _FILE_NOTIFY_INFORMATION *pNotify)
 
  219     UINT iCodePage = CP_UTF8;
 
  220     int iFileNameBytes = WideCharToMultiByte(iCodePage, 0,
 
  221                          pNotify->FileName, pNotify->FileNameLength / 2, 
nullptr, 0, 
nullptr, 
nullptr);
 
  225     Path.Grow(iFileNameBytes);
 
  226     char *pFilename = Path.getMPtr(
SLen(Path.getData()));
 
  228     int iWritten = WideCharToMultiByte(iCodePage, 0,
 
  229                                        pNotify->FileName, pNotify->FileNameLength / 2,
 
  230                                        pFilename, iFileNameBytes,
 
  232     if (iWritten != iFileNameBytes)
 
  233         Path.Shrink(iFileNameBytes+1);
 
  238 #elif not defined(__APPLE__) 
  243 #ifdef HAVE_SYS_INOTIFY_H 
  244     C4FileMonitor::pCallback = pCallback;
 
  255 #ifdef STDSCHEDULER_USE_EVENTS 
  256 HANDLE C4FileMonitor::GetEvent() { 
return 0; }
 
C4Application Application
 
bool Log(const char *szMessage)
 
bool LogF(const char *strMessage,...)
 
StdStrBuf::wchar_t_holder GetWideChar(const char *utf8, bool double_null_terminate=false)
 
std::enable_if< std::is_pod< T >::value >::type ZeroMem(T *lpMem, size_t dwSize)
 
size_t SLen(const char *sptr)
 
C4InteractiveThread InteractiveThread
 
void GetFDs(std::vector< struct pollfd > &FDs) override
 
void OnThreadEvent(C4InteractiveEventType eEvent, void *pEventData) override
 
bool Execute(int iTimeout=-1, pollfd *=nullptr) override
 
~C4FileMonitor() override
 
void AddDirectory(const char *szDir)
 
C4FileMonitor(ChangeNotify pCallback)
 
void RemoveProc(StdSchedulerProc *pProc)
 
void ClearCallback(C4InteractiveEventType eEvent, Callback *pnNetworkCallback)
 
bool AddProc(StdSchedulerProc *pProc)
 
bool PushEvent(C4InteractiveEventType eEventType, void *pData=nullptr)
 
void SetCallback(C4InteractiveEventType eEvent, Callback *pnNetworkCallback)
 
static void DeletePointer(void *data)