diff options
-rw-r--r-- | src/libs/installer/binarycontent.cpp | 242 | ||||
-rw-r--r-- | src/libs/installer/binarycontent.h | 17 | ||||
-rw-r--r-- | src/libs/installer/binarylayout.cpp | 110 | ||||
-rw-r--r-- | src/libs/installer/binarylayout.h | 70 | ||||
-rw-r--r-- | src/libs/installer/installer.pro | 6 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore_p.cpp | 11 | ||||
-rw-r--r-- | tests/auto/installer/binaryformat/tst_binaryformat.cpp | 107 | ||||
-rw-r--r-- | tools/devtool/binaryreplace.cpp | 3 | ||||
-rw-r--r-- | tools/devtool/binaryreplace.h | 2 | ||||
-rw-r--r-- | tools/devtool/main.cpp | 104 |
10 files changed, 356 insertions, 316 deletions
diff --git a/src/libs/installer/binarycontent.cpp b/src/libs/installer/binarycontent.cpp index 25032177b..7ba285f3a 100644 --- a/src/libs/installer/binarycontent.cpp +++ b/src/libs/installer/binarycontent.cpp @@ -41,6 +41,7 @@ #include "binarycontent.h" +#include "binarylayout.h" #include "errors.h" #include "fileio.h" #include "fileutils.h" @@ -93,214 +94,107 @@ qint64 BinaryContent::findMagicCookie(QFile *in, quint64 magicCookie) return -1; // never reached } -/*! -* \class QInstaller::BinaryContent -* -* BinaryContent handles binary information embedded into executables. -* Qt resources as well as resource collections can be stored. -* -* Explanation of the binary blob at the end of the installer or separate data file: -* -* \verbatim -* -* Meta data entry [1 ... n] -* [Format] -* Plain data (QResource) -* [Format] -* ---------------------------------------------------------- -* Operation count (qint64) -* Operation entry [1 ... n] -* [Format] -* Name (qint64, QString) -* XML (qint64, QString) -* [Format] -* Operation count (qint64) -* ---------------------------------------------------------- -* Component count -* Component data entry [1 ... n] -* [Format] -* Archive count (qint64), -* Name entry [1 ... n] -* [Format] -* Name (qint64, QByteArray), -* Offset (qint64), -* Length (qint64), -* [Format] -* Archive data entry [1 ... n] -* [Format] -* Plain data -* [Format] -* [Format] -* ---------------------------------------------------------- -* Component count (qint64) -* Component index entry [1 ... n] -* [Format] -* Name (qint64, QByteArray) -* Offset (qint64) -* Length (qint64) -* [Format] -* Component count (qint64) -* ---------------------------------------------------------- -* Component index block [Offset (qint64)] -* Component index block [Length (qint64)] -* ---------------------------------------------------------- -* Resource segments [1 ... n] -* [Format] -* Offset (qint64) -* Length (qint64) -* [Format] -* ---------------------------------------------------------- -* Operations information block [Offset (qint64)] -* Operations information block [Length (qint64)] -* ---------------------------------------------------------- -* Meta data count (qint64) -* ---------------------------------------------------------- -* Binary content size [Including Marker and Cookie (qint64)] -* ---------------------------------------------------------- -* Magic marker (qint64) -* Magic cookie (qint64) - -* \endverbatim -*/ - -/* static */ BinaryLayout BinaryContent::binaryLayout(QFile *file, quint64 magicCookie) { - const qint64 cookiePos = BinaryContent::findMagicCookie(file, magicCookie); - const qint64 indexSize = 5 * sizeof(qint64); - if (!file->seek(cookiePos - indexSize)) { - throw Error(QCoreApplication::translate("BinaryContent", - "Could not seek to binary layout section.")); - } - BinaryLayout layout; - layout.operationsStart = QInstaller::retrieveInt64(file); - layout.operationsEnd = QInstaller::retrieveInt64(file); - layout.resourceCount = QInstaller::retrieveInt64(file); - layout.dataBlockSize = QInstaller::retrieveInt64(file); - layout.magicMarker = QInstaller::retrieveInt64(file); - layout.magicCookie = QInstaller::retrieveInt64(file); - layout.indexSize = indexSize + sizeof(qint64); - layout.endOfData = file->pos(); - - qDebug() << "Operations start:" << layout.operationsStart; - qDebug() << "Operations end:" << layout.operationsEnd; - qDebug() << "Resource count:" << layout.resourceCount; - qDebug() << "Data block size:" << layout.dataBlockSize; - qDebug() << "Magic marker:" << layout.magicMarker; - qDebug() << "Magic cookie:" << layout.magicCookie; - qDebug() << "Index size:" << layout.indexSize; - qDebug() << "End of data:" << layout.endOfData; - - const qint64 resourceOffsetAndLengtSize = 2 * sizeof(qint64); - const qint64 dataBlockStart = layout.endOfData - layout.dataBlockSize; - for (int i = 0; i < layout.resourceCount; ++i) { - const qint64 offset = layout.endOfData - layout.indexSize - - (resourceOffsetAndLengtSize * (i + 1)); - if (!file->seek(offset)) { - throw Error(QCoreApplication::translate("BinaryContent", - "Could not seek to metadata index.")); - } - const qint64 metadataResourceOffset = QInstaller::retrieveInt64(file); - const qint64 metadataResourceLength = QInstaller::retrieveInt64(file); - layout.metadataResourceSegments.append(Range<qint64>::fromStartAndLength(metadataResourceOffset - + dataBlockStart, metadataResourceLength)); - } - - return layout; -} + layout.endOfBinaryContent = BinaryContent::findMagicCookie(file, magicCookie) + sizeof(qint64); -void BinaryContent::readBinaryContent(const QSharedPointer<QFile> &in, - ResourceCollection *metaResources, QList<OperationBlob> *operations, - ResourceCollectionManager *manager, qint64 *magicMarker, quint64 magicCookie) -{ - const qint64 pos = BinaryContent::findMagicCookie(in.data(), magicCookie); - const qint64 endOfBinaryContent = pos + sizeof(qint64); - - const qint64 posOfMetaDataCount = endOfBinaryContent - (4 * sizeof(qint64)); - if (!in->seek(posOfMetaDataCount)) { - throw Error(QCoreApplication::translate("BinaryContent", + const qint64 posOfMetaDataCount = layout.endOfBinaryContent - (4 * sizeof(qint64)); + if (!file->seek(posOfMetaDataCount)) { + throw QInstaller::Error(QCoreApplication::translate("BinaryLayout", "Could not seek to %1 to read the embedded meta data count.").arg(posOfMetaDataCount)); } + // read the meta resources count - const qint64 metaResourcesCount = QInstaller::retrieveInt64(in.data()); + const qint64 metaResourcesCount = QInstaller::retrieveInt64(file); - const qint64 posOfResourceCollectionsSegment = endOfBinaryContent + const qint64 posOfResourceCollectionsSegment = layout.endOfBinaryContent - ((metaResourcesCount * (2 * sizeof(qint64))) // minus the size of the meta data segments + (8 * sizeof(qint64))); // meta count, offset/length component index, marker, cookie... - if (!in->seek(posOfResourceCollectionsSegment)) { - throw Error(QCoreApplication::translate("BinaryContent", + if (!file->seek(posOfResourceCollectionsSegment)) { + throw Error(QCoreApplication::translate("BinaryLayout", "Could not seek to %1 to read the resource collection segment.") .arg(posOfResourceCollectionsSegment)); } + // read the resource collection index offset and length - const Range<qint64> resourceCollectionsSegment = QInstaller::retrieveInt64Range(in.data()); + layout.resourceCollectionsSegment = QInstaller::retrieveInt64Range(file); // read the meta data resource segments - QVector<Range<qint64> > metaDataResourceSegments; for (int i = 0; i < metaResourcesCount; ++i) - metaDataResourceSegments.append(QInstaller::retrieveInt64Range(in.data())); + layout.metaResourceSegments.append(QInstaller::retrieveInt64Range(file)); + + if (metaResourcesCount != layout.metaResourceSegments.count()) { + throw Error(QCoreApplication::translate("BinaryLayout", + "Unexpected mismatch of meta resources. Read %1, expected: %2.") + .arg(layout.metaResourceSegments.count()).arg(metaResourcesCount)); + } // read the operations offset and length - const Range<qint64> operationsSegment = QInstaller::retrieveInt64Range(in.data()); + layout.operationsSegment = QInstaller::retrieveInt64Range(file); // resources count - Q_UNUSED(QInstaller::retrieveInt64(in.data())) // read it, but deliberately not used + Q_UNUSED(QInstaller::retrieveInt64(file)) // read it, but deliberately not used // read the binary content size - const qint64 binaryContentSize = QInstaller::retrieveInt64(in.data()); - const qint64 endOfBinary = endOfBinaryContent - binaryContentSize; // end of "compiled" binary + layout.binaryContentSize = QInstaller::retrieveInt64(file); + layout.endOfExectuable = layout.endOfBinaryContent - layout.binaryContentSize; - // read the marker - const qint64 marker = QInstaller::retrieveInt64(in.data()); - if (magicMarker) - *magicMarker = marker; + layout.magicMarker = QInstaller::retrieveInt64(file); + layout.magicCookie = QInstaller::retrieveInt64(file); - // the cookie - Q_UNUSED(QInstaller::retrieveInt64(in.data())) // read it, but deliberately not used + // adjust the offsets to match the actual binary + for (int i = 0; i < layout.metaResourceSegments.count(); ++i) + layout.metaResourceSegments[i].move(layout.endOfExectuable); + layout.metaResourcesSegment = Range<qint64>::fromStartAndEnd(layout.metaResourceSegments + .first().start(), layout.metaResourceSegments.last().end()); - // append the calculated resource segments - if (metaResources) { - foreach (const Range<qint64> &segment, metaDataResourceSegments) { - metaResources->appendResource(QSharedPointer<Resource>(new Resource(in, - segment.moved(endOfBinary)))); - } - } + layout.operationsSegment.move(layout.endOfExectuable); + layout.resourceCollectionsSegment.move(layout.endOfExectuable); + + return layout; +} + +void BinaryContent::readBinaryContent(const QSharedPointer<QFile> &in, + ResourceCollection *metaResources, QList<OperationBlob> *operations, + ResourceCollectionManager *manager, qint64 *magicMarker, quint64 magicCookie) +{ + const BinaryLayout layout = BinaryContent::binaryLayout(in.data(), magicCookie); - const qint64 posOfOperationsBlock = endOfBinary + operationsSegment.start(); - if (!in->seek(posOfOperationsBlock)) { - throw Error(QCoreApplication::translate("BinaryContent", - "Could not seek to %1 to read the operation data.").arg(posOfOperationsBlock)); + if (metaResources) { // append the meta resources + foreach (const Range<qint64> &segment, layout.metaResourceSegments) + metaResources->appendResource(QSharedPointer<Resource>(new Resource(in, segment))); } - // read the operations count - qint64 operationsCount = QInstaller::retrieveInt64(in.data()); - // read the operations - for (int i = 0; i < operationsCount; ++i) { - const QString name = QInstaller::retrieveString(in.data()); - const QString xml = QInstaller::retrieveString(in.data()); - if (operations) + + if (operations) { + const qint64 posOfOperationsBlock = layout.operationsSegment.start(); + if (!in->seek(posOfOperationsBlock)) { + throw Error(QCoreApplication::translate("BinaryContent", + "Could not seek to %1 to read the operation data.").arg(posOfOperationsBlock)); + } + // read the operations count + qint64 operationsCount = QInstaller::retrieveInt64(in.data()); + // read the operations + for (int i = 0; i < operationsCount; ++i) { + const QString name = QInstaller::retrieveString(in.data()); + const QString xml = QInstaller::retrieveString(in.data()); operations->append(OperationBlob(name, xml)); + } + // operations count + Q_UNUSED(QInstaller::retrieveInt64(in.data())) // read it, but deliberately not used } - // operations count - Q_UNUSED(QInstaller::retrieveInt64(in.data())) // read it, but deliberately not used - // read the resource collections count - const qint64 collectionCount = QInstaller::retrieveInt64(in.data()); - - const qint64 posOfResourceCollectionBlock = endOfBinary + resourceCollectionsSegment.start(); - if (!in->seek(posOfResourceCollectionBlock)) { - throw Error(QCoreApplication::translate("BinaryContent", - "Could not seek to %1 to read the resource collection block.") - .arg(posOfResourceCollectionBlock)); - } if (manager) { // read the component index and data - manager->read(in, endOfBinary); - if (manager->collectionCount() != collectionCount) { - throw Error(QCoreApplication::translate("BinaryContent", - "Unexpected mismatch of resource collections. Read %1, expected: %2.") - .arg(manager->collectionCount()).arg(collectionCount)); + const qint64 posOfResourceCollectionBlock = layout.resourceCollectionsSegment.start(); + if (!in->seek(posOfResourceCollectionBlock)) { + throw Error(QCoreApplication::translate("BinaryContent", "Could not seek to %1 to " + "read the resource collection block.").arg(posOfResourceCollectionBlock)); } + manager->read(in, layout.endOfExectuable); } + + if (magicMarker) + *magicMarker = layout.magicMarker; } void BinaryContent::writeBinaryContent(const QSharedPointer<QFile> &out, diff --git a/src/libs/installer/binarycontent.h b/src/libs/installer/binarycontent.h index 2efe3d0fc..b4527a74a 100644 --- a/src/libs/installer/binarycontent.h +++ b/src/libs/installer/binarycontent.h @@ -43,9 +43,7 @@ #define BINARYCONTENT_H #include "binaryformat.h" -#include "range.h" - -#include <QVector> +#include "binarylayout.h" QT_BEGIN_NAMESPACE class QFile; @@ -53,19 +51,6 @@ QT_END_NAMESPACE namespace QInstaller { -struct BinaryLayout -{ - QVector<Range<qint64> > metadataResourceSegments; - qint64 operationsStart; - qint64 operationsEnd; - qint64 resourceCount; - qint64 dataBlockSize; - qint64 magicMarker; - quint64 magicCookie; - qint64 indexSize; - qint64 endOfData; -}; - class INSTALLER_EXPORT BinaryContent { public: diff --git a/src/libs/installer/binarylayout.cpp b/src/libs/installer/binarylayout.cpp new file mode 100644 index 000000000..6437262af --- /dev/null +++ b/src/libs/installer/binarylayout.cpp @@ -0,0 +1,110 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +/*! + \class QInstaller::BinaryLayout + + BinaryLayout handles binary information embedded into executables. + Qt resources as well as resource collections can be stored. + + Explanation of the binary blob at the end of the installer or separate data file: + + \code + + Meta data entry [1 ... n] + [Format] + Plain data (QResource) + [Format] + ---------------------------------------------------------- + Operation count (qint64) + Operation entry [1 ... n] + [Format] + Name (qint64, QString) + XML (qint64, QString) + [Format] + Operation count (qint64) + ---------------------------------------------------------- + Component count + Component data entry [1 ... n] + [Format] + Archive count (qint64), + Name entry [1 ... n] + [Format] + Name (qint64, QByteArray), + Offset (qint64), + Length (qint64), + [Format] + Archive data entry [1 ... n] + [Format] + Plain data + [Format] + [Format] + ---------------------------------------------------------- + Component count (qint64) + Component index entry [1 ... n] + [Format] + Name (qint64, QByteArray) + Offset (qint64) + Length (qint64) + [Format] + Component count (qint64) + ---------------------------------------------------------- + Component index block [Offset (qint64)] + Component index block [Length (qint64)] + ---------------------------------------------------------- + Resource segments [1 ... n] + [Format] + Offset (qint64) + Length (qint64) + [Format] + ---------------------------------------------------------- + Operations information block [Offset (qint64)] + Operations information block [Length (qint64)] + ---------------------------------------------------------- + Meta data count (qint64) + ---------------------------------------------------------- + Binary content size [Including Marker and Cookie (qint64)] + ---------------------------------------------------------- + Magic marker (qint64) + Magic cookie (qint64) + + \endcode +*/ diff --git a/src/libs/installer/binarylayout.h b/src/libs/installer/binarylayout.h new file mode 100644 index 000000000..87c8e97dd --- /dev/null +++ b/src/libs/installer/binarylayout.h @@ -0,0 +1,70 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef BINARYLAYOUT_H +#define BINARYLAYOUT_H + +#include "range.h" + +#include <QVector> + +namespace QInstaller { + +struct BinaryLayout +{ + qint64 endOfExectuable; + + QVector<Range<qint64> > metaResourceSegments; + + Range<qint64> metaResourcesSegment; + Range<qint64> operationsSegment; + Range<qint64> resourceCollectionsSegment; + + qint64 binaryContentSize; + qint64 magicMarker; + quint64 magicCookie; + + qint64 endOfBinaryContent; +}; + +} // namespace QInstaller + +#endif // BINARYLAYOUT diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index ffe086053..0f8ec3bcb 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -118,7 +118,8 @@ HEADERS += packagemanagercore.h \ remoteserverconnection.h \ remoteserverconnection_p.h \ fileio.h \ - binarycontent.h + binarycontent.h \ + binarylayout.h SOURCES += packagemanagercore.cpp \ packagemanagercore_p.cpp \ @@ -186,7 +187,8 @@ SOURCES += packagemanagercore.cpp \ remotefileengine.cpp \ remoteserverconnection.cpp \ fileio.cpp \ - binarycontent.cpp + binarycontent.cpp \ + binarylayout.cpp RESOURCES += resources/patch_file_lists.qrc \ resources/installer.qrc diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index c9cd458a6..e182d1159 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -43,6 +43,7 @@ #include "adminauthorization.h" #include "binarycontent.h" #include "binaryformatenginehandler.h" +#include "binarylayout.h" #include "component.h" #include "scriptengine.h" #include "componentmodel.h" @@ -1114,7 +1115,7 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinaryData(QFileDevice *outp const qint64 dataBlockStart = output->pos(); QVector<Range<qint64> >resourceSegments; - QVector<Range<qint64> >existingResourceSegments = layout.metadataResourceSegments; + QVector<Range<qint64> >existingResourceSegments = layout.metaResourceSegments; const QString newDefaultResource = m_core->value(QString::fromLatin1("DefaultResourceReplacement")); if (!newDefaultResource.isEmpty()) { @@ -1168,7 +1169,7 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinaryData(QFileDevice *outp QInstaller::appendInt64Range(output, segment.moved(-dataBlockStart)); QInstaller::appendInt64Range(output, Range<qint64>::fromStartAndEnd(operationsStart, operationsEnd) .moved(-dataBlockStart)); - QInstaller::appendInt64(output, layout.resourceCount); + QInstaller::appendInt64(output, layout.metaResourceSegments.count()); // data block size, from end of .exe to end of file QInstaller::appendInt64(output, output->pos() + 3 * sizeof(qint64) -dataBlockStart); QInstaller::appendInt64(output, BinaryContent::MagicUninstallerMarker); @@ -1368,7 +1369,8 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper layout = BinaryContent::binaryLayout(&input, BinaryContent::MagicCookie); if (!newBinaryWritten) { newBinaryWritten = true; - writeMaintenanceToolBinary(&input, layout.endOfData - layout.dataBlockSize, true); + writeMaintenanceToolBinary(&input, layout.endOfBinaryContent + - layout.binaryContentSize, true); } #endif } @@ -1402,7 +1404,8 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper QFile tmp(isInstaller() ? installerBinaryPath() : maintenanceToolName()); QInstaller::openForRead(&tmp); BinaryLayout tmpLayout = BinaryContent::binaryLayout(&tmp, BinaryContent::MagicCookie); - writeMaintenanceToolBinary(&tmp, tmpLayout.endOfData - tmpLayout.dataBlockSize, false); + writeMaintenanceToolBinary(&tmp, tmpLayout.endOfBinaryContent + - tmpLayout.binaryContentSize, false); } QFile file(maintenanceToolName() + QLatin1String(".new")); diff --git a/tests/auto/installer/binaryformat/tst_binaryformat.cpp b/tests/auto/installer/binaryformat/tst_binaryformat.cpp index d313bbbcc..87a1f7ef8 100644 --- a/tests/auto/installer/binaryformat/tst_binaryformat.cpp +++ b/tests/auto/installer/binaryformat/tst_binaryformat.cpp @@ -54,22 +54,11 @@ static const qint64 scLargeSize = 2097152LL; using namespace QInstaller; -struct Layout +struct Layout : public QInstaller::BinaryLayout { - Range<qint64> metaResourceSegment; - QVector<Range<qint64> > metaResourceSegments; - + qint64 metaSegmentsCount; qint64 operationsCount; - Range<qint64> operationsSegment; - qint64 collectionCount; - Range<qint64> resourceCollectionIndexSegment; - - qint64 binaryContentSize; - qint64 magicMarker; - quint64 magicCookie; - - qint64 endOfBinary; }; class TestOperation : public KDUpdater::UpdateOperation @@ -165,23 +154,22 @@ private slots: QInstaller::blockingWrite(&binary, QByteArray(scTinySize, '1')); Layout layout; - layout.endOfBinary = binary.pos(); + layout.endOfExectuable = binary.pos(); layout.magicMarker = BinaryContent::MagicInstallerMarker; layout.magicCookie = BinaryContent::MagicCookie; qint64 start = binary.pos(); // write default resource (fake) QInstaller::blockingWrite(&binary, QByteArray("Default resource data.")); qint64 end = binary.pos(); - layout.metaResourceSegments.append(Range<qint64>::fromStartAndEnd(start, end) - .moved(-layout.endOfBinary)); + layout.metaResourceSegments.append(Range<qint64>::fromStartAndEnd(start, end)); start = end; // // write additional resource (fake) QInstaller::blockingWrite(&binary, QByteArray("Additional resource data.")); end = binary.pos(); - layout.metaResourceSegments.append(Range<qint64>::fromStartAndEnd(start, end) - .moved(-layout.endOfBinary)); - layout.metaResourceSegment = Range<qint64>::fromStartAndEnd(layout.metaResourceSegments.first() - .start(), layout.metaResourceSegments.last().end()); + layout.metaResourceSegments.append(Range<qint64>::fromStartAndEnd(start, end)); + layout.metaResourcesSegment = Range<qint64>::fromStartAndEnd(layout.metaResourceSegments + .first().start(), layout.metaResourceSegments.last().end()); + layout.metaSegmentsCount = layout.metaResourceSegments.count(); start = end; layout.operationsCount = m_operations.count(); @@ -192,8 +180,7 @@ private slots: } QInstaller::appendInt64(&binary, layout.operationsCount); end = binary.pos(); - layout.operationsSegment = Range<qint64>::fromStartAndEnd(start, end).moved(-layout - .endOfBinary); + layout.operationsSegment = Range<qint64>::fromStartAndEnd(start, end); QTemporaryFile data; QTemporaryFile data2; @@ -227,25 +214,30 @@ private slots: manager.insertCollection(collection2); layout.collectionCount = manager.collectionCount(); - layout.resourceCollectionIndexSegment = manager.write(&binary, -layout.endOfBinary) - .moved(-layout.endOfBinary); + layout.resourceCollectionsSegment = manager.write(&binary, -layout.endOfExectuable); resource->close(); resource2->close(); } - QInstaller::appendInt64Range(&binary, layout.resourceCollectionIndexSegment); + QInstaller::appendInt64Range(&binary, layout.resourceCollectionsSegment.moved(-layout + .endOfExectuable)); + foreach (const Range<qint64> &segment, layout.metaResourceSegments) - QInstaller::appendInt64Range(&binary, segment); - QInstaller::appendInt64Range(&binary, layout.operationsSegment); - QInstaller::appendInt64(&binary, layout.metaResourceSegments.count()); + QInstaller::appendInt64Range(&binary, segment.moved(-layout.endOfExectuable)); - layout.binaryContentSize = (binary.pos() + (3 * sizeof(qint64))) - layout.endOfBinary; + QInstaller::appendInt64Range(&binary, layout.operationsSegment.moved(-layout + .endOfExectuable)); + + QInstaller::appendInt64(&binary, layout.metaSegmentsCount); + layout.binaryContentSize = (binary.pos() + (3 * sizeof(qint64))) - layout.endOfExectuable; QInstaller::appendInt64(&binary, layout.binaryContentSize); QInstaller::appendInt64(&binary, layout.magicMarker); QInstaller::appendInt64(&binary, layout.magicCookie); + layout.endOfBinaryContent = binary.pos(); + binary.close(); binary.setAutoRemove(false); @@ -260,41 +252,48 @@ private slots: QCOMPARE(QInstaller::retrieveData(binary.data(), scTinySize), QByteArray(scTinySize, '1')); Layout layout; - layout.endOfBinary = binary->pos(); - QCOMPARE(layout.endOfBinary, m_layout.endOfBinary); + layout.endOfExectuable = binary->pos(); + QCOMPARE(layout.endOfExectuable, m_layout.endOfExectuable); const qint64 pos = BinaryContent::findMagicCookie(binary.data(), BinaryContent::MagicCookie); - const qint64 endOfBinaryContent = pos + sizeof(qint64); + layout.endOfBinaryContent = pos + sizeof(qint64); + QCOMPARE(layout.endOfBinaryContent, m_layout.endOfBinaryContent); - binary->seek(endOfBinaryContent - (4 * sizeof(qint64))); + binary->seek(layout.endOfBinaryContent - (4 * sizeof(qint64))); - qint64 metaSegmentsCount = QInstaller::retrieveInt64(binary.data()); - QCOMPARE(metaSegmentsCount, m_layout.metaResourceSegments.count()); + layout.metaSegmentsCount = QInstaller::retrieveInt64(binary.data()); + QCOMPARE(layout.metaSegmentsCount, m_layout.metaSegmentsCount); - const qint64 offsetCollectionIndexSegments = endOfBinaryContent - - ((metaSegmentsCount * (2 * sizeof(qint64))) // minus the size of the meta segments + const qint64 offsetCollectionIndexSegments = layout.endOfBinaryContent + - ((layout.metaSegmentsCount * (2 * sizeof(qint64))) // minus size of the meta segments + (8 * sizeof(qint64))); // meta count, offset/length component index, marker, cookie... binary->seek(offsetCollectionIndexSegments); - layout.resourceCollectionIndexSegment = QInstaller::retrieveInt64Range(binary.data()); - QCOMPARE(layout.resourceCollectionIndexSegment, m_layout.resourceCollectionIndexSegment); + layout.resourceCollectionsSegment = QInstaller::retrieveInt64Range(binary.data()) + .moved(layout.endOfExectuable); + QCOMPARE(layout.resourceCollectionsSegment, m_layout.resourceCollectionsSegment); - for (int i = 0; i < metaSegmentsCount; ++i) - layout.metaResourceSegments.append(QInstaller::retrieveInt64Range(binary.data())); - layout.metaResourceSegment = Range<qint64>::fromStartAndEnd(layout.metaResourceSegments + for (int i = 0; i < layout.metaSegmentsCount; ++i) { + layout.metaResourceSegments.append(QInstaller::retrieveInt64Range(binary.data()) + .moved(layout.endOfExectuable)); + } + layout.metaResourcesSegment = Range<qint64>::fromStartAndEnd(layout.metaResourceSegments .first().start(), layout.metaResourceSegments.last().end()); - QCOMPARE(layout.metaResourceSegment, m_layout.metaResourceSegment); - QCOMPARE(layout.metaResourceSegments, m_layout.metaResourceSegments); - layout.operationsSegment = QInstaller::retrieveInt64Range(binary.data()); + QCOMPARE(layout.metaResourcesSegment, m_layout.metaResourcesSegment); + QCOMPARE(layout.metaResourceSegments.first(), m_layout.metaResourceSegments.first()); + QCOMPARE(layout.metaResourceSegments.last(), m_layout.metaResourceSegments.last()); + + layout.operationsSegment = QInstaller::retrieveInt64Range(binary.data()).moved(layout + .endOfExectuable); QCOMPARE(layout.operationsSegment, m_layout.operationsSegment); - QCOMPARE(metaSegmentsCount, QInstaller::retrieveInt64(binary.data())); + QCOMPARE(layout.metaSegmentsCount, QInstaller::retrieveInt64(binary.data())); layout.binaryContentSize = QInstaller::retrieveInt64(binary.data()); QCOMPARE(layout.binaryContentSize, m_layout.binaryContentSize); - QCOMPARE(layout.endOfBinary, endOfBinaryContent - layout.binaryContentSize); + QCOMPARE(layout.endOfExectuable, layout.endOfBinaryContent - layout.binaryContentSize); layout.magicMarker = QInstaller::retrieveInt64(binary.data()); QCOMPARE(layout.magicMarker, m_layout.magicMarker); @@ -302,7 +301,7 @@ private slots: layout.magicCookie = QInstaller::retrieveInt64(binary.data()); QCOMPARE(layout.magicCookie, m_layout.magicCookie); - binary->seek(layout.endOfBinary + layout.operationsSegment.start()); + binary->seek(layout.operationsSegment.start()); layout.operationsCount = QInstaller::retrieveInt64(binary.data()); QCOMPARE(layout.operationsCount, m_layout.operationsCount); @@ -318,8 +317,8 @@ private slots: layout.collectionCount = QInstaller::retrieveInt64(binary.data()); QCOMPARE(layout.collectionCount, m_layout.collectionCount); - binary->seek(layout.endOfBinary + layout.resourceCollectionIndexSegment.start()); - m_manager.read(binary, layout.endOfBinary); + binary->seek(layout.resourceCollectionsSegment.start()); + m_manager.read(binary, layout.endOfExectuable); const QList<ResourceCollection> components = m_manager.collections(); QCOMPARE(components.count(), m_layout.collectionCount); @@ -357,7 +356,7 @@ private slots: ResourceCollection resources; foreach (const Range<qint64> &segment, m_layout.metaResourceSegments) { resources.appendResource(QSharedPointer<Resource> (new Resource(existingBinary, - segment.moved(m_layout.endOfBinary)))); + segment))); } QList<OperationBlob> operations; @@ -388,10 +387,8 @@ private slots: QCOMPARE(magicMarker, m_layout.magicMarker); QCOMPARE(collection.resources().count(), m_layout.metaResourceSegments.count()); - for (int i = 0; i < collection.resources().count(); ++i) { - QCOMPARE(collection.resources().at(i)->segment(), m_layout.metaResourceSegments.at(i) - .moved(m_layout.endOfBinary)); - } + for (int i = 0; i < collection.resources().count(); ++i) + QCOMPARE(collection.resources().at(i)->segment(), m_layout.metaResourceSegments.at(i)); QCOMPARE(operations.count(), m_operations.count()); for (int i = 0; i < operations.count(); ++i) { diff --git a/tools/devtool/binaryreplace.cpp b/tools/devtool/binaryreplace.cpp index a7213ecfe..4bd76178d 100644 --- a/tools/devtool/binaryreplace.cpp +++ b/tools/devtool/binaryreplace.cpp @@ -41,6 +41,7 @@ #include "binaryreplace.h" +#include <binarycontent.h> #include <copyfiletask.h> #include <downloadfiletask.h> #include <errors.h> @@ -115,7 +116,7 @@ int BinaryReplace::replace(const QString &source, const QString &target) installerBaseNew.seek(installerBaseNew.size()); if (m_binaryLayout.magicMarker == QInstaller::BinaryContent::MagicInstallerMarker) { QInstaller::openForRead(&installerBaseOld); - installerBaseOld.seek(m_binaryLayout.metadataResourceSegments.first().start()); + installerBaseOld.seek(m_binaryLayout.metaResourcesSegment.start()); QInstaller::appendData(&installerBaseNew, &installerBaseOld, installerBaseOld .size() - installerBaseOld.pos()); installerBaseOld.close(); diff --git a/tools/devtool/binaryreplace.h b/tools/devtool/binaryreplace.h index 52f90c209..8d123356e 100644 --- a/tools/devtool/binaryreplace.h +++ b/tools/devtool/binaryreplace.h @@ -42,7 +42,7 @@ #ifndef BINARYREPLACE_H #define BINARYREPLACE_H -#include <binarycontent.h> +#include <binarylayout.h> class BinaryReplace { diff --git a/tools/devtool/main.cpp b/tools/devtool/main.cpp index 0a9c677d2..005aadd61 100644 --- a/tools/devtool/main.cpp +++ b/tools/devtool/main.cpp @@ -101,80 +101,58 @@ int main(int argc, char *argv[]) int result = EXIT_FAILURE; QVector<QByteArray> resourceMappings; + quint64 cookie = QInstaller::BinaryContent::MagicCookie; try { - QFile *file = new QFile(path); - QInstaller::openForRead(file); - - QInstaller::BinaryLayout layout = QInstaller::BinaryContent::binaryLayout(file, - QInstaller::BinaryContent::MagicCookie); - - if (layout.magicMarker == QInstaller::BinaryContent::MagicUninstallerMarker) { - QFileInfo fi(path); - if (QInstaller::isInBundle(fi.absoluteFilePath(), &bundlePath)) - fi.setFile(bundlePath); - path = fi.absolutePath() + QLatin1Char('/') + fi.baseName() + QLatin1String(".dat"); - - file->setFileName(path); - layout = QInstaller::BinaryContent::binaryLayout(file, - QInstaller::BinaryContent::MagicCookie); + { + QFile tmp(path); + QInstaller::openForRead(&tmp); + + QInstaller::BinaryLayout layout = QInstaller::BinaryContent::binaryLayout(&tmp, + cookie); + + if (layout.magicMarker == QInstaller::BinaryContent::MagicUninstallerMarker) { + QFileInfo fi(path); + if (QInstaller::isInBundle(fi.absoluteFilePath(), &bundlePath)) + fi.setFile(bundlePath); + path = fi.absolutePath() + QLatin1Char('/') + fi.baseName() + QLatin1String(".dat"); + + tmp.setFileName(path); + cookie = QInstaller::BinaryContent::MagicCookieDat; + layout = QInstaller::BinaryContent::binaryLayout(&tmp, cookie); + } + tmp.close(); + + if (parser.isSet(update)) { + // To update the binary we do not need any mapping. + BinaryReplace br(layout); + return br.replace(parser.value(update), path); + } } - if (parser.isSet(update)) { - // To update the binary we do not need any mapping. - BinaryReplace br(layout); - return br.replace(parser.value(update), path); - } + QSharedPointer<QFile> file(new QFile(path)); + QInstaller::openForRead(file.data()); + + qint64 magicMarker; + QInstaller::ResourceCollection meta; + QList<QInstaller::OperationBlob> operations; + QInstaller::ResourceCollectionManager manager; + QInstaller::BinaryContent::readBinaryContent(file, &meta, &operations, &manager, + &magicMarker, cookie); // map the inbuilt resources - foreach (const Range<qint64> &segment, layout.metadataResourceSegments) { - if (segment.length() <= 0) - continue; - if (!file->seek(segment.start())) - throw QInstaller::Error(QLatin1String("Could not seek to segment position.")); - const QByteArray ba = QInstaller::retrieveData(file, segment.length()); + foreach (const QSharedPointer<QInstaller::Resource> &resource, meta.resources()) { + const bool opened = resource->open(); + const QByteArray ba = resource->readAll(); if (!QResource::registerResource((const uchar*) ba.data(), QLatin1String(":/metadata"))) throw QInstaller::Error(QLatin1String("Could not register in-binary resource.")); resourceMappings.append(ba); + if (opened) + resource->close(); } - // instantiate the operations we support - const qint64 dataBlockStart = layout.endOfData - layout.dataBlockSize; - const qint64 operationsStart = layout.operationsStart + dataBlockStart; - if (!file->seek(operationsStart)) - throw QInstaller::Error(QLatin1String("Could not seek to operation list.")); - - QList<QInstaller::OperationBlob> performedOperations; - const qint64 operationsCount = QInstaller::retrieveInt64(file); - for (int i = 0; i < operationsCount; ++i) { - const QString name = QInstaller::retrieveString(file); - const QString data = QInstaller::retrieveString(file); - performedOperations.append(QInstaller::OperationBlob(name, data)); - } - - // seek to the position of the resource collections segment info - const qint64 resourceOffsetAndLengtSize = 2 * sizeof(qint64); - const qint64 resourceSectionSize = resourceOffsetAndLengtSize * layout.resourceCount; - qint64 offset = layout.endOfData - layout.indexSize - resourceSectionSize - - resourceOffsetAndLengtSize; - if (!file->seek(offset)) { - throw QInstaller::Error(QLatin1String("Could not seek to read the resource collection " - "segment info.")); - } - - offset = QInstaller::retrieveInt64(file) + dataBlockStart; - if (!file->seek(offset)) { - throw QInstaller::Error(QLatin1String("Could not seek to start position of resource " - "collection block.")); - } - - // setup the collection manager - QSharedPointer<QFile> data(file); - QInstaller::ResourceCollectionManager manager; - manager.read(data, dataBlockStart); - if (parser.isSet(dump)) { // To dump the content we do not need the binary format engine. - if (layout.magicMarker != QInstaller::BinaryContent::MagicInstallerMarker) + if (magicMarker != QInstaller::BinaryContent::MagicInstallerMarker) throw QInstaller::Error(QLatin1String("Source file is not an installer.")); BinaryDump bd; return bd.dump(manager, parser.value(dump)); @@ -184,7 +162,7 @@ int main(int argc, char *argv[]) .collections()); // setup the binary format engine if (parser.isSet(run)) { - OperationRunner runner(layout.magicMarker, performedOperations); + OperationRunner runner(magicMarker, operations); const QStringList arguments = parser.values(run); if (arguments.first() == QLatin1String("DO")) result = runner.runOperation(arguments.mid(1), OperationRunner::RunMode::Do); |