Utils: Fix iterateWithFind

The change of runInShell to take QString + QStringList meant
that the caller was no longer able to fine tune the argument
escaping. This lead to "find -exec ... \;" being escaped incorrectly.

Changing back to CommandLine fixes this.

Change-Id: I55b09bd745c09912a2a0b4e43432824a99c0dd4e
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2022-10-14 13:39:16 +02:00
parent 679a726330
commit a1e960a27c
4 changed files with 43 additions and 68 deletions

View File

@@ -6,6 +6,7 @@
#include "algorithm.h"
#include "qtcassert.h"
#include "hostosinfo.h"
#include "commandline.h"
#include <QCoreApplication>
#include <QOperatingSystemVersion>
@@ -619,83 +620,81 @@ OsType DesktopDeviceFileAccess::osType(const FilePath &filePath) const
UnixDeviceFileAccess::~UnixDeviceFileAccess() = default;
bool UnixDeviceFileAccess::runInShellSuccess(
const QString &executable,
const QStringList &args,
const QByteArray &stdInData) const
bool UnixDeviceFileAccess::runInShellSuccess(const CommandLine &cmdLine,
const QByteArray &stdInData) const
{
return runInShell(executable, args, stdInData).exitCode == 0;
return runInShell(cmdLine, stdInData).exitCode == 0;
}
bool UnixDeviceFileAccess::isExecutableFile(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("test", {"-x", path});
return runInShellSuccess({"test", {"-x", path}});
}
bool UnixDeviceFileAccess::isReadableFile(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("test", {"-r", path, "-a", "-f", path});
return runInShellSuccess({"test", {"-r", path, "-a", "-f", path}});
}
bool UnixDeviceFileAccess::isWritableFile(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("test", {"-w", path, "-a", "-f", path});
return runInShellSuccess({"test", {"-w", path, "-a", "-f", path}});
}
bool UnixDeviceFileAccess::isReadableDirectory(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("test", {"-r", path, "-a", "-d", path});
return runInShellSuccess({"test", {"-r", path, "-a", "-d", path}});
}
bool UnixDeviceFileAccess::isWritableDirectory(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("test", {"-w", path, "-a", "-d", path});
return runInShellSuccess({"test", {"-w", path, "-a", "-d", path}});
}
bool UnixDeviceFileAccess::isFile(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("test", {"-f", path});
return runInShellSuccess({"test", {"-f", path}});
}
bool UnixDeviceFileAccess::isDirectory(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("test", {"-d", path});
return runInShellSuccess({"test", {"-d", path}});
}
bool UnixDeviceFileAccess::isSymLink(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("test", {"-h", path});
return runInShellSuccess({"test", {"-h", path}});
}
bool UnixDeviceFileAccess::ensureExistingFile(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("touch", {path});
return runInShellSuccess({"touch", {path}});
}
bool UnixDeviceFileAccess::createDirectory(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("mkdir", {"-p", path});
return runInShellSuccess({"mkdir", {"-p", path}});
}
bool UnixDeviceFileAccess::exists(const FilePath &filePath) const
{
const QString path = filePath.path();
return runInShellSuccess("test", {"-e", path});
return runInShellSuccess({"test", {"-e", path}});
}
bool UnixDeviceFileAccess::removeFile(const FilePath &filePath) const
{
return runInShellSuccess("rm", {filePath.path()});
return runInShellSuccess({"rm", {filePath.path()}});
}
bool UnixDeviceFileAccess::removeRecursively(const FilePath &filePath, QString *error) const
@@ -711,7 +710,7 @@ bool UnixDeviceFileAccess::removeRecursively(const FilePath &filePath, QString *
levelsNeeded = 2;
QTC_ASSERT(path.count('/') >= levelsNeeded, return false);
RunResult result = runInShell("rm", {"-rf", "--", path});
RunResult result = runInShell({"rm", {"-rf", "--", path}});
if (error)
*error = QString::fromUtf8(result.stdErr);
return result.exitCode == 0;
@@ -719,17 +718,17 @@ bool UnixDeviceFileAccess::removeRecursively(const FilePath &filePath, QString *
bool UnixDeviceFileAccess::copyFile(const FilePath &filePath, const FilePath &target) const
{
return runInShellSuccess("cp", {filePath.path(), target.path()});
return runInShellSuccess({"cp", {filePath.path(), target.path()}});
}
bool UnixDeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const
{
return runInShellSuccess("mv", {filePath.path(), target.path()});
return runInShellSuccess({"mv", {filePath.path(), target.path()}});
}
FilePath UnixDeviceFileAccess::symLinkTarget(const FilePath &filePath) const
{
const RunResult result = runInShell("readlink", {"-n", "-e", filePath.path()});
const RunResult result = runInShell({"readlink", {"-n", "-e", filePath.path()}});
const QString out = QString::fromUtf8(result.stdOut);
return out.isEmpty() ? FilePath() : filePath.withNewPath(out);
}
@@ -747,7 +746,7 @@ std::optional<QByteArray> UnixDeviceFileAccess::fileContents(
args += QString("seek=%1").arg(offset / gcd);
}
const RunResult r = runInShell("dd", args);
const RunResult r = runInShell({"dd", args});
if (r.exitCode != 0)
return {};
@@ -765,7 +764,7 @@ bool UnixDeviceFileAccess::writeFileContents(
args.append("bs=1");
args.append(QString("seek=%1").arg(offset));
}
return runInShellSuccess("dd", args, data);
return runInShellSuccess({"dd", args}, data);
}
OsType UnixDeviceFileAccess::osType(const FilePath &filePath) const
@@ -776,7 +775,7 @@ OsType UnixDeviceFileAccess::osType(const FilePath &filePath) const
QDateTime UnixDeviceFileAccess::lastModified(const FilePath &filePath) const
{
const RunResult result = runInShell("stat", {"-L", "-c", "%Y", filePath.path()});
const RunResult result = runInShell({"stat", {"-L", "-c", "%Y", filePath.path()}});
qint64 secs = result.stdOut.toLongLong();
const QDateTime dt = QDateTime::fromSecsSinceEpoch(secs, Qt::UTC);
return dt;
@@ -784,7 +783,7 @@ QDateTime UnixDeviceFileAccess::lastModified(const FilePath &filePath) const
QFile::Permissions UnixDeviceFileAccess::permissions(const FilePath &filePath) const
{
const RunResult result = runInShell("stat", {"-L", "-c", "%a", filePath.path()});
const RunResult result = runInShell({"stat", {"-L", "-c", "%a", filePath.path()}});
const uint bits = result.stdOut.toUInt(nullptr, 8);
QFileDevice::Permissions perm = {};
#define BIT(n, p) if (bits & (1<<n)) perm |= QFileDevice::p
@@ -804,24 +803,24 @@ QFile::Permissions UnixDeviceFileAccess::permissions(const FilePath &filePath) c
bool UnixDeviceFileAccess::setPermissions(const FilePath &filePath, QFile::Permissions perms) const
{
const int flags = int(perms);
return runInShellSuccess("chmod", {QString::number(flags, 16), filePath.path()});
return runInShellSuccess({"chmod", {QString::number(flags, 16), filePath.path()}});
}
qint64 UnixDeviceFileAccess::fileSize(const FilePath &filePath) const
{
const RunResult result = runInShell("stat", {"-L", "-c", "%s", filePath.path()});
const RunResult result = runInShell({"stat", {"-L", "-c", "%s", filePath.path()}});
return result.stdOut.toLongLong();
}
qint64 UnixDeviceFileAccess::bytesAvailable(const FilePath &filePath) const
{
const RunResult result = runInShell("df", {"-k", filePath.path()});
const RunResult result = runInShell({"df", {"-k", filePath.path()}});
return FileUtils::bytesAvailableFromDFOutput(result.stdOut);
}
QByteArray UnixDeviceFileAccess::fileId(const FilePath &filePath) const
{
const RunResult result = runInShell("stat", {"-L", "-c", "%D:%i", filePath.path()});
const RunResult result = runInShell({"stat", {"-L", "-c", "%D:%i", filePath.path()}});
if (result.exitCode != 0)
return {};
@@ -830,7 +829,7 @@ QByteArray UnixDeviceFileAccess::fileId(const FilePath &filePath) const
FilePathInfo UnixDeviceFileAccess::filePathInfo(const FilePath &filePath) const
{
const RunResult stat = runInShell("stat", {"-L", "-c", "%f %Y %s", filePath.path()});
const RunResult stat = runInShell({"stat", {"-L", "-c", "%f %Y %s", filePath.path()}});
return FileUtils::filePathInfoFromTriple(QString::fromLatin1(stat.stdOut));
}
@@ -842,14 +841,14 @@ bool UnixDeviceFileAccess::iterateWithFind(
{
QTC_CHECK(filePath.isAbsolutePath());
QStringList arguments = filter.asFindArguments(filePath.path());
CommandLine cmdLine{"find", filter.asFindArguments(filePath.path())};
// TODO: Using stat -L will always return the link target, not the link itself.
// We may wan't to add the information that it is a link at some point.
if (callBack.index() == 1)
arguments.append(R"(-exec echo -n \"{}\"" " \; -exec stat -L -c "%f %Y %s" "{}" \;)");
cmdLine.addArgs(R"(-exec echo -n \"{}\"" " \; -exec stat -L -c "%f %Y %s" "{}" \;)", CommandLine::Raw);
const RunResult result = runInShell("find", arguments);
const RunResult result = runInShell(cmdLine);
const QString out = QString::fromUtf8(result.stdOut);
if (result.exitCode != 0) {
// Find returns non-zero exit code for any error it encounters, even if it finds some files.
@@ -901,7 +900,7 @@ void UnixDeviceFileAccess::findUsingLs(
const FileFilter &filter,
QStringList *found) const
{
const RunResult result = runInShell("ls", {"-1", "-p", "--", current});
const RunResult result = runInShell({"ls", {"-1", "-p", "--", current}});
const QStringList entries = QString::fromUtf8(result.stdOut).split('\n', Qt::SkipEmptyParts);
for (QString entry : entries) {
const QChar last = entry.back();