diff options
Diffstat (limited to 'src/plugins/docker/dockerdevice.cpp')
-rw-r--r-- | src/plugins/docker/dockerdevice.cpp | 261 |
1 files changed, 40 insertions, 221 deletions
diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index bcab94bcb8b..be7124c995e 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -32,6 +32,7 @@ #include <utils/algorithm.h> #include <utils/basetreeview.h> +#include <utils/devicefileaccess.h> #include <utils/deviceshell.h> #include <utils/environment.h> #include <utils/fileutils.h> @@ -113,6 +114,25 @@ private: FilePath m_devicePath; }; +class DockerDeviceFileAccess : public UnixDeviceFileAccess +{ +public: + DockerDeviceFileAccess(DockerDevicePrivate *dev) + : m_dev(dev) + {} + + RunResult runInShell(const QString &executable, + const QStringList &arguments, + const QByteArray &stdInData) const override; + + std::optional<QByteArray> fileContents( + const FilePath &filePath, + qint64 limit, + qint64 offset) const override; + + DockerDevicePrivate *m_dev = nullptr; +}; + class DockerDevicePrivate : public QObject { public: @@ -129,8 +149,6 @@ public: return runInShell(cmd, stdInData).exitCode == 0; } - std::optional<QByteArray> fileContents(const FilePath &filePath, qint64 limit, qint64 offset); - void updateContainerAccess(); void changeMounts(QStringList newMounts); bool ensureReachable(const FilePath &other); @@ -177,8 +195,8 @@ public: QString m_container; Environment m_cachedEnviroment; - bool m_useFind = true; // prefer find over ls and hacks, but be able to use ls as fallback bool m_isShutdown = false; + DockerDeviceFileAccess m_fileAccess{this}; }; class DockerProcessImpl : public Utils::ProcessInterface @@ -337,9 +355,28 @@ Tasks DockerDevicePrivate::validateMounts() const return result; } +RunResult DockerDeviceFileAccess::runInShell( + const QString &executable, + const QStringList &arguments, + const QByteArray &stdInData) const +{ + QTC_ASSERT(m_dev, return {}); + return m_dev->runInShell({FilePath::fromString(executable), arguments}, stdInData); +} + +std::optional<QByteArray> DockerDeviceFileAccess::fileContents( + const FilePath &filePath, + qint64 limit, + qint64 offset) const +{ + m_dev->updateContainerAccess(); + return UnixDeviceFileAccess::fileContents(filePath, limit, offset); +} + DockerDevice::DockerDevice(DockerSettings *settings, const DockerDeviceData &data) : d(new DockerDevicePrivate(this, settings, data)) { + setFileAccess(&d->m_fileAccess); setDisplayType(Tr::tr("Docker")); setOsType(OsTypeOtherUnix); setDefaultDisplayName(Tr::tr("Docker Image")); @@ -778,165 +815,6 @@ bool DockerDevice::handlesFile(const FilePath &filePath) const return false; } -bool DockerDevice::isExecutableFile(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"test", {"-x", path}}); -} - -bool DockerDevice::isReadableFile(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"test", {"-r", path, "-a", "-f", path}}); -} - -bool DockerDevice::isWritableFile(const Utils::FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"test", {"-w", path, "-a", "-f", path}}); -} - -bool DockerDevice::isReadableDirectory(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"test", {"-r", path, "-a", "-d", path}}); -} - -bool DockerDevice::isWritableDirectory(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"test", {"-w", path, "-a", "-d", path}}); -} - -bool DockerDevice::isFile(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"test", {"-f", path}}); -} - -bool DockerDevice::isDirectory(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"test", {"-d", path}}); -} - -bool DockerDevice::createDirectory(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"mkdir", {"-p", path}}); -} - -bool DockerDevice::exists(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"test", {"-e", path}}); -} - -bool DockerDevice::ensureExistingFile(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - const QString path = filePath.path(); - return d->runInShellSuccess({"touch", {path}}); -} - -bool DockerDevice::removeFile(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - return d->runInShellSuccess({"rm", {filePath.path()}}); -} - -bool DockerDevice::removeRecursively(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - QTC_ASSERT(filePath.path().startsWith('/'), return false); - - const QString path = filePath.cleanPath().path(); - // We are expecting this only to be called in a context of build directories or similar. - // Chicken out in some cases that _might_ be user code errors. - QTC_ASSERT(path.startsWith('/'), return false); - const int levelsNeeded = path.startsWith("/home/") ? 4 : 3; - QTC_ASSERT(path.count('/') >= levelsNeeded, return false); - - return d->runInShellSuccess({"rm", {"-rf", "--", path}}); -} - -bool DockerDevice::copyFile(const FilePath &filePath, const FilePath &target) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - QTC_ASSERT(handlesFile(target), return false); - return d->runInShellSuccess({"cp", {filePath.path(), target.path()}}); -} - -bool DockerDevice::renameFile(const FilePath &filePath, const FilePath &target) const -{ - QTC_ASSERT(handlesFile(filePath), return false); - QTC_ASSERT(handlesFile(target), return false); - return d->runInShellSuccess({"mv", {filePath.path(), target.path()}}); -} - -QDateTime DockerDevice::lastModified(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return {}); - const RunResult result = d->runInShell({"stat", {"-L", "-c", "%Y", filePath.path()}}); - qint64 secs = result.stdOut.toLongLong(); - const QDateTime dt = QDateTime::fromSecsSinceEpoch(secs, Qt::UTC); - return dt; -} - -FilePath DockerDevice::symLinkTarget(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return {}); - const RunResult result = d->runInShell({"readlink", {"-n", "-e", filePath.path()}}); - const QString out = QString::fromUtf8(result.stdOut); - return out.isEmpty() ? FilePath() : filePath.withNewPath(out); -} - -qint64 DockerDevice::fileSize(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return -1); - const RunResult result = d->runInShell({"stat", {"-L", "-c", "%s", filePath.path()}}); - return result.stdOut.toLongLong(); -} - -QFileDevice::Permissions DockerDevice::permissions(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return {}); - - const RunResult result = d->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 - BIT(0, ExeOther); - BIT(1, WriteOther); - BIT(2, ReadOther); - BIT(3, ExeGroup); - BIT(4, WriteGroup); - BIT(5, ReadGroup); - BIT(6, ExeUser); - BIT(7, WriteUser); - BIT(8, ReadUser); -#undef BIT - return perm; -} - -bool DockerDevice::setPermissions(const FilePath &filePath, - QFileDevice::Permissions permissions) const -{ - Q_UNUSED(permissions) - QTC_ASSERT(handlesFile(filePath), return {}); - QTC_CHECK(false); // FIXME: Implement. - return false; -} - bool DockerDevice::ensureReachable(const FilePath &other) const { if (other.needsDevice()) @@ -947,43 +825,6 @@ bool DockerDevice::ensureReachable(const FilePath &other) const return d->ensureReachable(other.parentDir()); } -void DockerDevice::iterateDirectory(const FilePath &filePath, - const FilePath::IterateDirCallback &callBack, - const FileFilter &filter) const -{ - QTC_ASSERT(handlesFile(filePath), return); - auto runInShell = [this](const CommandLine &cmd) { return d->runInShell(cmd); }; - FileUtils::iterateUnixDirectory(filePath, filter, &d->m_useFind, runInShell, callBack); -} - -std::optional<QByteArray> DockerDevice::fileContents(const FilePath &filePath, - qint64 limit, - qint64 offset) const -{ - QTC_ASSERT(handlesFile(filePath), return {}); - return d->fileContents(filePath, limit, offset); -} - -bool DockerDevice::writeFileContents(const FilePath &filePath, - const QByteArray &data, - qint64 offset) const -{ - QTC_ASSERT(handlesFile(filePath), return {}); - CommandLine cmd({"dd", {"of=" + filePath.path()}}); - if (offset != 0) { - cmd.addArg("bs=1"); - cmd.addArg(QString("seek=%1").arg(offset)); - } - return d->runInShellSuccess(cmd, data); -} - -FilePathInfo DockerDevice::filePathInfo(const FilePath &filePath) const -{ - QTC_ASSERT(handlesFile(filePath), return {}); - const RunResult stat = d->runInShell({"stat", {"-L", "-c", "%f %Y %s", filePath.path()}}); - return FileUtils::filePathInfoFromTriple(QString::fromLatin1(stat.stdOut)); -} - Environment DockerDevice::systemEnvironment() const { return d->environment(); @@ -995,28 +836,6 @@ void DockerDevice::aboutToBeRemoved() const detector.undoAutoDetect(id().toString()); } -std::optional<QByteArray> DockerDevicePrivate::fileContents(const FilePath &filePath, - qint64 limit, - qint64 offset) -{ - updateContainerAccess(); - - QStringList args = {"if=" + filePath.path(), "status=none"}; - if (limit > 0 || offset > 0) { - const qint64 gcd = std::gcd(limit, offset); - args += {QString("bs=%1").arg(gcd), - QString("count=%1").arg(limit / gcd), - QString("seek=%1").arg(offset / gcd)}; - } - - const RunResult r = m_shell->runInShell({"dd", args}); - - if (r.exitCode != 0) - return {}; - - return r.stdOut; -} - void DockerDevicePrivate::fetchSystemEnviroment() { updateContainerAccess(); |