Utils: Add an offset parameter to the content writing FilePath function

Use QFile::seek to implement locally and a dd seek based poor man's
implementation on RL and docker.

Change-Id: I241d1c34c00e991845d132ad8edefa1377ba1311
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
hjk
2022-10-10 17:11:51 +02:00
parent 0c2a86b63f
commit 2e38cb6848
12 changed files with 65 additions and 27 deletions

View File

@@ -586,28 +586,32 @@ void FilePath::asyncFileContents(const Continuation<const std::optional<QByteArr
cont(fileContents(maxSize, offset));
}
bool FilePath::writeFileContents(const QByteArray &data) const
bool FilePath::writeFileContents(const QByteArray &data, qint64 offset) const
{
if (needsDevice()) {
QTC_ASSERT(s_deviceHooks.writeFileContents, return {});
return s_deviceHooks.writeFileContents(*this, data);
return s_deviceHooks.writeFileContents(*this, data, offset);
}
QFile file(path());
QTC_ASSERT(file.open(QFile::WriteOnly | QFile::Truncate), return false);
if (offset != 0)
file.seek(offset);
qint64 res = file.write(data);
return res == data.size();
}
void FilePath::asyncWriteFileContents(const Continuation<bool> &cont, const QByteArray &data) const
void FilePath::asyncWriteFileContents(const Continuation<bool> &cont,
const QByteArray &data,
qint64 offset) const
{
if (needsDevice()) {
QTC_ASSERT(s_deviceHooks.asyncWriteFileContents, return);
s_deviceHooks.asyncWriteFileContents(cont, *this, data);
s_deviceHooks.asyncWriteFileContents(cont, *this, data, offset);
return;
}
cont(writeFileContents(data));
cont(writeFileContents(data, offset));
}
bool FilePath::needsDevice() const

View File

@@ -118,7 +118,7 @@ public:
FilePaths dirEntries(const FileFilter &filter, QDir::SortFlags sort = QDir::NoSort) const;
FilePaths dirEntries(QDir::Filters filters) const;
std::optional<QByteArray> fileContents(qint64 maxSize = -1, qint64 offset = 0) const;
bool writeFileContents(const QByteArray &data) const;
bool writeFileContents(const QByteArray &data, qint64 offset = 0) const;
bool operator==(const FilePath &other) const;
bool operator!=(const FilePath &other) const;
@@ -180,7 +180,9 @@ public:
void asyncFileContents(const Continuation<const std::optional<QByteArray> &> &cont,
qint64 maxSize = -1,
qint64 offset = 0) const;
void asyncWriteFileContents(const Continuation<bool> &cont, const QByteArray &data) const;
void asyncWriteFileContents(const Continuation<bool> &cont,
const QByteArray &data,
qint64 offset = 0) const;
// Prefer not to use
// Using needsDevice() in "user" code is likely to result in code that
@@ -259,7 +261,7 @@ public:
const std::function<bool(const FilePath &)> &, // Abort on 'false' return.
const FileFilter &)> iterateDirectory;
std::function<std::optional<QByteArray>(const FilePath &, qint64, qint64)> fileContents;
std::function<bool(const FilePath &, const QByteArray &)> writeFileContents;
std::function<bool(const FilePath &, const QByteArray &, qint64)> writeFileContents;
std::function<QDateTime(const FilePath &)> lastModified;
std::function<QFile::Permissions(const FilePath &)> permissions;
std::function<bool(const FilePath &, QFile::Permissions)> setPermissions;
@@ -276,7 +278,8 @@ public:
std::function<void(
const Continuation<const std::optional<QByteArray> &> &, const FilePath &, qint64, qint64)>
asyncFileContents;
std::function<void(const Continuation<bool> &, const FilePath &, const QByteArray &)> asyncWriteFileContents;
std::function<void(const Continuation<bool> &, const FilePath &, const QByteArray &, qint64)>
asyncWriteFileContents;
std::function<bool(const FilePath &, const FilePath &)> ensureReachable;
};

View File

@@ -910,10 +910,17 @@ std::optional<QByteArray> DockerDevice::fileContents(const FilePath &filePath,
return d->fileContents(filePath, limit, offset);
}
bool DockerDevice::writeFileContents(const FilePath &filePath, const QByteArray &data) const
bool DockerDevice::writeFileContents(const FilePath &filePath,
const QByteArray &data,
qint64 offset) const
{
QTC_ASSERT(handlesFile(filePath), return {});
return d->runInShellSuccess({"dd", {"of=" + filePath.path()}}, data);
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);
}
Environment DockerDevice::systemEnvironment() const

View File

@@ -105,7 +105,9 @@ public:
std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit,
qint64 offset) const override;
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
bool writeFileContents(const Utils::FilePath &filePath,
const QByteArray &data,
qint64 offset) const override;
QDateTime lastModified(const Utils::FilePath &filePath) const override;
qint64 fileSize(const Utils::FilePath &filePath) const override;
QFileDevice::Permissions permissions(const Utils::FilePath &filePath) const override;

View File

@@ -278,10 +278,12 @@ std::optional<QByteArray> DesktopDevice::fileContents(const FilePath &filePath,
return filePath.fileContents(limit, offset);
}
bool DesktopDevice::writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const
bool DesktopDevice::writeFileContents(const FilePath &filePath,
const QByteArray &data,
qint64 offset) const
{
QTC_ASSERT(handlesFile(filePath), return {});
return filePath.writeFileContents(data);
return filePath.writeFileContents(data, offset);
}
} // namespace ProjectExplorer

View File

@@ -56,7 +56,9 @@ public:
std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit,
qint64 offset) const override;
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
bool writeFileContents(const Utils::FilePath &filePath,
const QByteArray &data,
qint64 offset) const override;
qint64 fileSize(const Utils::FilePath &filePath) const override;
QFile::Permissions permissions(const Utils::FilePath &filePath) const override;
bool setPermissions(const Utils::FilePath &filePath, QFile::Permissions) const override;

View File

@@ -544,10 +544,12 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
device->asyncFileContents(cont, filePath, maxSize, offset);
};
deviceHooks.writeFileContents = [](const FilePath &filePath, const QByteArray &data) {
deviceHooks.writeFileContents = [](const FilePath &filePath,
const QByteArray &data,
qint64 offset) {
auto device = DeviceManager::deviceForPath(filePath);
QTC_ASSERT(device, return false);
return device->writeFileContents(filePath, data);
return device->writeFileContents(filePath, data, offset);
};
deviceHooks.lastModified = [](const FilePath &filePath) {

View File

@@ -384,19 +384,21 @@ void IDevice::asyncFileContents(const Continuation<std::optional<QByteArray>> &c
cont(fileContents(filePath, limit, offset));
}
bool IDevice::writeFileContents(const FilePath &filePath, const QByteArray &data) const
bool IDevice::writeFileContents(const FilePath &filePath, const QByteArray &data, qint64 offset) const
{
Q_UNUSED(filePath);
Q_UNUSED(data);
Q_UNUSED(offset);
QTC_CHECK(false);
return {};
}
void IDevice::asyncWriteFileContents(const Continuation<bool> &cont,
const FilePath &filePath,
const QByteArray &data) const
const QByteArray &data,
qint64 offset) const
{
cont(writeFileContents(filePath, data));
cont(writeFileContents(filePath, data, offset));
}
QDateTime IDevice::lastModified(const FilePath &filePath) const

View File

@@ -243,7 +243,9 @@ public:
virtual std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit,
qint64 offset) const;
virtual bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const;
virtual bool writeFileContents(const Utils::FilePath &filePath,
const QByteArray &data,
qint64 offset) const;
virtual QDateTime lastModified(const Utils::FilePath &filePath) const;
virtual QFile::Permissions permissions(const Utils::FilePath &filePath) const;
virtual bool setPermissions(const Utils::FilePath &filePath, QFile::Permissions) const;
@@ -262,7 +264,8 @@ public:
qint64 offset) const;
virtual void asyncWriteFileContents(const Continuation<bool> &cont,
const Utils::FilePath &filePath,
const QByteArray &data) const;
const QByteArray &data,
qint64 offset) const;
virtual bool ensureReachable(const Utils::FilePath &other) const;

View File

@@ -1318,10 +1318,17 @@ std::optional<QByteArray> LinuxDevice::fileContents(const FilePath &filePath,
return result.stdOut;
}
bool LinuxDevice::writeFileContents(const FilePath &filePath, const QByteArray &data) const
bool LinuxDevice::writeFileContents(const FilePath &filePath,
const QByteArray &data,
qint64 offset) const
{
QTC_ASSERT(handlesFile(filePath), return {});
return d->runInShellSuccess({"dd", {"of=" + filePath.path()}}, data);
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);
}
static FilePaths dirsToCreate(const FilesToTransfer &files)

View File

@@ -58,7 +58,9 @@ public:
std::optional<QByteArray> fileContents(const Utils::FilePath &filePath,
qint64 limit,
qint64 offset) const override;
bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override;
bool writeFileContents(const Utils::FilePath &filePath,
const QByteArray &data,
qint64 offset) const override;
QDateTime lastModified(const Utils::FilePath &filePath) const override;
Utils::ProcessInterface *createProcessInterface() const override;
ProjectExplorer::FileTransferInterface *createFileTransferInterface(

View File

@@ -134,8 +134,10 @@ void tst_fsengine::initTestCase()
qint64 offset) {
return FilePath::fromString(filePath.path()).asyncFileContents(cont, maxSize, offset);
};
deviceHooks.writeFileContents = [](const FilePath &filePath, const QByteArray &data) {
return FilePath::fromString(filePath.path()).writeFileContents(data);
deviceHooks.writeFileContents = [](const FilePath &filePath,
const QByteArray &data,
qint64 offset) {
return FilePath::fromString(filePath.path()).writeFileContents(data, offset);
};
deviceHooks.lastModified = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).lastModified();