Refactor createSymbolicLink() and createNtfsJunction()
Both functions now return a result object. Eliminates the need to pass the errorMessage out-parameter. Adapt auto-tests. Change-Id: I110b68fedc67b01f76796c44fa55383b2cc03460 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
ebacf42561
commit
01f003f0aa
@ -715,12 +715,11 @@ void tst_QFileInfo::canonicalFilePath()
|
|||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
|
||||||
const QString linkTarget = QStringLiteral("res");
|
const QString linkTarget = QStringLiteral("res");
|
||||||
const DWORD dwErr = FileSystem::createSymbolicLink(linkTarget, m_resourcesDir, &errorMessage);
|
const auto result = FileSystem::createSymbolicLink(linkTarget, m_resourcesDir);
|
||||||
if (dwErr == ERROR_PRIVILEGE_NOT_HELD)
|
if (result.dwErr == ERROR_PRIVILEGE_NOT_HELD)
|
||||||
QSKIP(msgInsufficientPrivileges(errorMessage));
|
QSKIP(msgInsufficientPrivileges(result.errorMessage));
|
||||||
QVERIFY2(dwErr == ERROR_SUCCESS, qPrintable(errorMessage));
|
QVERIFY2(result.dwErr == ERROR_SUCCESS, qPrintable(result.errorMessage));
|
||||||
QString currentPath = QDir::currentPath();
|
QString currentPath = QDir::currentPath();
|
||||||
QVERIFY(QDir::setCurrent(linkTarget));
|
QVERIFY(QDir::setCurrent(linkTarget));
|
||||||
const QString actualCanonicalPath = QFileInfo("file1").canonicalFilePath();
|
const QString actualCanonicalPath = QFileInfo("file1").canonicalFilePath();
|
||||||
@ -1359,12 +1358,11 @@ void tst_QFileInfo::isSymbolicLink_data()
|
|||||||
|
|
||||||
#ifndef Q_NO_SYMLINKS
|
#ifndef Q_NO_SYMLINKS
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
QString errorMessage;
|
const auto creationResult = FileSystem::createSymbolicLink("symlink", m_sourceFile);
|
||||||
const DWORD creationResult = FileSystem::createSymbolicLink("symlink", m_sourceFile, &errorMessage);
|
if (creationResult.dwErr == ERROR_PRIVILEGE_NOT_HELD) {
|
||||||
if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
|
QWARN(msgInsufficientPrivileges(creationResult.errorMessage));
|
||||||
QWARN(msgInsufficientPrivileges(errorMessage));
|
|
||||||
} else {
|
} else {
|
||||||
QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
|
QVERIFY2(creationResult.dwErr == ERROR_SUCCESS, qPrintable(creationResult.errorMessage));
|
||||||
QTest::newRow("NTFS-symlink")
|
QTest::newRow("NTFS-symlink")
|
||||||
<< "symlink" << true;
|
<< "symlink" << true;
|
||||||
}
|
}
|
||||||
@ -1423,21 +1421,20 @@ void tst_QFileInfo::link_data()
|
|||||||
|
|
||||||
#ifndef Q_NO_SYMLINKS
|
#ifndef Q_NO_SYMLINKS
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
QString errorMessage;
|
auto creationResult = FileSystem::createSymbolicLink("link", m_sourceFile);
|
||||||
DWORD creationResult = FileSystem::createSymbolicLink("link", m_sourceFile, &errorMessage);
|
if (creationResult.dwErr == ERROR_PRIVILEGE_NOT_HELD) {
|
||||||
if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
|
QWARN(msgInsufficientPrivileges(creationResult.errorMessage));
|
||||||
QWARN(msgInsufficientPrivileges(errorMessage));
|
|
||||||
} else {
|
} else {
|
||||||
QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
|
QVERIFY2(creationResult.dwErr == ERROR_SUCCESS, qPrintable(creationResult.errorMessage));
|
||||||
QTest::newRow("link")
|
QTest::newRow("link")
|
||||||
<< "link" << false << true << QFileInfo(m_sourceFile).absoluteFilePath();
|
<< "link" << false << true << QFileInfo(m_sourceFile).absoluteFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
creationResult = FileSystem::createSymbolicLink("brokenlink", "dummyfile", &errorMessage);
|
creationResult = FileSystem::createSymbolicLink("brokenlink", "dummyfile");
|
||||||
if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
|
if (creationResult.dwErr == ERROR_PRIVILEGE_NOT_HELD) {
|
||||||
QWARN(msgInsufficientPrivileges(errorMessage));
|
QWARN(msgInsufficientPrivileges(creationResult.errorMessage));
|
||||||
} else {
|
} else {
|
||||||
QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
|
QVERIFY2(creationResult.dwErr == ERROR_SUCCESS, qPrintable(creationResult.errorMessage));
|
||||||
QTest::newRow("broken link")
|
QTest::newRow("broken link")
|
||||||
<< "brokenlink" << false << true << QFileInfo("dummyfile").absoluteFilePath();
|
<< "brokenlink" << false << true << QFileInfo("dummyfile").absoluteFilePath();
|
||||||
}
|
}
|
||||||
@ -1701,7 +1698,6 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
|
|||||||
{
|
{
|
||||||
// Symlink to UNC share
|
// Symlink to UNC share
|
||||||
pwd.mkdir("unc");
|
pwd.mkdir("unc");
|
||||||
QString errorMessage;
|
|
||||||
QString uncTarget = QStringLiteral("//") + QtNetworkSettings::winServerName() + "/testshare";
|
QString uncTarget = QStringLiteral("//") + QtNetworkSettings::winServerName() + "/testshare";
|
||||||
QString uncSymlink = QDir::toNativeSeparators(pwd.absolutePath().append("\\unc\\link_to_unc"));
|
QString uncSymlink = QDir::toNativeSeparators(pwd.absolutePath().append("\\unc\\link_to_unc"));
|
||||||
QTest::newRow("UNC symlink")
|
QTest::newRow("UNC symlink")
|
||||||
@ -1753,24 +1749,23 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
|
|||||||
QFETCH(QString, linkTarget);
|
QFETCH(QString, linkTarget);
|
||||||
QFETCH(QString, canonicalFilePath);
|
QFETCH(QString, canonicalFilePath);
|
||||||
|
|
||||||
QString errorMessage;
|
FileSystem::Result creationResult;
|
||||||
DWORD creationResult = ERROR_SUCCESS;
|
|
||||||
switch (resource.type) {
|
switch (resource.type) {
|
||||||
case NtfsTestResource::None:
|
case NtfsTestResource::None:
|
||||||
break;
|
break;
|
||||||
case NtfsTestResource::SymLink:
|
case NtfsTestResource::SymLink:
|
||||||
creationResult = FileSystem::createSymbolicLink(resource.source, resource.target, &errorMessage);
|
creationResult = FileSystem::createSymbolicLink(resource.source, resource.target);
|
||||||
break;
|
break;
|
||||||
case NtfsTestResource::Junction:
|
case NtfsTestResource::Junction:
|
||||||
creationResult = FileSystem::createNtfsJunction(resource.target, resource.source, &errorMessage);
|
creationResult = FileSystem::createNtfsJunction(resource.target, resource.source);
|
||||||
if (creationResult == ERROR_NOT_SUPPORTED) // Special value indicating non-NTFS drive
|
if (creationResult.dwErr == ERROR_NOT_SUPPORTED) // Special value indicating non-NTFS drive
|
||||||
QSKIP(qPrintable(errorMessage));
|
QSKIP(qPrintable(creationResult.errorMessage));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creationResult == ERROR_PRIVILEGE_NOT_HELD)
|
if (creationResult.dwErr == ERROR_PRIVILEGE_NOT_HELD)
|
||||||
QSKIP(msgInsufficientPrivileges(errorMessage));
|
QSKIP(msgInsufficientPrivileges(creationResult.errorMessage));
|
||||||
QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
|
QVERIFY2(creationResult.dwErr == ERROR_SUCCESS, qPrintable(creationResult.errorMessage));
|
||||||
|
|
||||||
QFileInfo fi(path);
|
QFileInfo fi(path);
|
||||||
auto guard = qScopeGuard([&fi, this]() {
|
auto guard = qScopeGuard([&fi, this]() {
|
||||||
|
@ -94,9 +94,8 @@ void qfileinfo::symLinkTargetPerformanceMounpoint()
|
|||||||
QString rootVolume = QString::fromWCharArray(buffer);
|
QString rootVolume = QString::fromWCharArray(buffer);
|
||||||
QString mountpoint = "mountpoint";
|
QString mountpoint = "mountpoint";
|
||||||
rootVolume.replace("\\\\?\\","\\??\\");
|
rootVolume.replace("\\\\?\\","\\??\\");
|
||||||
QString errorMessage;
|
const auto result = FileSystem::createNtfsJunction(rootVolume, mountpoint);
|
||||||
QVERIFY2(FileSystem::createNtfsJunction(rootVolume, mountpoint, &errorMessage) == ERROR_SUCCESS,
|
QVERIFY2(result.dwErr == ERROR_SUCCESS, qPrintable(result.errorMessage));
|
||||||
qPrintable(errorMessage));
|
|
||||||
|
|
||||||
QFileInfo info(mountpoint);
|
QFileInfo info(mountpoint);
|
||||||
info.setCaching(false);
|
info.setCaching(false);
|
||||||
|
@ -83,10 +83,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
static DWORD createSymbolicLink(const QString &symLinkName, const QString &target,
|
struct Result {
|
||||||
QString *errorMessage)
|
DWORD dwErr = ERROR_SUCCESS;
|
||||||
|
QString link;
|
||||||
|
QString target;
|
||||||
|
QString errorMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Result createSymbolicLink(const QString &symLinkName, const QString &target)
|
||||||
{
|
{
|
||||||
DWORD result = ERROR_SUCCESS;
|
Result result;
|
||||||
const QString nativeSymLinkName = QDir::toNativeSeparators(symLinkName);
|
const QString nativeSymLinkName = QDir::toNativeSeparators(symLinkName);
|
||||||
const QString nativeTarget = QDir::toNativeSeparators(target);
|
const QString nativeTarget = QDir::toNativeSeparators(target);
|
||||||
DWORD flags = 0;
|
DWORD flags = 0;
|
||||||
@ -96,15 +102,18 @@ public:
|
|||||||
flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
|
flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
|
||||||
if (CreateSymbolicLink(reinterpret_cast<const wchar_t*>(nativeSymLinkName.utf16()),
|
if (CreateSymbolicLink(reinterpret_cast<const wchar_t*>(nativeSymLinkName.utf16()),
|
||||||
reinterpret_cast<const wchar_t*>(nativeTarget.utf16()), flags) == FALSE) {
|
reinterpret_cast<const wchar_t*>(nativeTarget.utf16()), flags) == FALSE) {
|
||||||
result = GetLastError();
|
result.dwErr = GetLastError();
|
||||||
QTextStream(errorMessage) << "CreateSymbolicLink(" << nativeSymLinkName << ", "
|
QTextStream(&result.errorMessage) << "CreateSymbolicLink(" << nativeSymLinkName << ", "
|
||||||
<< nativeTarget << ", 0x" << Qt::hex << flags << Qt::dec << ") failed with error " << result
|
<< nativeTarget << ", 0x" << Qt::hex << flags << Qt::dec << ") failed with error "
|
||||||
<< ": " << qt_error_string(int(result));
|
<< result.dwErr << ": " << qt_error_string(int(result.dwErr));
|
||||||
|
} else {
|
||||||
|
result.link = nativeSymLinkName;
|
||||||
|
result.target = nativeTarget;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD createNtfsJunction(QString target, QString linkName, QString *errorMessage)
|
static Result createNtfsJunction(QString target, QString linkName)
|
||||||
{
|
{
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DWORD ReparseTag;
|
DWORD ReparseTag;
|
||||||
@ -121,7 +130,7 @@ public:
|
|||||||
DWORD returnedLength;
|
DWORD returnedLength;
|
||||||
wchar_t fileSystem[MAX_PATH] = L"";
|
wchar_t fileSystem[MAX_PATH] = L"";
|
||||||
PREPARSE_MOUNTPOINT_DATA_BUFFER reparseInfo = (PREPARSE_MOUNTPOINT_DATA_BUFFER) reparseBuffer;
|
PREPARSE_MOUNTPOINT_DATA_BUFFER reparseInfo = (PREPARSE_MOUNTPOINT_DATA_BUFFER) reparseBuffer;
|
||||||
DWORD result = ERROR_SUCCESS;
|
Result result;
|
||||||
|
|
||||||
QFileInfo junctionInfo(linkName);
|
QFileInfo junctionInfo(linkName);
|
||||||
linkName = QDir::toNativeSeparators(junctionInfo.absoluteFilePath());
|
linkName = QDir::toNativeSeparators(junctionInfo.absoluteFilePath());
|
||||||
@ -129,13 +138,14 @@ public:
|
|||||||
if (GetVolumeInformationW(reinterpret_cast<const wchar_t *>(drive.utf16()),
|
if (GetVolumeInformationW(reinterpret_cast<const wchar_t *>(drive.utf16()),
|
||||||
NULL, 0, NULL, NULL, NULL,
|
NULL, 0, NULL, NULL, NULL,
|
||||||
fileSystem, sizeof(fileSystem)/sizeof(WCHAR)) == FALSE) {
|
fileSystem, sizeof(fileSystem)/sizeof(WCHAR)) == FALSE) {
|
||||||
result = GetLastError();
|
result.dwErr = GetLastError();
|
||||||
*errorMessage = "GetVolumeInformationW() failed: " + qt_error_string(int(result));
|
result.errorMessage = "GetVolumeInformationW() failed: " + qt_error_string(int(result.dwErr));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (QString::fromWCharArray(fileSystem) != "NTFS") {
|
if (QString::fromWCharArray(fileSystem) != "NTFS") {
|
||||||
*errorMessage = "This seems not to be an NTFS volume. Junctions are not allowed.";
|
result.errorMessage = "This seems not to be an NTFS volume. Junctions are not allowed.";
|
||||||
return ERROR_NOT_SUPPORTED;
|
result.dwErr = ERROR_NOT_SUPPORTED;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target.startsWith("\\??\\") && !target.startsWith("\\\\?\\")) {
|
if (!target.startsWith("\\??\\") && !target.startsWith("\\\\?\\")) {
|
||||||
@ -149,8 +159,8 @@ public:
|
|||||||
hFile = CreateFileW( (wchar_t*)linkName.utf16(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
hFile = CreateFileW( (wchar_t*)linkName.utf16(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
||||||
FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL );
|
FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL );
|
||||||
if (hFile == INVALID_HANDLE_VALUE) {
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||||||
result = GetLastError();
|
result.dwErr = GetLastError();
|
||||||
*errorMessage = "CreateFileW(" + linkName + ") failed: " + qt_error_string(int(result));
|
result.errorMessage = "CreateFileW(" + linkName + ") failed: " + qt_error_string(int(result.dwErr));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,8 +175,11 @@ public:
|
|||||||
reparseInfo->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE,
|
reparseInfo->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE,
|
||||||
NULL, 0, &returnedLength, NULL);
|
NULL, 0, &returnedLength, NULL);
|
||||||
if (!ioc) {
|
if (!ioc) {
|
||||||
result = GetLastError();
|
result.dwErr = GetLastError();
|
||||||
*errorMessage = "DeviceIoControl() failed: " + qt_error_string(int(result));
|
result.errorMessage = "DeviceIoControl() failed: " + qt_error_string(int(result.dwErr));
|
||||||
|
} else {
|
||||||
|
result.link = linkName;
|
||||||
|
result.target = target;
|
||||||
}
|
}
|
||||||
CloseHandle( hFile );
|
CloseHandle( hFile );
|
||||||
return result;
|
return result;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user