void DirectoryMonitor::processNotification(const string& aPath, const ByteVector& aBuf) { char* pBase = (char*)&aBuf[0]; string oldPath; for (;;) { FILE_NOTIFY_INFORMATION& fni = (FILE_NOTIFY_INFORMATION&)*pBase; string notifyPath(Text::fromT(tstring(fni.FileName, fni.FileNameLength / sizeof(wchar_t) ))); // If it could be a short filename, expand it. auto fileName = Util::getFileName(notifyPath); // The maximum length of an 8.3 filename is twelve, including the dot. /*if (fileName.length() <= 12 && fileName.front() == _T('~')) { // Convert to the long filename form. Unfortunately, this // does not work for deletions, so it's an imperfect fix. wchar_t wbuf[UNC_MAX_PATH]; if (::GetLongPathName(Text::toT(notifyPath).c_str(), wbuf, _countof (wbuf)) > 0) notifyPath = Text::fromT(wbuf); }*/ notifyPath = aPath + notifyPath; switch(fni.Action) { case FILE_ACTION_ADDED: // The file was added to the directory. fire(DirectoryMonitorListener::FileCreated(), notifyPath); break; case FILE_ACTION_REMOVED: // The file was removed from the directory. fire(DirectoryMonitorListener::FileDeleted(), notifyPath); break; case FILE_ACTION_RENAMED_OLD_NAME: // The file was renamed and this is the old name. oldPath = notifyPath; break; case FILE_ACTION_RENAMED_NEW_NAME: // The file was renamed and this is the new name. fire(DirectoryMonitorListener::FileRenamed(), oldPath, notifyPath); break; case FILE_ACTION_MODIFIED: fire(DirectoryMonitorListener::FileModified(), notifyPath); break; } if (!fni.NextEntryOffset) break; pBase += fni.NextEntryOffset; }; }
void DirectoryMonitor::processNotification(const string& aPath, const ByteVector& aBuf) { char* pBase = (char*)&aBuf[0]; string oldPath; for (;;) { FILE_NOTIFY_INFORMATION& fni = (FILE_NOTIFY_INFORMATION&)*pBase; string notifyPath(Text::fromT(tstring(fni.FileName, fni.FileNameLength / sizeof(wchar_t) ))); auto fileName = Util::getFileName(notifyPath); notifyPath = aPath + notifyPath; switch(fni.Action) { case FILE_ACTION_ADDED: // The file was added to the directory. fire(DirectoryMonitorListener::FileCreated(), notifyPath); break; case FILE_ACTION_REMOVED: // The file was removed from the directory. fire(DirectoryMonitorListener::FileDeleted(), notifyPath); break; case FILE_ACTION_RENAMED_OLD_NAME: // The file was renamed and this is the old name. oldPath = notifyPath; break; case FILE_ACTION_RENAMED_NEW_NAME: // The file was renamed and this is the new name. fire(DirectoryMonitorListener::FileRenamed(), oldPath, notifyPath); break; case FILE_ACTION_MODIFIED: fire(DirectoryMonitorListener::FileModified(), notifyPath); break; } if (!fni.NextEntryOffset) break; pBase += fni.NextEntryOffset; }; }
bool PPSNotifyGroupManager::joinNotifyGroup(const std::string& path, std::string& groupId) { std::string notifyFile; std::string notifyPath(path); std::size_t nPos = notifyPath.rfind('/'); // Search through the directories in the string until we find a valid .notify object while (nPos != std::string::npos) { // Chop off everything after the last '/' to get the path without the PPS object name notifyPath = notifyPath.substr(0, nPos); // Do we already have a notify group for this path? const_groupIter it = m_notifyGroups.find(notifyPath); // We found a match! if (it != m_notifyGroups.end() && (*it).second != NULL) { groupId = (*it).second->getNotifyGroupId(); return true; } // Add ".notify?wait" to the notify path, to make it a real file notifyFile = notifyPath + "/.notify?wait"; // Try to open this .notify object int fd = ::open(notifyFile.c_str(), O_RDONLY); // This is the .notify object to use if (fd >= 0) { char data[20]; int len = ::read(fd, data, sizeof(data) - 1); // Terminate string to remove the newline char data[len > 0 ? len - 1 : 0] = '\0'; PPSNotifier* pNotifier = new PPSNotifier(); pNotifier->setNotifyGroupId(std::string(data)); pNotifier->setNotifyOjbPath(notifyPath); pNotifier->setObjFd(::dup(fd)); ::close(fd); // Add this badboy to our cache of notify groups m_notifyGroups.insert(groupValue(notifyPath, pNotifier)); // Start the notify reading thread pNotifier->startNotifyLoop(); groupId = pNotifier->getNotifyGroupId(); return true; } // Keep looking else { nPos = notifyPath.rfind('/'); } } // We didn't find a notify group groupId = ""; return false; }