summaryrefslogtreecommitdiffstats
path: root/tests/shared
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@nokia.com>2010-04-15 15:28:31 +0200
committerZeno Albisser <zeno.albisser@nokia.com>2010-04-23 10:13:54 +0200
commit242845a50410e7b97206f6374408a2e53b5c29fb (patch)
tree082c813b80adad61e5d59db40bdf58e06f1fbb87 /tests/shared
parent06823355a435fa9bc9b5aa39d8687e85b3b7beaf (diff)
Added support for symlinks and junction points on Windows
Since ntfs symlinks (not .lnk files) can use relative paths to targets, support for relative links needed to be added. Directory junctions can also be used to mount another filesystem directly into an existing folder. Such junctions in that case use the volume id of the target volume for the link path. Therefor this commit also includes an implementation for resolving volume ids. To be independent of existing directories in test code i added a function to create own junction points. Reviewed-by: Joao Task-number: QTBUG-9009, QTBUG-7036
Diffstat (limited to 'tests/shared')
-rw-r--r--tests/shared/filesystem.h58
1 files changed, 58 insertions, 0 deletions
diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h
index 2d46c0d494..cc1781eb46 100644
--- a/tests/shared/filesystem.h
+++ b/tests/shared/filesystem.h
@@ -48,6 +48,11 @@
#include <QDir>
#include <QFile>
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+# define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
+# define REPARSE_MOUNTPOINT_HEADER_SIZE 8
+#endif
+
struct FileSystem
{
~FileSystem()
@@ -86,6 +91,59 @@ struct FileSystem
}
return false;
}
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ 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( 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.",SkipSingle);
+
+ 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( 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 = target.size() * 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:
QDir currentDir;