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 /src/corelib | |
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 'src/corelib')
-rw-r--r-- | src/corelib/io/qfsfileengine.cpp | 2 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_win.cpp | 18 |
2 files changed, 18 insertions, 2 deletions
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index a1ffb81..3cf08a7 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -208,6 +208,8 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) fi.setFile(prefix); if (fi.isSymLink()) { QString target = fi.symLinkTarget(); + if(QFileInfo(target).isRelative()) + target = fi.absolutePath() + slash + target; if (separatorPos != -1) { if (fi.isDir() && !target.endsWith(slash)) target.append(slash); diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index eeca07e..668379f 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -1275,7 +1275,12 @@ static QString readSymLink(const QString &link) REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize); DWORD retsize = 0; if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) { - if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); + const wchar_t* PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[offset]; + result = QString::fromWCharArray(PathBuffer, length); + } else if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { int length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); int offset = rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset]; @@ -1287,6 +1292,15 @@ static QString readSymLink(const QString &link) } qFree(rdb); CloseHandle(handle); + + QRegExp matchVolName(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), Qt::CaseInsensitive); + if(matchVolName.indexIn(result) == 0) { + DWORD len; + wchar_t buffer[MAX_PATH]; + QString volumeName = result.mid(0, matchVolName.matchedLength()).prepend(QLatin1String("\\\\?\\")); + if(GetVolumePathNamesForVolumeNameW(volumeName.utf16(), buffer, MAX_PATH, &len) != 0) + result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer)); + } } #else Q_UNUSED(link); @@ -1538,7 +1552,7 @@ bool QFSFileEnginePrivate::isSymlink() const if (hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); if ((findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - && findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) { + && (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK || findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) { is_link = true; } } |