From 1c5575f194656e7b4392f2b18669010a39f5b274 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 20 Sep 2023 18:49:59 -0700 Subject: [PATCH] moveToTrash/Unix: trust freeDesktopTrashLocation() to find the directory Make it receive the QSystemError so it can set the error condition properly in case the suitable location for this input file can't be found. This also includes the case when the input file does not exist in the first place, which I moved into the function because upcoming commits will imply this check anyway. Change-Id: I9d43e5b91eb142d6945cfffd1786c6e59d3b0204 Reviewed-by: Ahmad Samir Reviewed-by: Volker Hilsheimer --- src/corelib/io/qfilesystemengine_unix.cpp | 34 +++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index c67cfdb966e..950939597a9 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -1194,9 +1194,9 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &, QFileSystemEnt Implementing as per https://specifications.freedesktop.org/trash-spec/trashspec-1.0.html */ -static QString freeDesktopTrashLocation(const QString &sourcePath) +static QString freeDesktopTrashLocation(const QFileSystemEntry &source, QSystemError &error) { - auto makeTrashDir = [](const QDir &topDir, const QString &trashDir = QString()) { + auto makeTrashDir = [](const QDir &topDir, const QString &trashDir, QSystemError &error) { auto ownerPerms = QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner; @@ -1205,13 +1205,22 @@ static QString freeDesktopTrashLocation(const QString &sourcePath) bool created = QFileSystemEngine::createDirectory(QFileSystemEntry(targetDir), false, ownerPerms); if (created) return targetDir; + error = QSystemError(errno, QSystemError::StandardLibraryError); + // maybe it already exists and is a directory if (QFileInfo(targetDir).isDir()) return targetDir; return QString(); }; + if (QFileSystemMetaData md; !QFileSystemEngine::fillMetaData(source, md, QFileSystemMetaData::ExistsAttribute) + || !md.exists()) { + error = QSystemError(ENOENT, QSystemError::StandardLibraryError); + return QString(); + } + QString trash; + const QString sourcePath = source.filePath(); const QStorageInfo sourceStorage(sourcePath); const QStorageInfo homeStorage(QDir::home()); // We support trashing of files outside the users home partition @@ -1238,10 +1247,12 @@ static QString freeDesktopTrashLocation(const QString &sourcePath) qCritical("Warning: '%s' is a symlink to '%s'", dotTrashDir.nativeFilePath().constData(), qt_readlink(dotTrashDir.nativeFilePath()).constData()); + error = QSystemError(ELOOP, QSystemError::StandardLibraryError); } else if ((st.st_mode & S_ISVTX) == 0) { // we SHOULD report the failed check to the administrator qCritical("Warning: '%s' doesn't have sticky bit set!", dotTrashDir.nativeFilePath().constData()); + error = QSystemError(EPERM, QSystemError::StandardLibraryError); } else if (S_ISDIR(st.st_mode)) { /* "If the directory exists and passes the checks, a subdirectory of the @@ -1252,7 +1263,7 @@ static QString freeDesktopTrashLocation(const QString &sourcePath) the implementation MUST immediately create it, without any warnings or delays for the user." */ - trash = makeTrashDir(dotTrashDir.filePath(), userID); + trash = makeTrashDir(dotTrashDir.filePath(), userID, error); } } /* @@ -1264,7 +1275,7 @@ static QString freeDesktopTrashLocation(const QString &sourcePath) */ if (trash.isEmpty()) { const QString userTrashDir = dotTrash + u'-' + userID; - trash = makeTrashDir(QDir(sourceStorage.rootPath() + userTrashDir)); + trash = makeTrashDir(QDir(sourceStorage.rootPath() + userTrashDir), QString(), error); } } /* @@ -1279,8 +1290,8 @@ static QString freeDesktopTrashLocation(const QString &sourcePath) */ if (trash.isEmpty()) { QDir topDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); - trash = makeTrashDir(topDir, "Trash"_L1); - if (!QFileInfo(trash).isDir()) { + trash = makeTrashDir(topDir, "Trash"_L1, error); + if (trash.isEmpty()) { qWarning("Unable to establish trash directory in %s", topDir.path().toLocal8Bit().constData()); } @@ -1293,11 +1304,6 @@ static QString freeDesktopTrashLocation(const QString &sourcePath) bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source, QFileSystemEntry &newLocation, QSystemError &error) { - const QFileInfo sourceInfo(source.filePath()); - if (!sourceInfo.exists()) { - error = QSystemError(ENOENT, QSystemError::StandardLibraryError); - return false; - } const QFileSystemEntry sourcePath = [&] { if (QString path = source.filePath(); path.size() > 1 && path.endsWith(u'/')) { path.chop(1); @@ -1305,10 +1311,10 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source, } return absoluteName(source); }(); - - QDir trashDir(freeDesktopTrashLocation(sourcePath.filePath())); - if (!trashDir.exists()) + QString trashPath = freeDesktopTrashLocation(sourcePath, error); + if (trashPath.isEmpty()) return false; + QDir trashDir(trashPath); /* "A trash directory contains two subdirectories, named info and files." */