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>
This commit is contained in:
parent
6c504f2519
commit
36a169e31e
@ -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));
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user