2012-12-04 21:15:37 +04:00
|
|
|
/*
|
|
|
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
2014-01-13 19:16:19 +04:00
|
|
|
* the Free Software Foundation; version 2 of the License.
|
2012-12-04 21:15:37 +04:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*/
|
|
|
|
|
2012-12-05 21:23:35 +04:00
|
|
|
#include <QThread>
|
|
|
|
#include <QDebug>
|
|
|
|
|
2012-12-04 21:15:37 +04:00
|
|
|
#include "mirall/folderwatcher.h"
|
2012-12-05 21:23:35 +04:00
|
|
|
#include "mirall/folderwatcher_win.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <tchar.h>
|
2012-12-04 21:15:37 +04:00
|
|
|
|
|
|
|
namespace Mirall {
|
|
|
|
|
2012-12-05 21:23:35 +04:00
|
|
|
void WatcherThread::run()
|
|
|
|
{
|
2014-11-06 02:36:04 +03:00
|
|
|
_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
|
|
|
|
);
|
2012-12-04 21:15:37 +04:00
|
|
|
|
2014-11-06 02:36:04 +03:00
|
|
|
size_t bufsize = 4096;
|
|
|
|
size_t maxlen = 4096;
|
|
|
|
while(true) {
|
|
|
|
char fileNotify[bufsize];
|
|
|
|
// TODO: handle CreateFileW failure
|
|
|
|
FILE_NOTIFY_INFORMATION *pFileNotify =
|
|
|
|
(FILE_NOTIFY_INFORMATION*)fileNotify;
|
|
|
|
DWORD dwBytesReturned = 0;
|
|
|
|
SecureZeroMemory(pFileNotify, bufsize);
|
|
|
|
if(ReadDirectoryChangesW( _handle, (LPVOID)pFileNotify,
|
|
|
|
bufsize, true,
|
|
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
|
|
|
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);
|
2012-12-04 21:15:37 +04:00
|
|
|
|
2014-11-06 14:54:33 +03:00
|
|
|
QString longfile;
|
2014-11-06 02:36:04 +03:00
|
|
|
QScopedArrayPointer<TCHAR> buffer(new TCHAR[maxlen]);
|
|
|
|
if (GetLongPathNameW(reinterpret_cast<LPCWSTR>(file.utf16()), buffer.data(), maxlen) == 0) {
|
2014-11-06 14:54:33 +03:00
|
|
|
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);
|
2014-11-06 02:36:04 +03:00
|
|
|
}
|
2012-12-05 21:23:35 +04:00
|
|
|
|
2014-11-06 02:36:04 +03:00
|
|
|
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;
|
2012-12-06 19:26:27 +04:00
|
|
|
}
|
2012-12-05 21:23:35 +04:00
|
|
|
}
|
|
|
|
}
|
2012-12-04 21:15:37 +04:00
|
|
|
}
|
2012-12-06 19:26:27 +04:00
|
|
|
|
|
|
|
WatcherThread::~WatcherThread()
|
|
|
|
{
|
|
|
|
if (_handle)
|
|
|
|
FindCloseChangeNotification(_handle);
|
|
|
|
}
|
2012-12-05 21:23:35 +04:00
|
|
|
|
2014-01-13 18:23:52 +04:00
|
|
|
FolderWatcherPrivate::FolderWatcherPrivate(FolderWatcher *p, const QString& path)
|
2012-12-05 21:23:35 +04:00
|
|
|
: _parent(p)
|
|
|
|
{
|
2014-01-13 18:23:52 +04:00
|
|
|
_thread = new WatcherThread(path);
|
2012-12-06 19:26:27 +04:00
|
|
|
connect(_thread, SIGNAL(changed(const QString&)),
|
|
|
|
_parent,SLOT(changeDetected(const QString&)));
|
|
|
|
_thread->start();
|
2012-12-05 21:23:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
FolderWatcherPrivate::~FolderWatcherPrivate()
|
|
|
|
{
|
2012-12-06 19:26:27 +04:00
|
|
|
_thread->terminate();
|
|
|
|
_thread->wait();
|
2012-12-05 21:23:35 +04:00
|
|
|
delete _thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Mirall
|