From 6ca14dce65634e202b36499c76c268c87f78ceb6 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 20 Jul 2009 19:47:32 +0200 Subject: Workaround for transacted, locked and inaccesible files wich can not be stat'ed in a natural way. FindFirstFile solves this problem. Task-number: 167099 Task-number: 189202 Merge-request: 880 Reviewed-by: Joerg Bornemann --- src/corelib/io/qfsfileengine_win.cpp | 88 ++++++++++++++++++++++++++++++++++ tests/auto/qfileinfo/tst_qfileinfo.cpp | 18 ++++++- 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index d4e2e93..53f0144 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -527,6 +527,29 @@ qint64 QFSFileEnginePrivate::nativeSize() const WIN32_FILE_ATTRIBUTE_DATA attribData; bool ok = ::GetFileAttributesEx((const wchar_t*)nativeFilePath.constData(), GetFileExInfoStandard, &attribData); + if (!ok) { + int errorCode = GetLastError(); + if (errorCode != ERROR_INVALID_NAME + && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + QByteArray path = nativeFilePath; + // path for the FindFirstFile should not end with a trailing slash + while (path.endsWith('\\')) + path.chop(1); + + // FindFirstFile can not handle drives + if (!path.endsWith(':')) { + WIN32_FIND_DATA findData; + HANDLE hFind = ::FindFirstFile((const wchar_t*)path.constData(), + &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + ok = true; + attribData.nFileSizeHigh = findData.nFileSizeHigh; + attribData.nFileSizeLow = findData.nFileSizeLow; + } + } + } + } if (ok) { qint64 size = attribData.nFileSizeHigh; size <<= 32; @@ -878,6 +901,26 @@ static inline bool isDirPath(const QString &dirPath, bool *existed) path += QLatin1Char('\\'); DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); + if (fileAttrib == INVALID_FILE_ATTRIBUTES) { + int errorCode = GetLastError(); + if (errorCode != ERROR_INVALID_NAME + && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + // path for the FindFirstFile should not end with a trailing slash + while (path.endsWith(QLatin1Char('\\'))) + path.chop(1); + + // FindFirstFile can not handle drives + if (!path.endsWith(QLatin1Char(':'))) { + WIN32_FIND_DATA findData; + HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), + &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + fileAttrib = findData.dwFileAttributes; + } + } + } + } if (existed) *existed = fileAttrib != INVALID_FILE_ATTRIBUTES; @@ -1149,6 +1192,27 @@ bool QFSFileEnginePrivate::doStat() const #endif } else { fileAttrib = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16()); + if (fileAttrib == INVALID_FILE_ATTRIBUTES) { + int errorCode = GetLastError(); + if (errorCode != ERROR_INVALID_NAME + && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + QString path = QDir::toNativeSeparators(fname); + // path for the FindFirstFile should not end with a trailing slash + while (path.endsWith(QLatin1Char('\\'))) + path.chop(1); + + // FindFirstFile can not handle drives + if (!path.endsWith(QLatin1Char(':'))) { + WIN32_FIND_DATA findData; + HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), + &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + fileAttrib = findData.dwFileAttributes; + } + } + } + } could_stat = fileAttrib != INVALID_FILE_ATTRIBUTES; if (!could_stat) { #if !defined(Q_OS_WINCE) @@ -1744,6 +1808,30 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const } else { WIN32_FILE_ATTRIBUTE_DATA attribData; bool ok = ::GetFileAttributesEx((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData); + if (!ok) { + int errorCode = GetLastError(); + if (errorCode != ERROR_INVALID_NAME + && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + QString path = QDir::toNativeSeparators(d->filePath); + // path for the FindFirstFile should not end with a trailing slash + while (path.endsWith(QLatin1Char('\\'))) + path.chop(1); + + // FindFirstFile can not handle drives + if (!path.endsWith(QLatin1Char(':'))) { + WIN32_FIND_DATA findData; + HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), + &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + ok = true; + attribData.ftCreationTime = findData.ftCreationTime; + attribData.ftLastWriteTime = findData.ftLastWriteTime; + attribData.ftLastAccessTime = findData.ftLastAccessTime; + } + } + } + } if (ok) { if(time == CreationTime) ret = fileTimeToQDateTime(&attribData.ftCreationTime); diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp index 48dc357..e5831fd 100644 --- a/tests/auto/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp @@ -127,6 +127,8 @@ private slots: void size_data(); void size(); + void systemFiles(); + void compare_data(); void compare(); @@ -354,8 +356,9 @@ void tst_QFileInfo::exists_data() QTest::newRow("data6") << "resources/*" << false; QTest::newRow("data7") << "resources/*.foo" << false; QTest::newRow("data8") << "resources/*.ext1" << false; - QTest::newRow("data9") << "." << true; - QTest::newRow("data10") << ". " << false; + QTest::newRow("data9") << "resources/file?.ext1" << false; + QTest::newRow("data10") << "." << true; + QTest::newRow("data11") << ". " << false; QTest::newRow("simple dir") << "resources" << true; QTest::newRow("simple dir with slash") << "resources/" << true; @@ -741,6 +744,17 @@ void tst_QFileInfo::size() QTEST(int(fi.size()), "size"); } +void tst_QFileInfo::systemFiles() +{ +#ifndef Q_OS_WIN + QSKIP("This is a Windows only test", SkipAll); +#endif + QFileInfo fi("c:\\pagefile.sys"); + QVERIFY(fi.exists()); // task 167099 + QVERIFY(fi.size() > 0); // task 189202 + QVERIFY(fi.lastModified().isValid()); +} + void tst_QFileInfo::compare_data() { QTest::addColumn("file1"); -- cgit v0.12