summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@nokia.com>2010-04-15 13:28:31 (GMT)
committerZeno Albisser <zeno.albisser@nokia.com>2010-04-23 08:13:54 (GMT)
commit242845a50410e7b97206f6374408a2e53b5c29fb (patch)
tree082c813b80adad61e5d59db40bdf58e06f1fbb87 /src/corelib
parent06823355a435fa9bc9b5aa39d8687e85b3b7beaf (diff)
downloadQt-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.cpp2
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp18
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;
}
}