summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2016-11-18 16:54:09 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2016-11-22 04:57:02 +0000
commitd20773824529d191e7b483b505107dce6c1b1c3d (patch)
tree3a71cbcef337eb9efb709d178af2eee1123e493b
parent32b99a38c563e4037362a25b2a749e2261bf16da (diff)
Fix missing last modification time stamp in qrc content
The time stamp is added at the end of the node information and consequently this also bumps the version. Task-number: QTBUG-57182 Change-Id: Ia10e006f28c0b168b2bcd74ed8b7098f84d10af3 Reviewed-by: hjk <hjk@qt.io>
-rw-r--r--src/corelib/io/qresource.cpp65
-rw-r--r--src/corelib/io/qresource.h1
-rw-r--r--src/tools/rcc/rcc.cpp46
-rw-r--r--src/tools/rcc/rcc.h1
-rw-r--r--tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp15
-rw-r--r--tests/auto/tools/rcc/data/images/images.expected10
-rw-r--r--tests/auto/tools/rcc/tst_rcc.cpp17
7 files changed, 133 insertions, 22 deletions
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 7fe3753da4..72042e1600 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -101,35 +101,38 @@ class QResourceRoot
Directory = 0x02
};
const uchar *tree, *names, *payloads;
- inline int findOffset(int node) const { return node * 14; } //sizeof each tree element
+ int version;
+ inline int findOffset(int node) const { return node * (14 + (version >= 0x02 ? 8 : 0)); } //sizeof each tree element
uint hash(int node) const;
QString name(int node) const;
short flags(int node) const;
public:
mutable QAtomicInt ref;
- inline QResourceRoot(): tree(0), names(0), payloads(0) {}
- inline QResourceRoot(const uchar *t, const uchar *n, const uchar *d) { setSource(t, n, d); }
+ inline QResourceRoot(): tree(0), names(0), payloads(0), version(0) {}
+ inline QResourceRoot(int version, const uchar *t, const uchar *n, const uchar *d) { setSource(version, t, n, d); }
virtual ~QResourceRoot() { }
int findNode(const QString &path, const QLocale &locale=QLocale()) const;
inline bool isContainer(int node) const { return flags(node) & Directory; }
inline bool isCompressed(int node) const { return flags(node) & Compressed; }
const uchar *data(int node, qint64 *size) const;
+ QDateTime lastModified(int node) const;
QStringList children(int node) const;
virtual QString mappingRoot() const { return QString(); }
bool mappingRootSubdir(const QString &path, QString *match=0) const;
inline bool operator==(const QResourceRoot &other) const
- { return tree == other.tree && names == other.names && payloads == other.payloads; }
+ { return tree == other.tree && names == other.names && payloads == other.payloads && version == other.version; }
inline bool operator!=(const QResourceRoot &other) const
{ return !operator==(other); }
enum ResourceRootType { Resource_Builtin, Resource_File, Resource_Buffer };
virtual ResourceRootType type() const { return Resource_Builtin; }
protected:
- inline void setSource(const uchar *t, const uchar *n, const uchar *d) {
+ inline void setSource(int v, const uchar *t, const uchar *n, const uchar *d) {
tree = t;
names = n;
payloads = d;
+ version = v;
}
};
@@ -231,6 +234,7 @@ public:
mutable qint64 size;
mutable const uchar *data;
mutable QStringList children;
+ mutable QDateTime lastModified;
QResource *q_ptr;
Q_DECLARE_PUBLIC(QResource)
@@ -244,6 +248,7 @@ QResourcePrivate::clear()
data = 0;
size = 0;
children.clear();
+ lastModified = QDateTime();
container = 0;
for(int i = 0; i < related.size(); ++i) {
QResourceRoot *root = related.at(i);
@@ -274,6 +279,7 @@ QResourcePrivate::load(const QString &file)
size = 0;
compressed = 0;
}
+ lastModified = res->lastModified(node);
} else if(res->isContainer(node) != container) {
qWarning("QResourceInfo: Resource [%s] has both data and children!", file.toLatin1().constData());
}
@@ -284,6 +290,7 @@ QResourcePrivate::load(const QString &file)
data = 0;
size = 0;
compressed = 0;
+ lastModified = QDateTime();
res->ref.ref();
related.append(res);
}
@@ -514,6 +521,17 @@ const uchar *QResource::data() const
}
/*!
+ Returns the date and time when the file was last modified before
+ packaging into a resource.
+*/
+QDateTime QResource::lastModified() const
+{
+ Q_D(const QResource);
+ d->ensureInitialized();
+ return d->lastModified;
+}
+
+/*!
Returns \c true if the resource represents a directory and thus may have
children() in it, false if it represents a file.
@@ -780,6 +798,24 @@ const uchar *QResourceRoot::data(int node, qint64 *size) const
*size = 0;
return 0;
}
+
+QDateTime QResourceRoot::lastModified(int node) const
+{
+ if (node == -1 || version < 0x02)
+ return QDateTime();
+
+ const int offset = findOffset(node) + 14;
+
+ const quint64 timeStamp = (quint64(tree[offset+0]) << 56) + (quint64(tree[offset+1]) << 48) +
+ (quint64(tree[offset+2]) << 40) + (quint64(tree[offset+3]) << 32) +
+ (quint64(tree[offset+4]) << 24) + (quint64(tree[offset+5]) << 16) +
+ (quint64(tree[offset+6]) << 8) + (quint64(tree[offset+7]));
+ if (timeStamp == 0)
+ return QDateTime();
+
+ return QDateTime::fromMSecsSinceEpoch(timeStamp);
+}
+
QStringList QResourceRoot::children(int node) const
{
if(node == -1)
@@ -829,9 +865,9 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
const unsigned char *name, const unsigned char *data)
{
QMutexLocker lock(resourceMutex());
- if(version == 0x01 && resourceList()) {
+ if ((version == 0x01 || version == 0x2) && resourceList()) {
bool found = false;
- QResourceRoot res(tree, name, data);
+ QResourceRoot res(version, tree, name, data);
for(int i = 0; i < resourceList()->size(); ++i) {
if(*resourceList()->at(i) == res) {
found = true;
@@ -839,7 +875,7 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
}
}
if(!found) {
- QResourceRoot *root = new QResourceRoot(tree, name, data);
+ QResourceRoot *root = new QResourceRoot(version, tree, name, data);
root->ref.ref();
resourceList()->append(root);
}
@@ -852,8 +888,8 @@ Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tre
const unsigned char *name, const unsigned char *data)
{
QMutexLocker lock(resourceMutex());
- if(version == 0x01 && resourceList()) {
- QResourceRoot res(tree, name, data);
+ if ((version == 0x01 || version == 0x02) && resourceList()) {
+ QResourceRoot res(version, tree, name, data);
for(int i = 0; i < resourceList()->size(); ) {
if(*resourceList()->at(i) == res) {
QResourceRoot *root = resourceList()->takeAt(i);
@@ -919,9 +955,9 @@ public:
if (size >= 0 && (tree_offset >= size || data_offset >= size || name_offset >= size))
return false;
- if(version == 0x01) {
+ if (version == 0x01 || version == 0x02) {
buffer = b;
- setSource(b+tree_offset, b+name_offset, b+data_offset);
+ setSource(version, b+tree_offset, b+name_offset, b+data_offset);
return true;
}
return false;
@@ -1430,8 +1466,11 @@ QString QResourceFileEngine::owner(FileOwner) const
return QString();
}
-QDateTime QResourceFileEngine::fileTime(FileTime) const
+QDateTime QResourceFileEngine::fileTime(FileTime time) const
{
+ Q_D(const QResourceFileEngine);
+ if (time == ModificationTime)
+ return d->resource.lastModified();
return QDateTime();
}
diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h
index a50bbbdaca..895cf0456e 100644
--- a/src/corelib/io/qresource.h
+++ b/src/corelib/io/qresource.h
@@ -69,6 +69,7 @@ public:
bool isCompressed() const;
qint64 size() const;
const uchar *data() const;
+ QDateTime lastModified() const;
static void addSearchPath(const QString &path);
static QStringList searchPaths();
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index 18772d2816..c8ac554cd4 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -203,6 +203,12 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
}
if (text || pass1)
lib.writeChar('\n');
+
+ // last modified time stamp
+ const QDateTime lastModified = m_fileInfo.lastModified();
+ lib.writeNumber8(quint64(lastModified.isValid() ? lastModified.toMSecsSinceEpoch() : 0));
+ if (text || pass1)
+ lib.writeChar('\n');
}
qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
@@ -833,6 +839,38 @@ void RCCResourceLibrary::writeNumber4(quint32 number)
}
}
+void RCCResourceLibrary::writeNumber8(quint64 number)
+{
+ if (m_format == RCCResourceLibrary::Pass2) {
+ m_outDevice->putChar(char(number >> 56));
+ m_outDevice->putChar(char(number >> 48));
+ m_outDevice->putChar(char(number >> 40));
+ m_outDevice->putChar(char(number >> 32));
+ m_outDevice->putChar(char(number >> 24));
+ m_outDevice->putChar(char(number >> 16));
+ m_outDevice->putChar(char(number >> 8));
+ m_outDevice->putChar(char(number));
+ } else if (m_format == RCCResourceLibrary::Binary) {
+ writeChar(number >> 56);
+ writeChar(number >> 48);
+ writeChar(number >> 40);
+ writeChar(number >> 32);
+ writeChar(number >> 24);
+ writeChar(number >> 16);
+ writeChar(number >> 8);
+ writeChar(number);
+ } else {
+ writeHex(number >> 56);
+ writeHex(number >> 48);
+ writeHex(number >> 40);
+ writeHex(number >> 32);
+ writeHex(number >> 24);
+ writeHex(number >> 16);
+ writeHex(number >> 8);
+ writeHex(number);
+ }
+}
+
bool RCCResourceLibrary::writeHeader()
{
if (m_format == C_Code || m_format == Pass1) {
@@ -1076,7 +1114,7 @@ bool RCCResourceLibrary::writeInitializer()
if (m_root) {
writeString(" ");
writeAddNamespaceFunction("qRegisterResourceData");
- writeString("\n (0x01, qt_resource_struct, "
+ writeString("\n (0x02, qt_resource_struct, "
"qt_resource_name, qt_resource_data);\n");
}
writeString(" return 1;\n");
@@ -1097,7 +1135,7 @@ bool RCCResourceLibrary::writeInitializer()
if (m_root) {
writeString(" ");
writeAddNamespaceFunction("qUnregisterResourceData");
- writeString("\n (0x01, qt_resource_struct, "
+ writeString("\n (0x02, qt_resource_struct, "
"qt_resource_name, qt_resource_data);\n");
}
writeString(" return 1;\n");
@@ -1114,10 +1152,10 @@ bool RCCResourceLibrary::writeInitializer()
} else if (m_format == Binary) {
int i = 4;
char *p = m_out.data();
- p[i++] = 0; // 0x01
+ p[i++] = 0; // 0x02
p[i++] = 0;
p[i++] = 0;
- p[i++] = 1;
+ p[i++] = 2;
p[i++] = (m_treeOffset >> 24) & 0xff;
p[i++] = (m_treeOffset >> 16) & 0xff;
diff --git a/src/tools/rcc/rcc.h b/src/tools/rcc/rcc.h
index 8d0d83e00c..157cd4809f 100644
--- a/src/tools/rcc/rcc.h
+++ b/src/tools/rcc/rcc.h
@@ -118,6 +118,7 @@ private:
void writeHex(quint8 number);
void writeNumber2(quint16 number);
void writeNumber4(quint32 number);
+ void writeNumber8(quint64 number);
void writeChar(char c) { m_out.append(c); }
void writeByteArray(const QByteArray &);
void write(const char *, int len);
diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
index 561ab193c6..7fdd00876f 100644
--- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
+++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
@@ -55,6 +55,7 @@ private slots:
void searchPath();
void doubleSlashInRoot();
void setLocale();
+ void lastModified();
private:
const QString m_runtimeResourceRcc;
@@ -489,6 +490,20 @@ void tst_QResourceEngine::setLocale()
QLocale::setDefault(QLocale::system());
}
+void tst_QResourceEngine::lastModified()
+{
+ {
+ QFileInfo fi(":/");
+ QVERIFY(fi.exists());
+ QVERIFY2(!fi.lastModified().isValid(), qPrintable(fi.lastModified().toString()));
+ }
+ {
+ QFileInfo fi(":/search_file.txt");
+ QVERIFY(fi.exists());
+ QVERIFY(fi.lastModified().isValid());
+ }
+}
+
QTEST_MAIN(tst_QResourceEngine)
#include "tst_qresourceengine.moc"
diff --git a/tests/auto/tools/rcc/data/images/images.expected b/tests/auto/tools/rcc/data/images/images.expected
index 1f0157d51c..eb5d9222c8 100644
--- a/tests/auto/tools/rcc/data/images/images.expected
+++ b/tests/auto/tools/rcc/data/images/images.expected
@@ -79,16 +79,22 @@ static const unsigned char qt_resource_name[] = {
static const unsigned char qt_resource_struct[] = {
// :
0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
// :/images
0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x2,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
// :/images/subdir
0x0,0x0,0x0,0x12,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x5,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
// :/images/square.png
0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xa9,
+TIMESTAMP:images/square.png
// :/images/circle.png
0x0,0x0,0x0,0x24,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
+TIMESTAMP:images/circle.png
// :/images/subdir/triangle.png
0x0,0x0,0x0,0x58,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0xb,
+TIMESTAMP:images/subdir/triangle.png
};
@@ -120,7 +126,7 @@ int QT_RCC_MANGLE_NAMESPACE(qInitResources)();
int QT_RCC_MANGLE_NAMESPACE(qInitResources)()
{
QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
- (0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
+ (0x02, qt_resource_struct, qt_resource_name, qt_resource_data);
return 1;
}
@@ -128,7 +134,7 @@ int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)();
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)()
{
QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
- (0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
+ (0x02, qt_resource_struct, qt_resource_name, qt_resource_data);
return 1;
}
diff --git a/tests/auto/tools/rcc/tst_rcc.cpp b/tests/auto/tools/rcc/tst_rcc.cpp
index 8d95d06e30..54a2854ede 100644
--- a/tests/auto/tools/rcc/tst_rcc.cpp
+++ b/tests/auto/tools/rcc/tst_rcc.cpp
@@ -92,12 +92,23 @@ static QString doCompare(const QStringList &actual, const QStringList &expected)
QByteArray ba;
for (int i = 0, n = expected.size(); i != n; ++i) {
- if (expected.at(i).startsWith("IGNORE:"))
+ QString expectedLine = expected.at(i);
+ if (expectedLine.startsWith("IGNORE:"))
continue;
- if (expected.at(i) != actual.at(i)) {
+ if (expectedLine.startsWith("TIMESTAMP:")) {
+ const QString relativePath = expectedLine.mid(strlen("TIMESTAMP:"));
+ const quint64 timeStamp = QFileInfo(relativePath).lastModified().toMSecsSinceEpoch();
+ expectedLine.clear();
+ for (int shift = 56; shift >= 0; shift -= 8) {
+ expectedLine.append(QLatin1String("0x"));
+ expectedLine.append(QString::number(quint8(timeStamp >> shift), 16));
+ expectedLine.append(QLatin1Char(','));
+ }
+ }
+ if (expectedLine != actual.at(i)) {
qDebug() << "LINES" << i << "DIFFER";
ba.append(
- "\n<<<<<< actual\n" + actual.at(i) + "\n======\n" + expected.at(i)
+ "\n<<<<<< actual\n" + actual.at(i) + "\n======\n" + expectedLine
+ "\n>>>>>> expected\n"
);
}