diff options
author | Tim Jenssen <tim.jenssen@nokia.com> | 2012-05-30 18:29:54 +0200 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@nokia.com> | 2012-05-30 18:43:01 +0200 |
commit | f9a37cb9585e8a28843f8b234497a22da6f2bcff (patch) | |
tree | cdaaf6e4352004b78bcdb82217119794c3024bec /src/libs/installer/link.cpp | |
parent | cedcc6eb4bc7c57c7cb5da06de121021faa82ba9 (diff) |
QFileInfo(m_path).readLink(); can't read junctions
- in older code there was a try to resolve junctions like symbolic links,
but this broke many other code
- we copied the read windows symlink code from the private qt file and
made small adjustmenst to be able to call it directly in targetPath() method
- and changed the isValid behaviour, because we want to create links to
locations which are created later
- and it is creating the path to the link on every OS
Change-Id: Id11839bbf2ecfde410982833d10f96d36fe1cab7
Reviewed-by: Alexander Lenhardt <alexander.lenhardt@nokia.com>
Diffstat (limited to 'src/libs/installer/link.cpp')
-rw-r--r-- | src/libs/installer/link.cpp | 77 |
1 files changed, 61 insertions, 16 deletions
diff --git a/src/libs/installer/link.cpp b/src/libs/installer/link.cpp index daf9daa61..ac70ff423 100644 --- a/src/libs/installer/link.cpp +++ b/src/libs/installer/link.cpp @@ -80,6 +80,7 @@ public: QString normalizedPath = QString(path).replace(QLatin1Char('/'), QLatin1Char('\\')); m_dirHandle = CreateFile(normalizedPath.utf16(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0); + if (m_dirHandle == INVALID_HANDLE_VALUE) { qWarning() << QString::fromLatin1("Could not open: '%1'; error: %2\n").arg(path).arg(GetLastError()); } @@ -98,17 +99,42 @@ private: HANDLE m_dirHandle; }; +QString readWindowsSymLink(const QString &path) +{ + QString result; + FileHandleWrapper dirHandle(path); + if (dirHandle.handle() != INVALID_HANDLE_VALUE) { + REPARSE_DATA_BUFFER* reparseStructData = (REPARSE_DATA_BUFFER*)calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + DWORD bytesReturned = 0; + if (::DeviceIoControl(dirHandle.handle(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseStructData, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned, 0)) { + if (reparseStructData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + int length = reparseStructData->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + int offset = reparseStructData->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); + const wchar_t* PathBuffer = &reparseStructData->MountPointReparseBuffer.PathBuffer[offset]; + result = QString::fromWCharArray(PathBuffer, length); + } else if (reparseStructData->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + int length = reparseStructData->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + int offset = reparseStructData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); + const wchar_t* PathBuffer = &reparseStructData->SymbolicLinkReparseBuffer.PathBuffer[offset]; + result = QString::fromWCharArray(PathBuffer, length); + } + // cut-off "//?/" and "/??/" + if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\')) + result = result.mid(4); + } + free(reparseStructData); + } + return result; +} + Link createJunction(const QString &linkPath, const QString &targetPath) { - bool junctionDirectoryExists = QFileInfo(linkPath).exists(); - if (!junctionDirectoryExists) - junctionDirectoryExists = QDir().mkpath(linkPath); - if (!junctionDirectoryExists) { + if (!QDir().mkpath(linkPath)) { qWarning() << QString::fromLatin1("Could not create the mount directory: %1").arg( linkPath); return Link(linkPath); } - FileHandleWrapper dirHandle(linkPath); if (dirHandle.handle() == INVALID_HANDLE_VALUE) { qWarning() << QString::fromLatin1("Could not open: '%1'; error: %2\n").arg(linkPath).arg( @@ -180,7 +206,7 @@ bool removeJunction(const QString &path) Link createLnSymlink(const QString &linkPath, const QString &targetPath) { int linkedError = symlink(targetPath.toLocal8Bit(), linkPath.toLocal8Bit()); - if (linkedError > 0) { + if (linkedError != 0) { qWarning() << QString::fromLatin1("Could not create a symlink: from '%1' to %2; error: %3" ).arg(linkPath, targetPath).arg(linkedError); } @@ -200,29 +226,48 @@ Link::Link(const QString &path) : m_path(path) { } -Link Link::create(const QString &linkPath, const QString &targetPath) +Link Link::create(const QString &link, const QString &targetPath) { - QFileInfo targetFileInfo(targetPath); - if (!targetFileInfo.exists()) { - qWarning() << QString::fromLatin1("\"%1\" does not exist - so nothing was created."); - return Link(linkPath); + QStringList pathParts = QFileInfo(link).absoluteFilePath().split(QLatin1Char('/')); + pathParts.removeLast(); + QString linkPath = pathParts.join(QLatin1String("/")); + bool linkPathExists = QFileInfo(linkPath).exists(); + if (!linkPathExists) + linkPathExists = QDir().mkpath(linkPath); + if (!linkPathExists) { + qWarning() << QString::fromLatin1("Could not create the needed directories: %1").arg( + link); + return Link(link); } #ifdef Q_OS_WIN - if (targetFileInfo.isDir()) - return createJunction(linkPath, targetPath); + if (QFileInfo(targetPath).isDir()) + return createJunction(link, targetPath); qWarning() << QString::fromLatin1("At the moment the %1 can not create anything else as "\ "junctions for directories under windows").arg(QLatin1String(Q_FUNC_INFO)); - return Link(linkPath); + return Link(link); #else - return createLnSymlink(linkPath, targetPath); + return createLnSymlink(link, targetPath); #endif } QString Link::targetPath() const { +#ifdef Q_OS_WIN + return readWindowsSymLink(m_path); +#else return QFileInfo(m_path).readLink(); +#endif +} + +bool Link::exists() +{ +#ifdef Q_OS_WIN + return QFileInfo(m_path).exists(); +#else + return QFileInfo(m_path).isSymLink(); +#endif } bool Link::targetExists() @@ -237,7 +282,7 @@ bool Link::isValid() bool Link::remove() { - if (!isValid()) + if (!QFileInfo(m_path).exists()) return false; #ifdef Q_OS_WIN return removeJunction(m_path); |