diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-09-20 18:31:38 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2023-09-23 16:16:09 -0700 |
commit | 36a169e31e86fadde41c61804ce437164977f60a (patch) | |
tree | d7d120bd6f927c2287840cb76c3baeabea998ae5 /src/corelib/io/qfilesystemengine_unix.cpp | |
parent | 6c504f2519e1180dbcfd77d5bb08b0db9742eeaa (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.cpp | 36 |
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)); } } /* |