QFile::moveToTrash: use $XDG_DATA_HOME/Trash as the trash directory

The code assumed that files in $HOME should be moved into $HOME/.Trash,
which is not what the spec says. The "home trash" is defined to be
$XDG_DATA_HOME/Trash, and we can expect $XDG_DATA_HOME to exist. If it
doesn't, then we can safely fail, as the environment is not compliant
with the Desktop Base Directory Specification [1] anyway.

[1] http://www.freedesktop.org/Standards/basedir-spec

This will make the tests fail on such non-compliant environments, such
as server versions of the distribution. That's acceptable.

[ChangeLog][QtCore][QFile] moveToTrash now creates the trash folder on
Linux as $XDG_DATA_HOME/Trash, as required by the freedesktop.org spec.

Change-Id: I7ef73c0c268ef5ea4df141bb7831b93a65ad213a
Fixes: QTBUG-83933
Pick-to: 5.15
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
Volker Hilsheimer 2020-05-04 09:44:15 +02:00
parent ea7d85457d
commit 112c285fcc

View File

@ -47,6 +47,9 @@
#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qoperatingsystemversion.h>
#include <QtCore/private/qcore_unix_p.h> #include <QtCore/private/qcore_unix_p.h>
#include <QtCore/qvarlengtharray.h> #include <QtCore/qvarlengtharray.h>
#ifndef QT_BOOTSTRAPPED
# include <QtCore/qstandardpaths.h>
#endif // QT_BOOTSTRAPPED
#include <pwd.h> #include <pwd.h>
#include <stdlib.h> // for realpath() #include <stdlib.h> // for realpath()
@ -1212,6 +1215,7 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
| QFileDevice::WriteOwner | QFileDevice::WriteOwner
| QFileDevice::ExeOwner; | QFileDevice::ExeOwner;
QString targetDir = topDir.filePath(trashDir); QString targetDir = topDir.filePath(trashDir);
// deliberately not using mkpath, since we want to fail if topDir doesn't exist
if (topDir.mkdir(trashDir)) if (topDir.mkdir(trashDir))
QFile::setPermissions(targetDir, ownerPerms); QFile::setPermissions(targetDir, ownerPerms);
if (QFileInfo(targetDir).isDir()) if (QFileInfo(targetDir).isDir())
@ -1227,11 +1231,11 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
}; };
QString trash; QString trash;
const QLatin1String dotTrash(".Trash");
const QStorageInfo sourceStorage(sourcePath); const QStorageInfo sourceStorage(sourcePath);
const QStorageInfo homeStorage(QDir::home()); const QStorageInfo homeStorage(QDir::home());
// We support trashing of files outside the users home partition // We support trashing of files outside the users home partition
if (sourceStorage != homeStorage) { if (sourceStorage != homeStorage) {
const QLatin1String dotTrash(".Trash");
QDir topDir(sourceStorage.rootPath()); QDir topDir(sourceStorage.rootPath());
/* /*
Method 1: Method 1:
@ -1288,13 +1292,17 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
file into the user's home trash or refuse to trash it." file into the user's home trash or refuse to trash it."
We trash the file into the user's home trash. We trash the file into the user's home trash.
"Its name and location are $XDG_DATA_HOME/Trash"; $XDG_DATA_HOME is what
QStandardPaths returns for GenericDataLocation. If that doesn't exist, then
we are not running on a freedesktop.org-compliant environment, and give up.
*/ */
if (trash.isEmpty()) { if (trash.isEmpty()) {
QDir topDir = QDir::home(); QDir topDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
trash = makeTrashDir(topDir, dotTrash); trash = makeTrashDir(topDir, QLatin1String("Trash"));
if (!QFileInfo(trash).isDir()) { if (!QFileInfo(trash).isDir()) {
qWarning("Unable to establish trash directory %s in %s", qWarning("Unable to establish trash directory in %s",
dotTrash.latin1(), topDir.path().toLocal8Bit().constData()); topDir.path().toLocal8Bit().constData());
} }
} }