summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qfilesystemengine_unix.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-09-20 18:31:38 -0700
committerThiago Macieira <thiago.macieira@intel.com>2023-09-23 16:16:09 -0700
commit36a169e31e86fadde41c61804ce437164977f60a (patch)
treed7d120bd6f927c2287840cb76c3baeabea998ae5 /src/corelib/io/qfilesystemengine_unix.cpp
parent6c504f2519e1180dbcfd77d5bb08b0db9742eeaa (diff)
moveToTrash/Unix: use lstat() to confirm $root/.Trash is suitable
We can't use QFileSystemEngine::fillMetaData() because there's no bit in QFileSystemMetaData to indicate the sticky flag, so we must make a at least one stat() or lstat() call ourselves. Given that we need to know if $root/.Trash is a symlink, that system call must be lstat(). And it turns out that system call provides everything we need to confirm its suitability. This avoids QDir overhead just to manipulate strings. Pick-to: 6.6 Change-Id: I9d43e5b91eb142d6945cfffd1786c5e54199ecb2 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/corelib/io/qfilesystemengine_unix.cpp')
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp36
1 files changed, 14 insertions, 22 deletions
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 4fa28a2952..355d553aaf 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -1187,7 +1187,7 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy
#ifndef QT_BOOTSTRAPPED
static QString freeDesktopTrashLocation(const QString &sourcePath)
{
- auto makeTrashDir = [](const QDir &topDir, const QString &trashDir) -> QString {
+ auto makeTrashDir = [](const QDir &topDir, const QString &trashDir = QString()) {
auto ownerPerms = QFileDevice::ReadOwner
| QFileDevice::WriteOwner
| QFileDevice::ExeOwner;
@@ -1201,21 +1201,15 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
return targetDir;
return QString();
};
- auto isSticky = [](const QFileInfo &fileInfo) -> bool {
- struct stat st;
- if (stat(QFile::encodeName(fileInfo.absoluteFilePath()).constData(), &st) == 0)
- return st.st_mode & S_ISVTX;
-
- return false;
- };
QString trash;
const QStorageInfo sourceStorage(sourcePath);
const QStorageInfo homeStorage(QDir::home());
// We support trashing of files outside the users home partition
if (sourceStorage != homeStorage) {
- const auto dotTrash = ".Trash"_L1;
- QDir topDir(sourceStorage.rootPath());
+ const auto dotTrash = "/.Trash"_L1;
+ QFileSystemEntry dotTrashDir(sourceStorage.rootPath() + dotTrash);
+
/*
Method 1:
"An administrator can create an $topdir/.Trash directory. The permissions on this
@@ -1226,21 +1220,20 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
(if it supports trashing in top directories) MUST check for the presence
of $topdir/.Trash."
*/
- const QString userID = QString::number(::getuid());
- if (topDir.cd(dotTrash)) {
- const QFileInfo trashInfo(topDir.path());
+ const QString userID = QString::number(::getuid());
+ if (QT_STATBUF st; QT_LSTAT(dotTrashDir.nativeFilePath(), &st) == 0) {
// we MUST check that the sticky bit is set, and that it is not a symlink
- if (trashInfo.isSymLink()) {
+ if (S_ISLNK(st.st_mode)) {
// we SHOULD report the failed check to the administrator
qCritical("Warning: '%s' is a symlink to '%s'",
- trashInfo.absoluteFilePath().toLocal8Bit().constData(),
- trashInfo.symLinkTarget().toLatin1().constData());
- } else if (!isSticky(trashInfo)) {
+ dotTrashDir.nativeFilePath().constData(),
+ qt_readlink(dotTrashDir.nativeFilePath()).constData());
+ } 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!",
- trashInfo.absoluteFilePath().toLocal8Bit().constData());
- } else if (trashInfo.isDir()) {
+ dotTrashDir.nativeFilePath().constData());
+ } else if (S_ISDIR(st.st_mode)) {
/*
"If the directory exists and passes the checks, a subdirectory of the
$topdir/.Trash directory is to be used as the user's trash directory
@@ -1250,7 +1243,7 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
the implementation MUST immediately create it, without any warnings or
delays for the user."
*/
- trash = makeTrashDir(topDir, userID);
+ trash = makeTrashDir(dotTrashDir.filePath(), userID);
}
}
/*
@@ -1261,9 +1254,8 @@ static QString freeDesktopTrashLocation(const QString &sourcePath)
immediately create it, without any warnings or delays for the user."
*/
if (trash.isEmpty()) {
- topDir = QDir(sourceStorage.rootPath());
const QString userTrashDir = dotTrash + u'-' + userID;
- trash = makeTrashDir(topDir, userTrashDir);
+ trash = makeTrashDir(QDir(sourceStorage.rootPath() + userTrashDir));
}
}
/*