From c7398dfdc581fbf36205fa826ad2aeadcd9b0122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Tue, 7 Apr 2015 22:24:15 +0200 Subject: [PATCH] GH-228 do not recurse into reparse points when deleting instances --- depends/util/include/pathutils.h | 8 +++++ depends/util/src/pathutils.cpp | 59 ++++++++++++++++++++++++++++++++ logic/BaseInstance.cpp | 2 +- logic/InstanceList.cpp | 2 +- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/depends/util/include/pathutils.h b/depends/util/include/pathutils.h index a506280e..f31b96d1 100644 --- a/depends/util/include/pathutils.h +++ b/depends/util/include/pathutils.h @@ -51,8 +51,16 @@ LIBUTIL_EXPORT bool ensureFilePathExists(QString filenamepath); */ LIBUTIL_EXPORT bool ensureFolderPathExists(QString filenamepath); +/** + * Copy a folder recursively + */ LIBUTIL_EXPORT bool copyPath(QString src, QString dst, bool follow_symlinks = true); +/** + * Delete a folder recursively + */ +LIBUTIL_EXPORT bool deletePath(QString path); + /// Opens the given file in the default application. LIBUTIL_EXPORT void openFileInDefaultProgram(QString filename); diff --git a/depends/util/src/pathutils.cpp b/depends/util/src/pathutils.cpp index 1cbb2cb2..ce9138be 100644 --- a/depends/util/src/pathutils.cpp +++ b/depends/util/src/pathutils.cpp @@ -152,6 +152,65 @@ bool copyPath(QString src, QString dst, bool follow_symlinks) } return OK; } +#if defined Q_OS_WIN32 +#include +#include +#endif +bool deletePath(QString path) +{ + bool OK = true; + QDir dir(path); + + if (!dir.exists()) + { + return OK; + } + auto allEntries = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | + QDir::AllDirs | QDir::Files, + QDir::DirsFirst); + + for(QFileInfo info: allEntries) + { +#if defined Q_OS_WIN32 + QString nativePath = QDir::toNativeSeparators(info.absoluteFilePath()); + auto wString = nativePath.toStdWString(); + DWORD dwAttrs = GetFileAttributesW(wString.c_str()); + // Windows: check for junctions, reparse points and other nasty things of that sort + if(dwAttrs & FILE_ATTRIBUTE_REPARSE_POINT) + { + if (info.isFile()) + { + OK &= QFile::remove(info.absoluteFilePath()); + } + else if (info.isDir()) + { + OK &= dir.rmdir(info.absoluteFilePath()); + } + } +#else + // We do not trust Qt with reparse points, but do trust it with unix symlinks. + if(info.isSymLink()) + { + OK &= QFile::remove(info.absoluteFilePath()); + } +#endif + else if (info.isDir()) + { + OK &= deletePath(info.absoluteFilePath()); + } + else if (info.isFile()) + { + OK &= QFile::remove(info.absoluteFilePath()); + } + else + { + OK = false; + qCritical() << "Delete ERROR: Unknown filesystem object:" << info.absoluteFilePath(); + } + } + OK &= dir.rmdir(dir.absolutePath()); + return OK; +} void openDirInDefaultProgram(QString path, bool ensureExists) { diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index 69bc7597..1c6d3e4b 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -61,7 +61,7 @@ void BaseInstance::iconUpdated(QString key) void BaseInstance::nuke() { - QDir(instanceRoot()).removeRecursively(); + deletePath(instanceRoot()); emit nuked(this); } diff --git a/logic/InstanceList.cpp b/logic/InstanceList.cpp index 4e295e7f..3bdceb51 100644 --- a/logic/InstanceList.cpp +++ b/logic/InstanceList.cpp @@ -503,7 +503,7 @@ InstanceList::copyInstance(InstancePtr &newInstance, InstancePtr &oldInstance, c qDebug() << instDir.toUtf8(); if (!copyPath(oldInstance->instanceRoot(), instDir, false)) { - rootDir.removeRecursively(); + deletePath(instDir); return InstanceList::CantCreateDir; }