Replace readSectors/writeSectors backend functions.

New alternatives use QByteArray to store data and use bytes, not sectors.
This commit is contained in:
Andrius Štikonas 2017-10-26 16:20:21 +01:00
parent 6c7c636572
commit 72dfbe480a
26 changed files with 175 additions and 207 deletions

View File

@ -94,22 +94,21 @@ public:
virtual bool createPartitionTable(Report& report, const PartitionTable& ptable) = 0; virtual bool createPartitionTable(Report& report, const PartitionTable& ptable) = 0;
/** /**
* Read sectors from an opened device into a buffer. * Read data from an opened device into a buffer.
* @param buffer the buffer to write the read data to * @param buffer the buffer to write the read data to
* @param offset offset sector where to start reading on the device * @param offset offset byte where to start reading on the device
* @param numSectors number of sectors to read * @param size the number of bytes to read
* @return true on success * @return true on success
*/ */
virtual bool readSectors(void* buffer, qint64 offset, qint64 numSectors) = 0; virtual bool readData(QByteArray& buffer, qint64 offset, qint64 size) = 0;
/** /**
* Write sectors from a buffer to an exclusively opened device. * Write data from a buffer to an exclusively opened device.
* @param buffer the buffer with the data * @param buffer the buffer with the data
* @param offset offset sector where to start writing to the device * @param offset offset byte where to start writing to the device
* @param numSectors number of sectors to write
* @return true on success * @return true on success
*/ */
virtual bool writeSectors(void* buffer, qint64 offset, qint64 numSectors) = 0; virtual bool writeData(QByteArray& buffer, qint64 offset) = 0;
protected: protected:
void setExclusive(bool b) { void setExclusive(bool b) {

View File

@ -41,13 +41,12 @@ protected:
public: public:
virtual bool open() = 0; virtual bool open() = 0;
virtual qint64 sectorSize() const = 0; virtual bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) = 0;
virtual bool readSectors(void* buffer, qint64 readOffset, qint64 numSectors) = 0;
virtual qint64 length() const = 0; virtual qint64 length() const = 0;
virtual bool overlaps(const CopyTarget& target) const = 0; virtual bool overlaps(const CopyTarget& target) const = 0;
virtual qint64 firstSector() const = 0; virtual qint64 firstByte() const = 0;
virtual qint64 lastSector() const = 0; virtual qint64 lastByte() const = 0;
private: private:
}; };

View File

@ -28,14 +28,14 @@
/** Constructs a CopySource on the given Device /** Constructs a CopySource on the given Device
@param d Device from which to copy @param d Device from which to copy
@param firstsector First sector that will be copied @param firstbyte the first byte that will be copied
@param lastsector Last sector that will be copied @param lastbyte the last byte that will be copied
*/ */
CopySourceDevice::CopySourceDevice(Device& d, qint64 firstsector, qint64 lastsector) : CopySourceDevice::CopySourceDevice(Device& d, qint64 firstbyte, qint64 lastbyte) :
CopySource(), CopySource(),
m_Device(d), m_Device(d),
m_FirstSector(firstsector), m_FirstByte(firstbyte),
m_LastSector(lastsector), m_LastByte(lastbyte),
m_BackendDevice(nullptr) m_BackendDevice(nullptr)
{ {
} }
@ -55,36 +55,28 @@ bool CopySourceDevice::open()
return m_BackendDevice != nullptr; return m_BackendDevice != nullptr;
} }
/** Returns the Device's sector size
@return the sector size
*/
qint64 CopySourceDevice::sectorSize() const
{
return device().logicalSize();
}
/** Returns the length of this CopySource /** Returns the length of this CopySource
@return length of the copy source @return length of the copy source
*/ */
qint64 CopySourceDevice::length() const qint64 CopySourceDevice::length() const
{ {
return lastSector() - firstSector() + 1; return lastByte() - firstByte() + 1;
} }
/** Reads a given number of sectors from the Device into the given buffer. /** Reads a given number of bytes from the Device into the given buffer.
Note that @p readOffset must be greater or equal than zero. Note that @p readOffset must be greater or equal than zero.
@param buffer the buffer to store the read sectors in @param buffer the buffer to store the read bytes in
@param readOffset the offset to begin reading @param readOffset the offset to begin reading
@param numSectors the number of sector to read @param size the number of bytes to read
@return true if successful @return true if successful
*/ */
bool CopySourceDevice::readSectors(void* buffer, qint64 readOffset, qint64 numSectors) bool CopySourceDevice::readData(QByteArray& buffer, qint64 readOffset, qint64 size)
{ {
Q_ASSERT(readOffset >= 0); Q_ASSERT(readOffset >= 0);
return m_BackendDevice->readSectors(buffer, readOffset, numSectors); return m_BackendDevice->readData(buffer, readOffset, size);
} }
/** Checks if this CopySourceDevice overlaps with the given CopyTarget /** Checks if this CopySourceDevice overlaps with the given CopyTarget
@ -100,11 +92,11 @@ bool CopySourceDevice::overlaps(const CopyTarget& target) const
return false; return false;
// overlapping at the front? // overlapping at the front?
if (firstSector() <= t.firstSector() && lastSector() >= t.firstSector()) if (firstByte() <= t.firstByte() && lastByte() >= t.firstByte())
return true; return true;
// overlapping at the back? // overlapping at the back?
if (firstSector() <= t.lastSector() && lastSector() >= t.lastSector()) if (firstByte() <= t.lastByte() && lastByte() >= t.lastByte())
return true; return true;
} catch (...) { } catch (...) {
} }

View File

@ -39,21 +39,20 @@ class LIBKPMCORE_EXPORT CopySourceDevice : public CopySource
Q_DISABLE_COPY(CopySourceDevice) Q_DISABLE_COPY(CopySourceDevice)
public: public:
CopySourceDevice(Device& d, qint64 firstsector, qint64 lastsector); CopySourceDevice(Device& d, qint64 firstbyte, qint64 lastbyte);
~CopySourceDevice(); ~CopySourceDevice();
public: public:
bool open() override; bool open() override;
qint64 sectorSize() const override; bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) override;
bool readSectors(void* buffer, qint64 readOffset, qint64 numSectors) override;
qint64 length() const override; qint64 length() const override;
bool overlaps(const CopyTarget& target) const override; bool overlaps(const CopyTarget& target) const override;
qint64 firstSector() const override { qint64 firstByte() const override {
return m_FirstSector; /**< @return first sector to copying */ return m_FirstByte; /**< @return first byte to copy */
} }
qint64 lastSector() const override { qint64 lastByte() const override {
return m_LastSector; /**< @return last sector to copy */ return m_LastByte; /**< @return last byte to copy */
} }
Device& device() { Device& device() {
@ -65,8 +64,8 @@ public:
protected: protected:
Device& m_Device; Device& m_Device;
const qint64 m_FirstSector; const qint64 m_FirstByte;
const qint64 m_LastSector; const qint64 m_LastByte;
CoreBackendDevice* m_BackendDevice CoreBackendDevice* m_BackendDevice
; ;
}; };

View File

@ -23,12 +23,10 @@
/** Constructs a CopySourceFile from the given @p filename. /** Constructs a CopySourceFile from the given @p filename.
@param filename filename of the file to copy from @param filename filename of the file to copy from
@param sectorsize the sector size to assume for the file, usually the target Device's sector size
*/ */
CopySourceFile::CopySourceFile(const QString& filename, qint64 sectorsize) : CopySourceFile::CopySourceFile(const QString& filename) :
CopySource(), CopySource(),
m_File(filename), m_File(filename)
m_SectorSize(sectorsize)
{ {
} }
@ -40,24 +38,25 @@ bool CopySourceFile::open()
return file().open(QIODevice::ReadOnly); return file().open(QIODevice::ReadOnly);
} }
/** Returns the length of the file in sectors. /** Returns the length of the file in bytes.
@return length of the file in sectors. @return length of the file in bytes.
*/ */
qint64 CopySourceFile::length() const qint64 CopySourceFile::length() const
{ {
return QFileInfo(file()).size() / sectorSize(); return QFileInfo(file()).size();
} }
/** Reads the given number of sectors from the file into the given buffer. /** Reads the given number of bytes from the file into the given buffer.
@param buffer buffer to store the sectors read in @param buffer buffer to store the bytes read in
@param readOffset offset where to begin reading @param readOffset offset where to begin reading
@param numSectors number of sectors to read @param size the number of bytes to read
@return true on success @return true on success
*/ */
bool CopySourceFile::readSectors(void* buffer, qint64 readOffset, qint64 numSectors) bool CopySourceFile::readData(QByteArray& buffer, qint64 readOffset, qint64 size)
{ {
if (!file().seek(readOffset * sectorSize())) if (!file().seek(readOffset))
return false; return false;
return file().read(static_cast<char*>(buffer), numSectors * sectorSize()) == numSectors * sectorSize(); buffer = file().read(size);
return !buffer.isEmpty();
} }

View File

@ -36,23 +36,20 @@ class CopyTarget;
class CopySourceFile : public CopySource class CopySourceFile : public CopySource
{ {
public: public:
CopySourceFile(const QString& filename, qint64 sectorsize); CopySourceFile(const QString& filename);
public: public:
bool open() override; bool open() override;
bool readSectors(void* buffer, qint64 readOffset, qint64 numSectors) override; bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) override;
qint64 length() const override; qint64 length() const override;
qint64 sectorSize() const override {
return m_SectorSize; /**< @return the file's sector size */
}
bool overlaps(const CopyTarget&) const override { bool overlaps(const CopyTarget&) const override {
return false; /**< @return false for file */ return false; /**< @return false for file */
} }
qint64 firstSector() const override { qint64 firstByte() const override {
return 0; /**< @return 0 for file */ return 0; /**< @return 0 for file */
} }
qint64 lastSector() const override { qint64 lastByte() const override {
return length(); /**< @return equal to length for file. @see length() */ return length(); /**< @return equal to length for file. @see length() */
} }
@ -66,7 +63,6 @@ protected:
protected: protected:
QFile m_File; QFile m_File;
qint64 m_SectorSize;
}; };
#endif #endif

View File

@ -20,12 +20,10 @@
/** Constructs a CopySourceShred with the given @p size /** Constructs a CopySourceShred with the given @p size
@param s the size the copy source will (pretend to) have @param s the size the copy source will (pretend to) have
@param sectorsize the sectorsize the copy source will (pretend to) have
*/ */
CopySourceShred::CopySourceShred(qint64 s, qint64 sectorsize, bool randomShred) : CopySourceShred::CopySourceShred(qint64 s, bool randomShred) :
CopySource(), CopySource(),
m_Size(s), m_Size(s),
m_SectorSize(sectorsize),
m_SourceFile(randomShred ? QStringLiteral("/dev/urandom") : QStringLiteral("/dev/zero")) m_SourceFile(randomShred ? QStringLiteral("/dev/urandom") : QStringLiteral("/dev/zero"))
{ {
} }
@ -38,23 +36,24 @@ bool CopySourceShred::open()
return sourceFile().open(QIODevice::ReadOnly); return sourceFile().open(QIODevice::ReadOnly);
} }
/** Returns the length of the source in sectors. /** Returns the length of the source in bytes.
@return length of the source in sectors. @return length of the source in bytes.
*/ */
qint64 CopySourceShred::length() const qint64 CopySourceShred::length() const
{ {
return size() / sectorSize(); return size();
} }
/** Reads the given number of sectors from the source into the given buffer. /** Reads the given number of bytes from the source into the given buffer.
@param buffer buffer to store the sectors read in @param buffer buffer to store the data read in
@param readOffset offset where to begin reading (unused) @param readOffset offset where to begin reading (unused)
@param numSectors number of sectors to read @param size the number of bytes to read
@return true on success @return true on success
*/ */
bool CopySourceShred::readSectors(void* buffer, qint64 readOffset, qint64 numSectors) bool CopySourceShred::readData(QByteArray& buffer, qint64 readOffset, qint64 size)
{ {
Q_UNUSED(readOffset); Q_UNUSED(readOffset);
return sourceFile().read(static_cast<char*>(buffer), numSectors * sectorSize()) == numSectors * sectorSize(); buffer = sourceFile().read(size);
return !buffer.isEmpty();
} }

View File

@ -34,23 +34,20 @@ class CopyTarget;
class CopySourceShred : public CopySource class CopySourceShred : public CopySource
{ {
public: public:
CopySourceShred(qint64 size, qint64 sectorsize, bool randomShred); CopySourceShred(qint64 size, bool randomShred);
public: public:
bool open() override; bool open() override;
bool readSectors(void* buffer, qint64 readOffset, qint64 numSectors) override; bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) override;
qint64 length() const override; qint64 length() const override;
qint64 sectorSize() const override {
return m_SectorSize; /**< @return the file's sector size */
}
bool overlaps(const CopyTarget&) const override { bool overlaps(const CopyTarget&) const override {
return false; /**< @return false for shred source */ return false; /**< @return false for shred source */
} }
qint64 firstSector() const override { qint64 firstByte() const override {
return 0; /**< @return 0 for shred source */ return 0; /**< @return 0 for shred source */
} }
qint64 lastSector() const override { qint64 lastByte() const override {
return length(); /**< @return equal to length for shred source. @see length() */ return length(); /**< @return equal to length for shred source. @see length() */
} }
@ -67,7 +64,6 @@ protected:
private: private:
qint64 m_Size; qint64 m_Size;
qint64 m_SectorSize;
QFile m_SourceFile; QFile m_SourceFile;
}; };

View File

@ -35,27 +35,26 @@ class CopyTarget
Q_DISABLE_COPY(CopyTarget) Q_DISABLE_COPY(CopyTarget)
protected: protected:
CopyTarget() : m_SectorsWritten(0) {} CopyTarget() : m_BytesWritten(0) {}
virtual ~CopyTarget() {} virtual ~CopyTarget() {}
public: public:
virtual bool open() = 0; virtual bool open() = 0;
virtual qint64 sectorSize() const = 0; virtual bool writeData(QByteArray& buffer, qint64 writeOffset) = 0;
virtual bool writeSectors(void* buffer, qint64 writeOffset, qint64 numSectors) = 0; virtual qint64 firstByte() const = 0;
virtual qint64 firstSector() const = 0; virtual qint64 lastByte() const = 0;
virtual qint64 lastSector() const = 0;
qint64 sectorsWritten() const { qint64 bytesWritten() const {
return m_SectorsWritten; return m_BytesWritten;
} }
protected: protected:
void setSectorsWritten(qint64 s) { void setBytesWritten(qint64 s) {
m_SectorsWritten = s; m_BytesWritten = s;
} }
private: private:
qint64 m_SectorsWritten; qint64 m_BytesWritten;
}; };
#endif #endif

View File

@ -26,15 +26,15 @@
/** Constructs a device to copy to. /** Constructs a device to copy to.
@param d the Device to copy to @param d the Device to copy to
@param firstsector the first sector on the Device to write to @param firstbyte the first byte on the Device to write to
@param lastsector the last sector on the Device to write to @param lastbyte the last byte on the Device to write to
*/ */
CopyTargetDevice::CopyTargetDevice(Device& d, qint64 firstsector, qint64 lastsector) : CopyTargetDevice::CopyTargetDevice(Device& d, qint64 firstbyte, qint64 lastbyte) :
CopyTarget(), CopyTarget(),
m_Device(d), m_Device(d),
m_BackendDevice(nullptr), m_BackendDevice(nullptr),
m_FirstSector(firstsector), m_FirstByte(firstbyte),
m_LastSector(lastsector) m_LastByte(lastbyte)
{ {
} }
@ -53,28 +53,21 @@ bool CopyTargetDevice::open()
return m_BackendDevice != nullptr; return m_BackendDevice != nullptr;
} }
/** @return the Device's sector size */ /** Writes the given number of bytes to the Device.
qint64 CopyTargetDevice::sectorSize() const
{
return device().logicalSize();
}
/** Writes the given number of sectors to the Device.
Note that @p writeOffset must be greater or equal than zero. Note that @p writeOffset must be greater or equal than zero.
@param buffer the data to write @param buffer the data to write
@param writeOffset where to start writing on the Device @param writeOffset where to start writing on the Device
@param numSectors the number of sectors in @p buffer
@return true on success @return true on success
*/ */
bool CopyTargetDevice::writeSectors(void* buffer, qint64 writeOffset, qint64 numSectors) bool CopyTargetDevice::writeData(QByteArray& buffer, qint64 writeOffset)
{ {
Q_ASSERT(writeOffset >= 0); Q_ASSERT(writeOffset >= 0);
bool rval = m_BackendDevice->writeSectors(buffer, writeOffset, numSectors); bool rval = m_BackendDevice->writeData(buffer, writeOffset);
if (rval) if (rval)
setSectorsWritten(sectorsWritten() + numSectors); setBytesWritten(bytesWritten() + buffer.size());
return rval; return rval;
} }

View File

@ -41,18 +41,17 @@ class LIBKPMCORE_EXPORT CopyTargetDevice : public CopyTarget
Q_DISABLE_COPY(CopyTargetDevice) Q_DISABLE_COPY(CopyTargetDevice)
public: public:
CopyTargetDevice(Device& d, qint64 firstsector, qint64 lastsector); CopyTargetDevice(Device& d, qint64 firstbyte, qint64 lastbyte);
~CopyTargetDevice(); ~CopyTargetDevice();
public: public:
bool open() override; bool open() override;
qint64 sectorSize() const override; bool writeData(QByteArray& buffer, qint64 writeOffset) override;
bool writeSectors(void* buffer, qint64 writeOffset, qint64 numSectors) override; qint64 firstByte() const override {
qint64 firstSector() const override { return m_FirstByte; /**< @return the first byte to write to */
return m_FirstSector; /**< @return the first sector to write to */
} }
qint64 lastSector() const override { qint64 lastByte() const override {
return m_LastSector; /**< @return the last sector to write to */ return m_LastByte; /**< @return the last byte to write to */
} }
Device& device() { Device& device() {
@ -65,8 +64,8 @@ public:
protected: protected:
Device& m_Device; Device& m_Device;
CoreBackendDevice* m_BackendDevice; CoreBackendDevice* m_BackendDevice;
const qint64 m_FirstSector; const qint64 m_FirstByte;
const qint64 m_LastSector; const qint64 m_LastByte;
}; };
#endif #endif

View File

@ -19,12 +19,10 @@
/** Constructs a file to write to. /** Constructs a file to write to.
@param filename name of the file to write to @param filename name of the file to write to
@param sectorsize the "sector size" of the file to write to, usually the sector size of the CopySourceDevice
*/ */
CopyTargetFile::CopyTargetFile(const QString& filename, qint64 sectorsize) : CopyTargetFile::CopyTargetFile(const QString& filename) :
CopyTarget(), CopyTarget(),
m_File(filename), m_File(filename)
m_SectorSize(sectorsize)
{ {
} }
@ -36,21 +34,20 @@ bool CopyTargetFile::open()
return file().open(QIODevice::WriteOnly | QIODevice::Truncate); return file().open(QIODevice::WriteOnly | QIODevice::Truncate);
} }
/** Writes the given number of sectors from the given buffer to the file. /** Writes the given number of bytes from the given buffer to the file.
@param buffer the data to write @param buffer the data to write
@param writeOffset where in the file to start writing @param writeOffset where in the file to start writing
@param numSectors the number of sectors to write
@return true on success @return true on success
*/ */
bool CopyTargetFile::writeSectors(void* buffer, qint64 writeOffset, qint64 numSectors) bool CopyTargetFile::writeData(QByteArray& buffer, qint64 writeOffset)
{ {
if (!file().seek(writeOffset * sectorSize())) if (!file().seek(writeOffset))
return false; return false;
bool rval = file().write(static_cast<char*>(buffer), numSectors * sectorSize()) == numSectors * sectorSize(); bool rval = file().write(buffer) == buffer.size();
if (rval) if (rval)
setSectorsWritten(sectorsWritten() + numSectors); setBytesWritten(bytesWritten() + buffer.size());
return rval; return rval;
} }

View File

@ -36,20 +36,17 @@ class QString;
class CopyTargetFile : public CopyTarget class CopyTargetFile : public CopyTarget
{ {
public: public:
CopyTargetFile(const QString& filename, qint64 sectorsize); CopyTargetFile(const QString& filename);
public: public:
bool open() override; bool open() override;
bool writeSectors(void* buffer, qint64 writeOffset, qint64 numSectors) override; bool writeData(QByteArray& buffer, qint64 writeOffset) override;
qint64 sectorSize() const override { qint64 firstByte() const override {
return m_SectorSize; /**< @return the file's sector size */
}
qint64 firstSector() const override {
return 0; /**< @return always 0 for a file */ return 0; /**< @return always 0 for a file */
} }
qint64 lastSector() const override { qint64 lastByte() const override {
return sectorsWritten(); /**< @return the number of sectors written so far */ return bytesWritten(); /**< @return the number of bytes written so far */
} }
protected: protected:
@ -62,7 +59,6 @@ protected:
protected: protected:
QFile m_File; QFile m_File;
qint64 m_SectorSize;
}; };
#endif #endif

View File

@ -131,6 +131,12 @@ public:
qint64 lastSector() const { qint64 lastSector() const {
return m_LastSector; /**< @return the Partition's last sector on the Device */ return m_LastSector; /**< @return the Partition's last sector on the Device */
} }
qint64 firstByte() const {
return firstSector() * sectorSize(); /**< @return the Partition's first byte on the Device */
}
qint64 lastByte() const {
return firstByte() + length() * sectorSize() - 1; /**< @return the Partition's last byte on the Device */
}
qint64 sectorsUsed() const; qint64 sectorsUsed() const;
qint64 sectorSize() const { qint64 sectorSize() const {
return m_SectorSize; /**< @return the sector size on the Partition's Device */ return m_SectorSize; /**< @return the sector size on the Partition's Device */

View File

@ -235,6 +235,12 @@ public:
qint64 length() const { qint64 length() const {
return lastSector() - firstSector() + 1; /**< @return the FileSystem's length */ return lastSector() - firstSector() + 1; /**< @return the FileSystem's length */
} }
qint64 firstByte() const {
return firstSector() * sectorSize(); /**< @return the FileSystem's first byte */
}
qint64 lastByte() const {
return firstByte() + length() * sectorSize() - 1; /**< @return the FileSystem's last byte */
}
void setFirstSector(qint64 s) { void setFirstSector(qint64 s) {
m_FirstSector = s; /**< @param s the new first sector */ m_FirstSector = s; /**< @param s the new first sector */

View File

@ -56,8 +56,8 @@ bool BackupFileSystemJob::run(Report& parent)
if (sourcePartition().fileSystem().supportBackup() == FileSystem::cmdSupportFileSystem) if (sourcePartition().fileSystem().supportBackup() == FileSystem::cmdSupportFileSystem)
rval = sourcePartition().fileSystem().backup(*report, sourceDevice(), sourcePartition().deviceNode(), fileName()); rval = sourcePartition().fileSystem().backup(*report, sourceDevice(), sourcePartition().deviceNode(), fileName());
else if (sourcePartition().fileSystem().supportBackup() == FileSystem::cmdSupportCore) { else if (sourcePartition().fileSystem().supportBackup() == FileSystem::cmdSupportCore) {
CopySourceDevice copySource(sourceDevice(), sourcePartition().fileSystem().firstSector(), sourcePartition().fileSystem().lastSector()); CopySourceDevice copySource(sourceDevice(), sourcePartition().fileSystem().firstByte(), sourcePartition().fileSystem().lastByte());
CopyTargetFile copyTarget(fileName(), sourceDevice().logicalSize()); CopyTargetFile copyTarget(fileName());
if (!copySource.open()) if (!copySource.open())
report->line() << xi18nc("@info:progress", "Could not open file system on source partition <filename>%1</filename> for backup.", sourcePartition().deviceNode()); report->line() << xi18nc("@info:progress", "Could not open file system on source partition <filename>%1</filename> for backup.", sourcePartition().deviceNode());

View File

@ -60,8 +60,8 @@ bool CopyFileSystemJob::run(Report& parent)
else if (sourcePartition().fileSystem().supportCopy() == FileSystem::cmdSupportFileSystem) else if (sourcePartition().fileSystem().supportCopy() == FileSystem::cmdSupportFileSystem)
rval = sourcePartition().fileSystem().copy(*report, targetPartition().deviceNode(), sourcePartition().deviceNode()); rval = sourcePartition().fileSystem().copy(*report, targetPartition().deviceNode(), sourcePartition().deviceNode());
else if (sourcePartition().fileSystem().supportCopy() == FileSystem::cmdSupportCore) { else if (sourcePartition().fileSystem().supportCopy() == FileSystem::cmdSupportCore) {
CopySourceDevice copySource(sourceDevice(), sourcePartition().fileSystem().firstSector(), sourcePartition().fileSystem().lastSector()); CopySourceDevice copySource(sourceDevice(), sourcePartition().fileSystem().firstByte(), sourcePartition().fileSystem().lastByte());
CopyTargetDevice copyTarget(targetDevice(), targetPartition().fileSystem().firstSector(), targetPartition().fileSystem().lastSector()); CopyTargetDevice copyTarget(targetDevice(), targetPartition().fileSystem().firstByte(), targetPartition().fileSystem().lastByte());
if (!copySource.open()) if (!copySource.open())
report->line() << xi18nc("@info:progress", "Could not open file system on source partition <filename>%1</filename> for copying.", sourcePartition().deviceNode()); report->line() << xi18nc("@info:progress", "Could not open file system on source partition <filename>%1</filename> for copying.", sourcePartition().deviceNode());

View File

@ -26,7 +26,6 @@
#include "util/report.h" #include "util/report.h"
#include <QDebug>
#include <QIcon> #include <QIcon>
#include <QTime> #include <QTime>
@ -39,78 +38,68 @@ Job::Job() :
bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source) bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source)
{ {
/** @todo copyBlocks() assumes that source.sectorSize() == target.sectorSize(). */
if (source.sectorSize() != target.sectorSize()) {
report.line() << xi18nc("@info:progress", "The logical sector sizes in the source and target for copying are not the same. This is currently unsupported.");
return false;
}
bool rval = true; bool rval = true;
const qint64 blockSize = 16065 * 8; // number of sectors per block to copy const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy
const qint64 blocksToCopy = source.length() / blockSize; const qint64 blocksToCopy = source.length() / blockSize;
qint64 readOffset = source.firstSector(); qint64 readOffset = source.firstByte();
qint64 writeOffset = target.firstSector(); qint64 writeOffset = target.firstByte();
qint32 copyDir = 1; qint32 copyDirection = 1;
if (target.firstSector() > source.firstSector()) { if (target.firstByte() > source.firstByte()) {
readOffset = source.firstSector() + source.length() - blockSize; readOffset = source.firstByte() + source.length() - blockSize;
writeOffset = target.firstSector() + source.length() - blockSize; writeOffset = target.firstByte() + source.length() - blockSize;
copyDir = -1; copyDirection = -1;
} }
report.line() << xi18nc("@info:progress", "Copying %1 blocks (%2 sectors) from %3 to %4, direction: %5.", blocksToCopy, source.length(), readOffset, writeOffset, copyDir); report.line() << xi18nc("@info:progress", "Copying %1 blocks (%2 bytes) from %3 to %4, direction: %5.", blocksToCopy, source.length(), readOffset, writeOffset, copyDirection);
qint64 blocksCopied = 0; qint64 blocksCopied = 0;
void* buffer = malloc(blockSize * source.sectorSize()); QByteArray buffer;
int percent = 0; int percent = 0;
QTime t; QTime t;
t.start(); t.start();
while (blocksCopied < blocksToCopy) { while (blocksCopied < blocksToCopy) {
if (!(rval = source.readSectors(buffer, readOffset + blockSize * blocksCopied * copyDir, blockSize))) if (!(rval = source.readData(buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize)))
break; break;
if (!(rval = target.writeSectors(buffer, writeOffset + blockSize * blocksCopied * copyDir, blockSize))) if (!(rval = target.writeData(buffer, writeOffset + blockSize * blocksCopied * copyDirection)))
break; break;
if (++blocksCopied * 100 / blocksToCopy != percent) { if (++blocksCopied * 100 / blocksToCopy != percent) {
percent = blocksCopied * 100 / blocksToCopy; percent = blocksCopied * 100 / blocksToCopy;
if (percent % 5 == 0 && t.elapsed() > 1000) { if (percent % 5 == 0 && t.elapsed() > 1000) {
const qint64 mibsPerSec = (blocksCopied * blockSize * source.sectorSize() / 1024 / 1024) / (t.elapsed() / 1000); const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (t.elapsed() / 1000);
const qint64 estSecsLeft = (100 - percent) * t.elapsed() / percent / 1000; const qint64 estSecsLeft = (100 - percent) * t.elapsed() / percent / 1000;
report.line() << xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString()); report.line() << xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString());
} }
emit progress(percent); emit progress(percent);
} }
} }
const qint64 lastBlock = source.length() % blockSize; const qint64 lastBlock = source.length() % blockSize;
// copy the remainder // copy the remainder
if (rval && lastBlock > 0) { if (rval && lastBlock > 0) {
Q_ASSERT(lastBlock < blockSize); Q_ASSERT(lastBlock < blockSize);
const qint64 lastBlockReadOffset = copyDir > 0 ? readOffset + blockSize * blocksCopied : source.firstSector(); const qint64 lastBlockReadOffset = copyDirection > 0 ? readOffset + blockSize * blocksCopied : source.firstByte();
const qint64 lastBlockWriteOffset = copyDir > 0 ? writeOffset + blockSize * blocksCopied : target.firstSector(); const qint64 lastBlockWriteOffset = copyDirection > 0 ? writeOffset + blockSize * blocksCopied : target.firstByte();
report.line() << xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset); report.line() << xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset);
rval = source.readSectors(buffer, lastBlockReadOffset, lastBlock); rval = source.readData(buffer, lastBlockReadOffset, lastBlock);
if (rval) if (rval)
rval = target.writeSectors(buffer, lastBlockWriteOffset, lastBlock); rval = target.writeData(buffer, lastBlockWriteOffset);
if (rval) if (rval)
emit progress(100); emit progress(100);
} }
free(buffer);
report.line() << xi18ncp("@info:progress argument 2 is a string such as 7 sectors (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 sector", "%1 sectors", target.sectorsWritten())); report.line() << xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", target.bytesWritten()));
return rval; return rval;
} }
@ -127,31 +116,31 @@ bool Job::rollbackCopyBlocks(Report& report, CopyTarget& origTarget, CopySource&
CopyTargetDevice& ctd = dynamic_cast<CopyTargetDevice&>(origTarget); CopyTargetDevice& ctd = dynamic_cast<CopyTargetDevice&>(origTarget);
// default: use values as if we were copying from front to back. // default: use values as if we were copying from front to back.
qint64 undoSourceFirstSector = origTarget.firstSector(); qint64 undoSourceFirstByte = origTarget.firstByte();
qint64 undoSourceLastSector = origTarget.firstSector() + origTarget.sectorsWritten() - 1; qint64 undoSourceLastByte = origTarget.firstByte() + origTarget.bytesWritten() - 1;
qint64 undoTargetFirstSector = origSource.firstSector(); qint64 undoTargetFirstByte = origSource.firstByte();
qint64 undoTargetLastSector = origSource.firstSector() + origTarget.sectorsWritten() - 1; qint64 undoTargetLastByte = origSource.firstByte() + origTarget.bytesWritten() - 1;
if (origTarget.firstSector() > origSource.firstSector()) { if (origTarget.firstByte() > origSource.firstByte()) {
// we were copying from back to front // we were copying from back to front
undoSourceFirstSector = origTarget.firstSector() + origSource.length() - origTarget.sectorsWritten(); undoSourceFirstByte = origTarget.firstByte() + origSource.length() - origTarget.bytesWritten();
undoSourceLastSector = origTarget.firstSector() + origSource.length() - 1; undoSourceLastByte = origTarget.firstByte() + origSource.length() - 1;
undoTargetFirstSector = origSource.lastSector() - origTarget.sectorsWritten() + 1; undoTargetFirstByte = origSource.lastByte() - origTarget.bytesWritten() + 1;
undoTargetLastSector = origSource.lastSector(); undoTargetLastByte = origSource.lastByte();
} }
report.line() << xi18nc("@info:progress", "Rollback from: First sector: %1, last sector: %2.", undoSourceFirstSector, undoSourceLastSector); report.line() << xi18nc("@info:progress", "Rollback from: First byte: %1, last byte: %2.", undoSourceFirstByte, undoSourceLastByte);
report.line() << xi18nc("@info:progress", "Rollback to: First sector: %1, last sector: %2.", undoTargetFirstSector, undoTargetLastSector); report.line() << xi18nc("@info:progress", "Rollback to: First byte: %1, last byte: %2.", undoTargetFirstByte, undoTargetLastByte);
CopySourceDevice undoSource(ctd.device(), undoSourceFirstSector, undoSourceLastSector); CopySourceDevice undoSource(ctd.device(), undoSourceFirstByte, undoSourceLastByte);
if (!undoSource.open()) { if (!undoSource.open()) {
report.line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to rollback copying.", ctd.device().deviceNode()); report.line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to rollback copying.", ctd.device().deviceNode());
return false; return false;
} }
CopyTargetDevice undoTarget(csd.device(), undoTargetFirstSector, undoTargetLastSector); CopyTargetDevice undoTarget(csd.device(), undoTargetFirstByte, undoTargetLastByte);
if (!undoTarget.open()) { if (!undoTarget.open()) {
report.line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to rollback copying.", csd.device().deviceNode()); report.line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> to rollback copying.", csd.device().deviceNode());
return false; return false;

View File

@ -55,8 +55,9 @@ bool MoveFileSystemJob::run(Report& parent)
// say we're finished: The CopyTargetDevice dtor asks the backend to close the device // say we're finished: The CopyTargetDevice dtor asks the backend to close the device
// and that may take a while. // and that may take a while.
{ {
CopySourceDevice moveSource(device(), partition().fileSystem().firstSector(), partition().fileSystem().lastSector()); qint64 length = partition().fileSystem().lastByte() - partition().fileSystem().firstByte();
CopyTargetDevice moveTarget(device(), newStart(), newStart() + partition().fileSystem().length()); CopySourceDevice moveSource(device(), partition().fileSystem().firstByte(), partition().fileSystem().lastByte());
CopyTargetDevice moveTarget(device(), newStart() * device().logicalSize(), newStart() * device().logicalSize() + length);
if (!moveSource.open()) if (!moveSource.open())
report->line() << xi18nc("@info:progress", "Could not open file system on partition <filename>%1</filename> for moving.", partition().deviceNode()); report->line() << xi18nc("@info:progress", "Could not open file system on partition <filename>%1</filename> for moving.", partition().deviceNode());

View File

@ -66,8 +66,8 @@ bool RestoreFileSystemJob::run(Report& parent)
// Again, a scope for copyTarget and copySource. See MoveFileSystemJob::run() // Again, a scope for copyTarget and copySource. See MoveFileSystemJob::run()
{ {
// FileSystems are restored to _partitions_, so don't use first and last sector of file system here // FileSystems are restored to _partitions_, so don't use first and last sector of file system here
CopyTargetDevice copyTarget(targetDevice(), targetPartition().firstSector(), targetPartition().lastSector()); CopyTargetDevice copyTarget(targetDevice(), targetPartition().firstByte(), targetPartition().lastByte());
CopySourceFile copySource(fileName(), copyTarget.sectorSize()); CopySourceFile copySource(fileName());
if (!copySource.open()) if (!copySource.open())
report->line() << xi18nc("@info:progress", "Could not open backup file <filename>%1</filename> to restore from.", fileName()); report->line() << xi18nc("@info:progress", "Could not open backup file <filename>%1</filename> to restore from.", fileName());

View File

@ -64,8 +64,8 @@ bool ShredFileSystemJob::run(Report& parent)
// Again, a scope for copyTarget and copySource. See MoveFileSystemJob::run() // Again, a scope for copyTarget and copySource. See MoveFileSystemJob::run()
{ {
CopyTargetDevice copyTarget(device(), partition().fileSystem().firstSector(), partition().fileSystem().lastSector()); CopyTargetDevice copyTarget(device(), partition().fileSystem().firstByte(), partition().fileSystem().lastByte());
CopySourceShred copySource(partition().capacity(), copyTarget.sectorSize(), m_RandomShred); CopySourceShred copySource(partition().capacity(), m_RandomShred);
if (!copySource.open()) if (!copySource.open())
report->line() << xi18nc("@info:progress", "Could not open random data source to overwrite file system."); report->line() << xi18nc("@info:progress", "Could not open random data source to overwrite file system.");

View File

@ -94,7 +94,7 @@ protected:
virtual ~Operation(); virtual ~Operation();
Q_SIGNALS: Q_SIGNALS:
int progress(int); void progress(int);
void jobStarted(Job*, Operation*); void jobStarted(Job*, Operation*);
void jobFinished(Job*, Operation*); void jobFinished(Job*, Operation*);

View File

@ -67,11 +67,11 @@ bool DummyDevice::createPartitionTable(Report& report, const PartitionTable& pta
return true; return true;
} }
bool DummyDevice::readSectors(void* buffer, qint64 offset, qint64 numSectors) bool DummyDevice::readData(QByteArray& buffer, qint64 offset, qint64 size)
{ {
Q_UNUSED(buffer); Q_UNUSED(buffer);
Q_UNUSED(offset); Q_UNUSED(offset);
Q_UNUSED(numSectors); Q_UNUSED(size);
if (!isExclusive()) if (!isExclusive())
return false; return false;
@ -79,11 +79,10 @@ bool DummyDevice::readSectors(void* buffer, qint64 offset, qint64 numSectors)
return true; return true;
} }
bool DummyDevice::writeSectors(void* buffer, qint64 offset, qint64 numSectors) bool DummyDevice::writeData(QByteArray& buffer, qint64 offset)
{ {
Q_UNUSED(buffer); Q_UNUSED(buffer);
Q_UNUSED(offset); Q_UNUSED(offset);
Q_UNUSED(numSectors);
if (!isExclusive()) if (!isExclusive())
return false; return false;

View File

@ -45,8 +45,8 @@ public:
bool createPartitionTable(Report& report, const PartitionTable& ptable) override; bool createPartitionTable(Report& report, const PartitionTable& ptable) override;
bool readSectors(void* buffer, qint64 offset, qint64 numSectors) override; bool readData(QByteArray& buffer, qint64 offset, qint64 size) override;
bool writeSectors(void* buffer, qint64 offset, qint64 numSectors) override; bool writeData(QByteArray& buffer, qint64 offset) override;
}; };
#endif #endif

View File

@ -111,18 +111,22 @@ bool LibPartedDevice::createPartitionTable(Report& report, const PartitionTable&
return LibPartedPartitionTable::commit(disk); return LibPartedPartitionTable::commit(disk);
} }
bool LibPartedDevice::readSectors(void* buffer, qint64 offset, qint64 numSectors) bool LibPartedDevice::readData(QByteArray& buffer, qint64 offset, qint64 size)
{
if (!isExclusive())
return false;
void *data = malloc(size);
bool rval = ped_device_read(pedDevice(), data, offset / pedDevice()->sector_size, size / pedDevice()->sector_size);
buffer = QByteArray(static_cast<char*>(data), size);
free(data);
return rval;
}
bool LibPartedDevice::writeData(QByteArray& buffer, qint64 offset)
{ {
if (!isExclusive()) if (!isExclusive())
return false; return false;
return ped_device_read(pedDevice(), buffer, offset, numSectors); return ped_device_write(pedDevice(), static_cast<const void *>(buffer.constData()), offset / pedDevice()->sector_size, buffer.size() / pedDevice()->sector_size);
}
bool LibPartedDevice::writeSectors(void* buffer, qint64 offset, qint64 numSectors)
{
if (!isExclusive())
return false;
return ped_device_write(pedDevice(), buffer, offset, numSectors);
} }

View File

@ -47,8 +47,8 @@ public:
bool createPartitionTable(Report& report, const PartitionTable& ptable) override; bool createPartitionTable(Report& report, const PartitionTable& ptable) override;
bool readSectors(void* buffer, qint64 offset, qint64 numSectors) override; bool readData(QByteArray& buffer, qint64 offset, qint64 size) override;
bool writeSectors(void* buffer, qint64 offset, qint64 numSectors) override; bool writeData(QByteArray& buffer, qint64 offset) override;
protected: protected:
PedDevice* pedDevice() { PedDevice* pedDevice() {