From 1216161584b730576c24fb128131838be1826b37 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Fri, 21 Aug 2009 15:26:53 +0200 Subject: NTFS symlink support for QFileInfo::isSymLink() We will handle reparse points with IO_REPARSE_TAG_MOUNT_POINT and IO_REPARSE_TAG_SYMLINK tag values only. isSymlink() assumes doStat() was called early. Merge-request: 1217 Reviewed-by: Joerg Bornemann --- src/corelib/io/qfsfileengine.cpp | 2 +- src/corelib/io/qfsfileengine_p.h | 3 ++- src/corelib/io/qfsfileengine_win.cpp | 40 +++++++++++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 3d109d1..1ca19cf 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -109,7 +109,7 @@ void QFSFileEnginePrivate::init() { is_sequential = 0; tried_stat = 0; -#ifdef Q_OS_UNIX +#if !defined(Q_OS_WINCE) need_lstat = 1; is_link = 0; #endif diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 15cbf5c..3c1e7e0 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -137,10 +137,11 @@ public: mutable uint is_sequential : 2; mutable uint could_stat : 1; mutable uint tried_stat : 1; -#ifdef Q_OS_UNIX +#if !defined(Q_OS_WINCE) mutable uint need_lstat : 1; mutable uint is_link : 1; #endif + bool doStat() const; bool isSymlink() const; diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index e524e8e..7b08767 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -1440,6 +1440,41 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const } /*! + \internal +*/ +bool QFSFileEnginePrivate::isSymlink() const +{ +#if !defined(Q_OS_WINCE) + if (need_lstat) { + need_lstat = false; + is_link = false; + + if (fileAttrib & FILE_ATTRIBUTE_REPARSE_POINT) { + QString path = QDir::toNativeSeparators(filePath); + // path for the FindFirstFile should not end with a trailing slash + while (path.endsWith(QLatin1Char('\\'))) + path.chop(1); + + WIN32_FIND_DATA findData; + HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), + &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + if ((findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + && (findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT + || findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) { + is_link = true; + } + } + } + } + return is_link; +#else + return false; +#endif // Q_OS_WINCE +} + +/*! \reimp */ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::FileFlags type) const @@ -1449,6 +1484,9 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil // Force a stat, so that we're guaranteed to get up-to-date results if (type & Refresh) { d->tried_stat = 0; +#if !defined(Q_OS_WINCE) + d->need_lstat = 1; +#endif } if (type & PermsMask) { @@ -1472,7 +1510,7 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil ret |= FileType; } } else if (d->doStat()) { - if (d->fileAttrib & FILE_ATTRIBUTE_REPARSE_POINT) + if ((type & LinkType) && d->isSymlink()) ret |= LinkType; if (d->fileAttrib & FILE_ATTRIBUTE_DIRECTORY) { ret |= DirectoryType; -- cgit v0.12