diff options
author | Zeno Albisser <zeno.albisser@nokia.com> | 2010-04-15 13:28:31 (GMT) |
---|---|---|
committer | Zeno Albisser <zeno.albisser@nokia.com> | 2010-04-23 08:13:54 (GMT) |
commit | 242845a50410e7b97206f6374408a2e53b5c29fb (patch) | |
tree | 082c813b80adad61e5d59db40bdf58e06f1fbb87 /tests/shared/filesystem.h | |
parent | 06823355a435fa9bc9b5aa39d8687e85b3b7beaf (diff) | |
download | Qt-242845a50410e7b97206f6374408a2e53b5c29fb.zip Qt-242845a50410e7b97206f6374408a2e53b5c29fb.tar.gz Qt-242845a50410e7b97206f6374408a2e53b5c29fb.tar.bz2 |
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/filesystem.h')
-rw-r--r-- | tests/shared/filesystem.h | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h index 2d46c0d..cc1781e 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; |