1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QT_TESTS_SHARED_FILESYSTEM_H_INCLUDED
#define QT_TESTS_SHARED_FILESYSTEM_H_INCLUDED
#include <QString>
#include <QStringList>
#include <QTemporaryDir>
#include <QScopedPointer>
#include <QDir>
#include <QFile>
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
#include <windows.h>
#include <winioctl.h>
#ifndef IO_REPARSE_TAG_MOUNT_POINT
#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
#endif
#define REPARSE_MOUNTPOINT_HEADER_SIZE 8
#ifndef FSCTL_SET_REPARSE_POINT
#define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#endif
#endif
// QTemporaryDir-based helper class for creating file-system hierarchies and cleaning up.
class FileSystem
{
Q_DISABLE_COPY(FileSystem)
public:
FileSystem() : m_temporaryDir(FileSystem::tempFilePattern()) {}
QString path() const { return m_temporaryDir.path(); }
QString absoluteFilePath(const QString &fileName) const { return path() + QLatin1Char('/') + fileName; }
bool createDirectory(const QString &relativeDirName)
{
if (m_temporaryDir.isValid()) {
QDir dir(m_temporaryDir.path());
return dir.mkpath(relativeDirName);
}
return false;
}
bool createFile(const QString &relativeFileName)
{
QScopedPointer<QFile> file(openFileForWrite(relativeFileName));
return !file.isNull();
}
qint64 createFileWithContent(const QString &relativeFileName)
{
QScopedPointer<QFile> file(openFileForWrite(relativeFileName));
return file.isNull() ? qint64(-1) : file->write(relativeFileName.toUtf8());
}
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
static void createNtfsJunction(QString target, QString linkName)
{
typedef struct {
DWORD ReparseTag;
DWORD ReparseDataLength;
WORD Reserved;
WORD ReparseTargetLength;
WORD ReparseTargetMaximumLength;
WORD Reserved1;
WCHAR ReparseTarget[1];
} REPARSE_MOUNTPOINT_DATA_BUFFER, *PREPARSE_MOUNTPOINT_DATA_BUFFER;
char reparseBuffer[MAX_PATH*3];
HANDLE hFile;
DWORD returnedLength;
wchar_t fileSystem[MAX_PATH] = L"";
PREPARSE_MOUNTPOINT_DATA_BUFFER reparseInfo = (PREPARSE_MOUNTPOINT_DATA_BUFFER) reparseBuffer;
QFileInfo junctionInfo(linkName);
linkName = QDir::toNativeSeparators(junctionInfo.absoluteFilePath());
GetVolumeInformationW( (wchar_t*)linkName.left(3).utf16(), NULL, 0, NULL, NULL, NULL,
fileSystem, sizeof(fileSystem)/sizeof(WCHAR));
if(QString().fromWCharArray(fileSystem) != "NTFS")
QSKIP("This seems not to be an NTFS volume. Junctions are not allowed.");
if (!target.startsWith("\\??\\") && !target.startsWith("\\\\?\\")) {
QFileInfo targetInfo(target);
target = QDir::toNativeSeparators(targetInfo.absoluteFilePath());
target.prepend("\\??\\");
if(target.endsWith('\\') && target.at(target.length()-2) != ':')
target.chop(1);
}
QDir().mkdir(linkName);
hFile = CreateFileW( (wchar_t*)linkName.utf16(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL );
QVERIFY(hFile != INVALID_HANDLE_VALUE );
memset( reparseInfo, 0, sizeof( *reparseInfo ));
reparseInfo->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
reparseInfo->ReparseTargetLength = WORD(target.size()) * WORD(sizeof(wchar_t));
reparseInfo->ReparseTargetMaximumLength = reparseInfo->ReparseTargetLength + sizeof(wchar_t);
target.toWCharArray(reparseInfo->ReparseTarget);
reparseInfo->ReparseDataLength = reparseInfo->ReparseTargetLength + 12;
bool ioc = DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, reparseInfo,
reparseInfo->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE,
NULL, 0, &returnedLength, NULL);
CloseHandle( hFile );
QVERIFY(ioc);
}
#endif
private:
static QString tempFilePattern()
{
QString result = QDir::tempPath();
if (!result.endsWith(QLatin1Char('/')))
result.append(QLatin1Char('/'));
result += QStringLiteral("qt-test-filesystem-");
result += QCoreApplication::applicationName();
result += QStringLiteral("-XXXXXX");
return result;
}
QFile *openFileForWrite(const QString &fileName) const
{
if (m_temporaryDir.isValid()) {
const QString absName = absoluteFilePath(fileName);
QScopedPointer<QFile> file(new QFile(absName));
if (file->open(QIODevice::WriteOnly))
return file.take();
qWarning("Cannot open '%s' for writing: %s", qPrintable(absName), qPrintable(file->errorString()));
}
return 0;
}
QTemporaryDir m_temporaryDir;
};
#endif // include guard
|