summaryrefslogtreecommitdiffstats
path: root/installerbuilder/common
diff options
context:
space:
mode:
authorkh1 <qt-info@nokia.com>2011-05-19 16:16:42 +0200
committerkh1 <qt-info@nokia.com>2011-05-19 16:16:42 +0200
commit7ccecfcb5ce5ab9bb3c827a780309ea577b3a5d8 (patch)
tree0f54b734de8ee5ba2ad080efa14960b4f5229cc8 /installerbuilder/common
parent412fbc9875f7552e6277653643c54cf225a4bb62 (diff)
Preparation to support a decoupled data file.
Diffstat (limited to 'installerbuilder/common')
-rw-r--r--installerbuilder/common/binaryformat.cpp152
-rw-r--r--installerbuilder/common/binaryformat.h39
2 files changed, 116 insertions, 75 deletions
diff --git a/installerbuilder/common/binaryformat.cpp b/installerbuilder/common/binaryformat.cpp
index 306914ae9..ed2627d09 100644
--- a/installerbuilder/common/binaryformat.cpp
+++ b/installerbuilder/common/binaryformat.cpp
@@ -199,7 +199,7 @@ QHash<QString,QString> QInstaller::retrieveDictionary(QIODevice *in)
return dict;
}
-qint64 QInstaller::findMagicCookie(QFile *in)
+qint64 QInstaller::findMagicCookie(QFile *in, quint64 magicCookie)
{
Q_ASSERT(in);
Q_ASSERT(in->isOpen());
@@ -217,7 +217,7 @@ qint64 QInstaller::findMagicCookie(QFile *in)
in->fileName(), in->errorString()));
}
const quint64 num = static_cast<quint64>(retrieveInt64(in));
- if (num == MagicCookie) {
+ if (num == magicCookie) {
in->seek(oldPos);
return pos;
}
@@ -756,10 +756,10 @@ static const uchar* addResourceFromBinary(QFile* file, const Range<qint64> &segm
}
BinaryContent::BinaryContent(const QString &path)
- : file(new QFile(path)),
- handler(components),
- m_magicmaker(0),
- dataBlockStart(0)
+ : file(new QFile(path))
+ , handler(components)
+ , m_magicmarker(0)
+ , dataBlockStart(0)
{
}
@@ -857,76 +857,101 @@ BinaryContent BinaryContent::readFromBinary(const QString &path)
if (!file->open(QIODevice::ReadOnly))
throw Error(QObject::tr("Could not open binary %1: %2").arg(path, file->errorString()));
- const qint64 cookiepos = findMagicCookie(file);
- Q_ASSERT(cookiepos >= 0);
- const qint64 endOfData = cookiepos + sizeof(qint64);
- const qint64 indexSize = 6 * sizeof(qint64);
- if (!file->seek(endOfData - indexSize))
- throw Error(QObject::tr("Could not seek to binary layout section"));
-
- // fetch all file positions to read the data stored after the actual binary
- qint64 operationsStart = retrieveInt64(file);
- const qint64 operationsEnd = retrieveInt64(file);
- const qint64 resourceCount = retrieveInt64(file);
- const qint64 dataBlockSize = retrieveInt64(file);
- c.m_magicmaker = retrieveInt64(file);
- const quint64 magicCookie = retrieveInt64(file);
-
- Q_UNUSED(magicCookie)
- Q_UNUSED(operationsEnd)
- Q_ASSERT(magicCookie == MagicCookie);
-
- const qint64 dataBlockStart = endOfData - dataBlockSize;
- const qint64 resourceSectionSize = 2 * sizeof(qint64) * resourceCount;
- for (int i = 0; i < resourceCount; ++i) {
- if (!file->seek(endOfData - indexSize - 2 * sizeof(qint64) * (i + 1)))
+ // check for supported binary, will throw if we can't find a marker
+ const qint64 cookiePos = findMagicCookie(file, QInstaller::MagicCookie);
+ const BinaryLayout layout = readBinaryLayout(file, cookiePos);
+ if (layout.magicMarker != MagicInstallerMarker) {
+ QString binaryDataPath = path;
+ QFileInfo fi(path + QLatin1String("/../../.."));
+ if (QFileInfo(fi.absoluteFilePath()).isBundle())
+ binaryDataPath = fi.absoluteFilePath();
+ fi.setFile(binaryDataPath);
+
+ bool retry = true;
+ QFile binaryData(fi.absolutePath() + QLatin1Char('/') + fi.baseName() + QLatin1String(".dat"));
+ if (binaryData.exists() && binaryData.open(QIODevice::ReadOnly)) {
+ // check for supported binary data file, will throw if we can't find a marker
+ try {
+ const qint64 cookiePosData = findMagicCookie(&binaryData, QInstaller::MagicCookieDat);
+ readBinaryData(c, &binaryData, readBinaryLayout(&binaryData, cookiePosData));
+ retry = false;
+ } catch (const Error &error) {
+ // this seems to be an unsupported dat file, try to read from original binary
+ verbose() << error.message();
+ }
+ }
+ if (retry)
+ readBinaryData(c, file, layout);
+ } else {
+ readBinaryData(c, file, layout);
+ }
+ return c;
+}
+
+/* static */
+BinaryLayout BinaryContent::readBinaryLayout(QIODevice *file, qint64 cookiePos)
+{
+ const qint64 indexSize = 5 * sizeof(qint64);
+ if (!file->seek(cookiePos - indexSize))
+ throw Error(QObject::tr("Could not seek to binary layout section!"));
+
+ BinaryLayout layout;
+ layout.operationsStart = retrieveInt64(file);
+ layout.operationsEnd = retrieveInt64(file);
+ layout.resourceCount = retrieveInt64(file);
+ layout.dataBlockSize = retrieveInt64(file);
+ layout.magicMarker = retrieveInt64(file);
+ layout.magicCookie = retrieveInt64(file);
+ layout.indexSize = indexSize + sizeof(qint64);
+ layout.endOfData = file->pos();
+
+ const qint64 resourceOffsetAndLengtSize = 2 * sizeof(qint64);
+ const qint64 dataBlockStart = layout.endOfData - layout.dataBlockSize;
+ for (int i = 0; i < layout.resourceCount; ++i) {
+ if (!file->seek(layout.endOfData - layout.indexSize - resourceOffsetAndLengtSize * (i + 1)))
throw Error(QObject::tr("Could not seek to metadata index"));
const qint64 metadataResourceOffset = retrieveInt64(file);
const qint64 metadataResourceLength = retrieveInt64(file);
- c.metadataResourceSegments.push_back(Range<qint64>::fromStartAndLength(metadataResourceOffset
+ layout.metadataResourceSegments.append(Range<qint64>::fromStartAndLength(metadataResourceOffset
+ dataBlockStart, metadataResourceLength));
}
- if (c.m_magicmaker != MagicInstallerMarker) {
- QString binaryPath = path;
- QFileInfo fi(binaryPath + QLatin1String("/../../.."));
- if (QFileInfo(fi.absoluteFilePath()).isBundle())
- binaryPath = fi.absoluteFilePath();
- fi.setFile(binaryPath);
-
- QFile *tmp = file;
- operationsStart += dataBlockStart;
- QFile operations(fi.absolutePath() + QLatin1Char('/') + fi.baseName() + QLatin1String(".dat"));
- if (operations.exists() && operations.open(QIODevice::ReadOnly)) {
- if (findMagicCookie(&operations) >= 0) {
- tmp = &operations;
- operationsStart = 0;
- }
- }
+ return layout;
+}
- if (!tmp->seek(operationsStart))
- throw Error(QObject::tr("Could not seek to operation list"));
- const qint64 operationsCount = retrieveInt64(tmp);
- verbose() << "operationsCount=" << operationsCount << std::endl;
+/* static */
+void BinaryContent::readBinaryData(BinaryContent &c, QIODevice *const file, const BinaryLayout &layout)
+{
+ c.m_magicmarker = layout.magicMarker;
+ c.metadataResourceSegments = layout.metadataResourceSegments;
- for (int i = 0; i < operationsCount; ++i) {
- const QString name = retrieveString(tmp);
- KDUpdater::UpdateOperation *op = KDUpdater::UpdateOperationFactory::instance().create(name);
- Q_ASSERT_X(op, __FUNCTION__, QString::fromLatin1("Invalid operation name: %1").arg(name)
- .toLatin1());
+ const qint64 dataBlockStart = layout.endOfData - layout.dataBlockSize;
+ const qint64 operationsStart = layout.operationsStart + dataBlockStart;
+ if (!file->seek(operationsStart))
+ throw Error(QObject::tr("Could not seek to operation list"));
- const QString xml = retrieveString(tmp);
- if (!op->fromXml(xml))
- qWarning() << "Failed to load XML for operation:" << name;
- verbose() << "Operation name: " << name << "\nOperation xml:\n" << xml.leftRef(1000) << std::endl;
- c.m_performedOperations.push(op);
- }
+ const qint64 operationsCount = retrieveInt64(file);
+ verbose() << "Number of operations: " << operationsCount << std::endl;
+
+ for (int i = 0; i < operationsCount; ++i) {
+ const QString name = retrieveString(file);
+ KDUpdater::UpdateOperation *op = KDUpdater::UpdateOperationFactory::instance().create(name);
+ Q_ASSERT_X(op, __FUNCTION__, QString::fromLatin1("Invalid operation name: %1").arg(name)
+ .toLatin1());
+
+ const QString xml = retrieveString(file);
+ if (!op->fromXml(xml))
+ qWarning() << "Failed to load XML for operation:" << name;
+ verbose() << "Operation name: " << name << "\nOperation xml:\n" << xml.leftRef(1000) << std::endl;
+ c.m_performedOperations.push(op);
}
// seek to the position of the component index
- if (!file->seek(endOfData - indexSize - resourceSectionSize - 2 * sizeof(qint64)))
+ const qint64 resourceOffsetAndLengtSize = 2 * sizeof(qint64);
+ const qint64 resourceSectionSize = resourceOffsetAndLengtSize * layout.resourceCount;
+ if (!file->seek(layout.endOfData - layout.indexSize - resourceSectionSize - resourceOffsetAndLengtSize))
throw Error(QObject::tr("Could not seek to component index information"));
const qint64 compIndexStart = retrieveInt64(file) + dataBlockStart;
@@ -949,7 +974,6 @@ BinaryContent BinaryContent::readFromBinary(const QString &path)
}
}
}
- return c;
}
@@ -958,7 +982,7 @@ BinaryContent BinaryContent::readFromBinary(const QString &path)
*/
qint64 BinaryContent::magicmaker() const
{
- return m_magicmaker;
+ return m_magicmarker;
}
/*!
diff --git a/installerbuilder/common/binaryformat.h b/installerbuilder/common/binaryformat.h
index 0f3c69982..81a87b83d 100644
--- a/installerbuilder/common/binaryformat.h
+++ b/installerbuilder/common/binaryformat.h
@@ -42,7 +42,17 @@ namespace KDUpdater {
}
namespace QInstaller {
- qint64 INSTALLER_EXPORT findMagicCookie(QFile *file);
+ static const qint64 MagicInstallerMarker = 0x12023233UL;
+ static const qint64 MagicUninstallerMarker = 0x12023234UL;
+
+ static const qint64 MagicUpdaterMarker = 0x12023235UL;
+ static const qint64 MagicPackageManagerMarker = 0x12023236UL;
+
+ // this cookie is put at the end of the file to determine whether we have data
+ static const quint64 MagicCookie = 0xc2630a1c99d668f8LL;
+ static const quint64 MagicCookieDat = 0xc2630a1c99d668f9LL;
+
+ qint64 INSTALLER_EXPORT findMagicCookie(QFile *file, quint64 magicCookie = MagicCookie);
void INSTALLER_EXPORT appendFileData(QIODevice *out, QIODevice *in);
void INSTALLER_EXPORT appendInt64(QIODevice *out, qint64 n);
void INSTALLER_EXPORT appendInt64Range(QIODevice *out, const Range<qint64> &r);
@@ -59,15 +69,6 @@ namespace QInstaller {
QString INSTALLER_EXPORT retrieveString(QIODevice *in);
QStringList INSTALLER_EXPORT retrieveStringList(QIODevice *in);
QHash<QString,QString> INSTALLER_EXPORT retrieveDictionary(QIODevice *in);
-
- static const qint64 MagicInstallerMarker = 0x12023233UL;
- static const qint64 MagicUninstallerMarker = 0x12023234UL;
-
- static const qint64 MagicUpdaterMarker = 0x12023235UL;
- static const qint64 MagicPackageManagerMarker = 0x12023236UL;
-
- // this cookie is put at the end of the file to determine whether we have data
- static const quint64 MagicCookie = 0xc2630a1c99d668f8LL;
}
namespace QInstallerCreator {
@@ -169,6 +170,18 @@ private:
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
{
explicit BinaryContent(const QString &path);
@@ -178,18 +191,22 @@ public:
static BinaryContent readFromApplicationFile();
static BinaryContent readFromBinary(const QString &path);
+ static BinaryLayout readBinaryLayout(QIODevice *file, qint64 cookiePos);
qint64 magicmaker() const;
int registerEmbeddedQResources();
QStack<KDUpdater::UpdateOperation*> performedOperations() const;
private:
+ static void readBinaryData(BinaryContent &c, QIODevice *const file, const BinaryLayout &layout);
+
+private:
QSharedPointer<QFile> file;
QInstallerCreator::ComponentIndex components;
QInstallerCreator::BinaryFormatEngineHandler handler;
QVector<Range<qint64> > metadataResourceSegments;
QVector<const uchar*> mappings;
- qint64 m_magicmaker;
+ qint64 m_magicmarker;
qint64 dataBlockStart;
QStack<KDUpdater::UpdateOperation*> m_performedOperations;
};