diff options
author | Olivier Goffart <olivier@woboq.com> | 2014-11-17 11:43:29 +0300 |
---|---|---|
committer | Olivier Goffart <olivier@woboq.com> | 2014-11-17 11:43:29 +0300 |
commit | e529bbed907409fc454427b48f6f033763b42114 (patch) | |
tree | ec53b033df0e5e557e34398fd7cb5f2cd3a78d0d /src/mirall | |
parent | 39e97779ec1136fc93379f049248b6894ee27a87 (diff) | |
parent | 7c034b427ed6b144a0d0e9a10d04ce1e2037d3f0 (diff) |
Merge pull request #2454 from owncloud/fswatcher_readdirectorychanges_port
switch to ReadDirectoryChangesW
Diffstat (limited to 'src/mirall')
-rw-r--r-- | src/mirall/folderwatcher_win.cpp | 83 |
1 files changed, 57 insertions, 26 deletions
diff --git a/src/mirall/folderwatcher_win.cpp b/src/mirall/folderwatcher_win.cpp index c6c8242fa..76f687709 100644 --- a/src/mirall/folderwatcher_win.cpp +++ b/src/mirall/folderwatcher_win.cpp @@ -25,42 +25,73 @@ namespace Mirall { void WatcherThread::run() { - _handle = FindFirstChangeNotification((wchar_t*)_path.utf16(), - true, // recursive watch - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_LAST_WRITE); + _handle = CreateFileW( + (wchar_t*)_path.utf16(), + FILE_LIST_DIRECTORY, + FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); if (_handle == INVALID_HANDLE_VALUE) { - qDebug() << Q_FUNC_INFO << "FindFirstChangeNotification function failed, stopping watcher!"; - FindCloseChangeNotification(_handle); - _handle = 0; - return; - } - - if (_handle == NULL) - { - qDebug() << Q_FUNC_INFO << "FindFirstChangeNotification returned null, stopping watcher!"; + qDebug() << Q_FUNC_INFO << "Failed to set up a watch for" << _path << ", stopping watcher!"; FindCloseChangeNotification(_handle); _handle = 0; return; } + size_t bufsize = 4096; + size_t maxlen = 4096; while(true) { - switch(WaitForSingleObject(_handle, /*wait*/ INFINITE)) { - case WAIT_OBJECT_0: - if (FindNextChangeNotification(_handle) == false) { - qDebug() << Q_FUNC_INFO << "FindFirstChangeNotification returned FALSE, stopping watcher!"; - FindCloseChangeNotification(_handle); - _handle = 0; - return; + char fileNotify[bufsize]; + FILE_NOTIFY_INFORMATION *pFileNotify = + (FILE_NOTIFY_INFORMATION*)fileNotify; + DWORD dwBytesReturned = 0; + SecureZeroMemory(pFileNotify, bufsize); + if(ReadDirectoryChangesW( _handle, (LPVOID)pFileNotify, + bufsize, true, + FILE_NOTIFY_CHANGE_FILE_NAME | + FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_LAST_WRITE, + &dwBytesReturned, NULL, NULL)) + { + FILE_NOTIFY_INFORMATION *curEntry = pFileNotify; + while(true) { + size_t len = pFileNotify->FileNameLength / 2; + QString file = _path + "\\" + QString::fromWCharArray(pFileNotify->FileName, len); + + QString longfile; + QScopedArrayPointer<TCHAR> buffer(new TCHAR[maxlen]); + if (GetLongPathNameW(reinterpret_cast<LPCWSTR>(file.utf16()), buffer.data(), maxlen) == 0) { + qDebug() << Q_FUNC_INFO << "Error converting file name to full length, resorting to original name."; + longfile = file; + } else { + longfile = QString::fromUtf16(reinterpret_cast<const ushort *>(buffer.data()), maxlen-1); + } + + qDebug() << Q_FUNC_INFO << "Found change in" << file; + emit changed(longfile); + if (curEntry->NextEntryOffset == 0) { + break; + } + curEntry = (FILE_NOTIFY_INFORMATION*) + (char*)curEntry + curEntry->NextEntryOffset; + } + } else { + switch(GetLastError()) { + case ERROR_NOTIFY_ENUM_DIR: + qDebug() << Q_FUNC_INFO << "Too many events for buffer, resizing"; + bufsize *= 2; + break; + default: + qDebug() << Q_FUNC_INFO << "General error while watching. Exiting."; + CloseHandle(_handle); + _handle = NULL; + break; } - // qDebug() << Q_FUNC_INFO << "Change detected in" << _path << "from" << QThread::currentThread (); - emit changed(_path); - break; - default: - qDebug() << Q_FUNC_INFO << "Error while watching"; } } } |