From ed46f1f00266ffc60b26248c8581bce72666c5eb Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Wed, 14 Sep 2022 14:19:59 +0200 Subject: [PATCH] linuxdevice: Fix ::bytesAvailable DeviceShell does not support piping commands at the moment. To continue to support ::bytesAvailable the parsing of the output from "df" is moved to FileUtils::bytesAvailableFromDFOutput. Change-Id: Ia229208748aa6c572b99899e6ae042bdd5654f4a Reviewed-by: Eike Ziller Reviewed-by: Qt CI Bot Reviewed-by: Jarek Kobus --- src/libs/utils/fileutils.cpp | 22 +++++++++++++++ src/libs/utils/fileutils.h | 2 ++ src/plugins/remotelinux/linuxdevice.cpp | 8 ++---- tests/auto/utils/fileutils/tst_fileutils.cpp | 29 ++++++++++++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index bdd67a6609e..32d41ec4c8c 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -531,4 +531,26 @@ void FileUtils::iterateLsOutput(const FilePath &base, #endif // QT_WIDGETS_LIB +qint64 FileUtils::bytesAvailableFromDFOutput(const QByteArray &dfOutput) +{ + const auto lines = filtered(dfOutput.split('\n'), + [](const QByteArray &line) { return line.size() > 0; }); + + QTC_ASSERT(lines.size() == 2, return -1); + const auto headers = filtered(lines[0].split(' '), + [](const QByteArray &field) { return field.size() > 0; }); + QTC_ASSERT(headers.size() >= 4, return -1); + QTC_ASSERT(headers[3] == QByteArray("Available"), return -1); + + const auto fields = filtered(lines[1].split(' '), + [](const QByteArray &field) { return field.size() > 0; }); + QTC_ASSERT(fields.size() >= 4, return -1); + + bool ok = false; + const quint64 result = QString::fromUtf8(fields[3]).toULongLong(&ok); + if (ok) + return result; + return -1; +} + } // namespace Utils diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h index 995ebfb78b0..a97d6e125b9 100644 --- a/src/libs/utils/fileutils.h +++ b/src/libs/utils/fileutils.h @@ -144,6 +144,8 @@ public: const FileFilter &filter, const std::function &callBack); + static qint64 bytesAvailableFromDFOutput(const QByteArray &dfOutput); + #ifdef QT_WIDGETS_LIB static void setDialogParentGetter(const std::function &getter); diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 813934e9200..b41a1f19b82 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -1273,13 +1273,9 @@ qint64 LinuxDevice::bytesAvailable(const FilePath &filePath) const QTC_ASSERT(handlesFile(filePath), return -1); CommandLine cmd("df", {"-k"}); cmd.addArg(filePath.path()); - cmd.addArgs("|tail -n 1 |sed 's/ */ /g'|cut -d ' ' -f 4", CommandLine::Raw); const QByteArray output = d->outputForRunInShell(cmd); - bool ok = false; - const qint64 size = output.toLongLong(&ok); - if (ok) - return size * 1024; - return -1; + + return FileUtils::bytesAvailableFromDFOutput(output); } QFileDevice::Permissions LinuxDevice::permissions(const FilePath &filePath) const diff --git a/tests/auto/utils/fileutils/tst_fileutils.cpp b/tests/auto/utils/fileutils/tst_fileutils.cpp index 38856873b97..c6ea1bab207 100644 --- a/tests/auto/utils/fileutils/tst_fileutils.cpp +++ b/tests/auto/utils/fileutils/tst_fileutils.cpp @@ -62,6 +62,8 @@ private slots: void linkFromString(); void pathAppended_data(); void pathAppended(); + void bytesAvailableFromDF_data(); + void bytesAvailableFromDF(); void asyncLocalCopy(); @@ -527,5 +529,32 @@ void tst_fileutils::asyncLocalCopy() QVERIFY(spy.count() == 1 || spy.wait(3000)); } +void tst_fileutils::bytesAvailableFromDF_data() +{ + QTest::addColumn("dfOutput"); + QTest::addColumn("expected"); + + QTest::newRow("empty") << QByteArray("") << qint64(-1); + QTest::newRow("mac") << QByteArray("Filesystem 1024-blocks Used Available Capacity iused ifree %iused Mounted on\n/dev/disk3s5 971350180 610014564 342672532 65% 4246780 3426725320 0% /System/Volumes/Data\n") << qint64(342672532); + QTest::newRow("alpine") << QByteArray("Filesystem 1K-blocks Used Available Use% Mounted on\noverlay 569466448 163526072 376983360 30% /\n") << qint64(376983360); + QTest::newRow("alpine-no-trailing-br") << QByteArray("Filesystem 1K-blocks Used Available Use% Mounted on\noverlay 569466448 163526072 376983360 30% /") << qint64(376983360); + QTest::newRow("alpine-missing-line") << QByteArray("Filesystem 1K-blocks Used Available Use% Mounted on\n") << qint64(-1); + QTest::newRow("wrong-header") << QByteArray("Filesystem 1K-blocks Used avail Use% Mounted on\noverlay 569466448 163526072 376983360 30% /\n") << qint64(-1); + QTest::newRow("not-enough-fields") << QByteArray("Filesystem 1K-blocks Used avail Use% Mounted on\noverlay 569466448\n") << qint64(-1); + QTest::newRow("not-enough-header-fields") << QByteArray("Filesystem 1K-blocks Used \noverlay 569466448 163526072 376983360 30% /\n") << qint64(-1); +} + +void tst_fileutils::bytesAvailableFromDF() +{ + if (HostOsInfo::isWindowsHost()) + QSKIP("Test only valid on unix-ish systems"); + + QFETCH(QByteArray, dfOutput); + QFETCH(qint64, expected); + + const auto result = FileUtils::bytesAvailableFromDFOutput(dfOutput); + QCOMPARE(result, expected); +} + QTEST_GUILESS_MAIN(tst_fileutils) #include "tst_fileutils.moc"