summaryrefslogtreecommitdiff
path: root/src/tools/qtlibspatcher
diff options
context:
space:
mode:
authorgoro <qtc-committer@nokia.com>2009-01-16 13:31:00 +0100
committergoro <qtc-committer@nokia.com>2009-01-22 17:13:40 +0100
commitf571457523d2986687017a8469ce4173fe46ec99 (patch)
tree4087cd7d514ce3e1dc48be80a778a859fc33ccfb /src/tools/qtlibspatcher
parent866ab744fb325e40cab7acefcaf2d27b3e6450cd (diff)
downloadqt-creator-f571457523d2986687017a8469ce4173fe46ec99.tar.gz
Check in qtlibspatcher from change 321515 plus compile fixes
Diffstat (limited to 'src/tools/qtlibspatcher')
-rw-r--r--src/tools/qtlibspatcher/binpatch.cpp210
-rw-r--r--src/tools/qtlibspatcher/binpatch.h74
-rw-r--r--src/tools/qtlibspatcher/qtlibspatcher.pro15
-rw-r--r--src/tools/qtlibspatcher/qtlibspatchermain.cpp219
4 files changed, 518 insertions, 0 deletions
diff --git a/src/tools/qtlibspatcher/binpatch.cpp b/src/tools/qtlibspatcher/binpatch.cpp
new file mode 100644
index 0000000000..e2fd4cc2f2
--- /dev/null
+++ b/src/tools/qtlibspatcher/binpatch.cpp
@@ -0,0 +1,210 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 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 GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#include <cstdio>
+#include <cstring>
+#include <locale>
+
+#include "binpatch.h"
+
+// returns positive value if it finds a null termination inside the buffer
+long BinPatch::getBufferStringLength(char *data, char *end)
+{
+ long size = 0;
+ while (data < end) {
+ if (*data == '\0')
+ return size;
+ ++data;
+ ++size;
+ }
+
+ return -1;
+}
+
+// returns true if data ends with one of the tokens. (Sep. with ;)
+bool BinPatch::endsWithTokens(const char *data)
+{
+ if(strlen(endTokens) > 0) {
+ char endstmp[1024];
+ ulong tlen = ulong(strlen(data));
+
+ if(strlen(endTokens) >= sizeof(endstmp))
+ return false;
+
+ strcpy(endstmp, endTokens);
+
+ char *token = strtok(endstmp, ";");
+
+ while(token != NULL) {
+ // check if it ends with the token
+ if ((tlen >= strlen(token))
+ && (strcasecmp((data+tlen)-strlen(token), token) == 0))
+ return true;
+ token = strtok(NULL, ";");
+ }
+ } else {
+ return true; //true if no tokens
+ }
+
+ return false; //no matching tokens
+}
+
+bool BinPatch::patchHelper(char *inbuffer, const char *oldstr, const char *newstr, size_t len, long *rw)
+{
+ char nc1 = *oldstr;
+ char nc2 = 0;
+ char *inend = inbuffer + len;
+ size_t oldlen = strlen(oldstr);
+ size_t newlen = strlen(newstr);
+ char *instart = inbuffer;
+ *rw = 0;
+ bool write = true;
+
+ isupper(nc1) ? nc2 = tolower(nc1) : nc2 = toupper(nc1);
+
+ while(inbuffer < inend) {
+ if ((*inbuffer == nc1) || (*inbuffer == nc2)) {
+ if (inbuffer > (inend-oldlen) || inbuffer > (inend-newlen)) {
+ *rw = (long)(inend-inbuffer); //rewind, not enough to make a compare
+ break;
+ }
+
+ if (strncasecmp(inbuffer, oldstr, oldlen) == 0) {
+ if (useLength && (instart == inbuffer)) {
+ *rw = (long)(len+1); //we don't have access to the length byte, rewind all + 1!
+ write = false;
+ break;
+ }
+
+ long oldsize = -1;
+ if (useLength) { //VC60
+ oldsize = (unsigned char)(*(inbuffer-1));
+
+ // vc60 pdb files sometimes uses 0A, then it should be null terminated
+ if (oldsize < (long)oldlen) {
+ if (oldsize != 0x0A) { //strange case... skip
+ inbuffer+=oldlen;
+ continue;
+ }
+
+ oldsize = getBufferStringLength(inbuffer, inend);
+
+ if (oldsize < 0) {
+ *rw = (long)(inend-inbuffer); //rewind, entire string not in buffer
+ break;
+ }
+ }
+
+ if (inbuffer > (inend-oldsize)) {
+ *rw = (long)(inend-inbuffer); //rewind, entire string not in buffer
+ break;
+ }
+ } else { //VC7x
+ oldsize = getBufferStringLength(inbuffer, inend);
+ if (oldsize < 0) {
+ *rw = (long)(inend-inbuffer); //rewind, entire string not in buffer
+ break;
+ }
+ }
+
+ char oldPath[1024];
+ if (oldsize > (long)sizeof(oldPath)) {
+ //at least don't crash
+ inbuffer+=oldsize;
+ continue;
+ }
+ memset(oldPath, '\0', sizeof(oldPath));
+ strncpy(oldPath, newstr, newlen);
+
+ if (insertReplace)
+ strncat(oldPath, inbuffer+oldlen, oldsize-oldlen);
+
+ // just replace if it ends with a token in endTokens
+ if (endsWithTokens(oldPath)) {
+ if (oldsize < (long)strlen(oldPath))
+ oldsize = (long)strlen(oldPath);
+
+ memcpy(inbuffer, oldPath, oldsize);
+ }
+
+ inbuffer+=oldsize;
+ continue;
+ }
+ }
+ ++inbuffer;
+ }
+
+ return write;
+}
+
+bool BinPatch::patch(const char *oldstr, const char *newstr)
+{
+ size_t oldlen = strlen(oldstr);
+ size_t newlen = strlen(newstr);
+
+ if ((!fileName || strlen(fileName) < 1)
+ || (!oldstr || oldlen < 1)
+ || (!newstr || newlen < 1))
+ return false;
+
+ FILE *input;
+
+ if (!(input = fopen(fileName, "r+b")))
+ {
+ fprintf(stderr, "Cannot open file %s!\n", fileName);
+ return false;
+ }
+
+ char data[60000];
+ long rw = 0;
+ long offset = 0;
+
+ size_t len;
+ len = fread(data, sizeof(char), sizeof(data), input);
+
+ do {
+ if (patchHelper(data, oldstr, newstr, len, &rw)) {
+ fseek(input, offset, SEEK_SET); //overwrite
+ fwrite(data, sizeof(char), len, input);
+ }
+
+ offset += (long)((-rw) + len);
+ if (fseek(input, offset, SEEK_SET) != 0)
+ break;
+ len = fread(data, sizeof(char), sizeof(data), input);
+ } while(!(feof(input) && (len <= oldlen || len <= newlen)));
+
+ fclose(input);
+
+ return true;
+}
diff --git a/src/tools/qtlibspatcher/binpatch.h b/src/tools/qtlibspatcher/binpatch.h
new file mode 100644
index 0000000000..a6867d39fb
--- /dev/null
+++ b/src/tools/qtlibspatcher/binpatch.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 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 GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#ifndef BINPATCH_H
+#define BINPATCH_H
+
+#include <string.h>
+
+typedef unsigned long ulong;
+typedef unsigned int uint;
+
+class BinPatch
+{
+public:
+ BinPatch(const char *file)
+ : useLength(false), insertReplace(false)
+ {
+ strcpy(endTokens, "");
+ strcpy(fileName, file);
+ }
+
+ void enableUseLength(bool enabled)
+ { useLength = enabled; }
+ void enableInsertReplace(bool enabled)
+ { insertReplace = enabled; }
+ void setEndTokens(const char *tokens)
+ { strcpy(endTokens, tokens); }
+
+ bool patch(const char *oldstr, const char *newstr);
+
+private:
+ long getBufferStringLength(char *data, char *end);
+ bool endsWithTokens(const char *data);
+
+ bool patchHelper(char *inbuffer, const char *oldstr,
+ const char *newstr, size_t len, long *rw);
+
+ bool useLength;
+ bool insertReplace;
+ char endTokens[1024];
+ char fileName[1024];
+};
+
+#endif
diff --git a/src/tools/qtlibspatcher/qtlibspatcher.pro b/src/tools/qtlibspatcher/qtlibspatcher.pro
new file mode 100644
index 0000000000..fb0b51c9c9
--- /dev/null
+++ b/src/tools/qtlibspatcher/qtlibspatcher.pro
@@ -0,0 +1,15 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Di 8. Jul 15:08:13 2008
+######################################################################
+
+CONFIG += console
+QT -= gui
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+DESTDIR = ./
+
+# Input
+HEADERS += binpatch.h
+SOURCES += binpatch.cpp qtlibspatchermain.cpp
diff --git a/src/tools/qtlibspatcher/qtlibspatchermain.cpp b/src/tools/qtlibspatcher/qtlibspatchermain.cpp
new file mode 100644
index 0000000000..f6b2da18f3
--- /dev/null
+++ b/src/tools/qtlibspatcher/qtlibspatchermain.cpp
@@ -0,0 +1,219 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 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 GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#include "binpatch.h"
+#include <stdio.h>
+
+#include <QFile>
+#include <QRegExp>
+#include <QTextStream>
+#include <QString>
+#include <QtCore/QDebug>
+
+bool patchBinaryWithQtPathes(const char *fileName, const char *baseQtPath)
+{
+ bool result = true;
+
+ static const struct
+ {
+ const char *variable;
+ const char *subDirectory;
+ } variables[] = {
+ {"qt_prfxpath=", ""},
+ {"qt_docspath=", "/doc"},
+ {"qt_hdrspath=", "/include"},
+ {"qt_libspath=", "/lib"},
+ {"qt_binspath=", "/bin"},
+ {"qt_plugpath=", "/plugins"},
+ {"qt_datapath=", ""},
+ {"qt_trnspath=", "/translations"},
+ {"qt_xmplpath=", "/examples"},
+ {"qt_demopath=", "/demos"}
+ };
+
+ for (int i = 0; i < sizeof(variables)/sizeof(variables[0]); i++) {
+ char newStr[256] = "";
+ strncpy(newStr, variables[i].variable, sizeof(newStr));
+ newStr[sizeof(newStr) - 1] = 0;
+ strncat(newStr, baseQtPath, sizeof(newStr) - strlen(newStr) - 1);
+ newStr[sizeof(newStr) - 1] = 0;
+ strncat(newStr, variables[i].subDirectory, sizeof(newStr) - strlen(newStr) - 1);
+ newStr[sizeof(newStr) - 1] = 0;
+ BinPatch binFile(fileName);
+ if (!binFile.patch(variables[i].variable, newStr)) {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+}
+
+bool patchBinariesWithQtPathes(const char *baseQtPath)
+{
+ bool result = true;
+
+ static const char *filesToPatch[] = {
+ "/bin/qmake.exe",
+ "/bin/QtCore4.dll",
+ "/bin/QtCored4.dll"
+ };
+
+ for (int i = 0; i < sizeof(filesToPatch)/sizeof(filesToPatch[0]); i++) {
+ char fileName[FILENAME_MAX] = "";
+ strncpy(fileName, baseQtPath, sizeof(fileName));
+ fileName[sizeof(fileName)-1] = '\0';
+ strncat(fileName, filesToPatch[i], sizeof(fileName) - strlen(fileName) - 1);
+ fileName[sizeof(fileName)-1] = '\0';
+ if (!patchBinaryWithQtPathes(fileName, baseQtPath)) {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+}
+
+bool patchDebugLibrariesWithQtPath(const char *baseQtPath)
+{
+ bool result = true;
+
+ static const struct
+ {
+ const char *fileName;
+ const char *sourceLocation;
+ } libraries[] = {
+ {"/bin/Qt3Supportd4.dll", "/src/qt3support/"},
+ {"/bin/QtCored4.dll", "/src/corelib/"},
+ {"/bin/QtGuid4.dll", "/src/gui/"},
+ {"/bin/QtHelpd4.dll", "/tools/assistant/lib/"},
+ {"/bin/QtNetworkd4.dll", "/src/network/"},
+ {"/bin/QtOpenGLd4.dll", "/src/opengl/"},
+ {"/bin/QtScriptd4.dll", "/src/script/"},
+ {"/bin/QtSqld4.dll", "/src/sql/"},
+ {"/bin/QtSvgd4.dll", "/src/svg/"},
+ {"/bin/QtTestd4.dll", "/src/testlib/"},
+ {"/bin/QtWebKitd4.dll", "/src/3rdparty/webkit/WebCore/"},
+ {"/bin/QtXmld4.dll", "/src/xml/"},
+ {"/bin/QtXmlPatternsd4.dll", "/src/xmlpatterns/"},
+ {"/plugins/accessible/qtaccessiblecompatwidgetsd4.dll", "/src/plugins/accessible/compat/"},
+ {"/plugins/accessible/qtaccessiblewidgetsd4.dll", "/src/plugins/accessible/widgets/"},
+ {"/plugins/codecs/qcncodecsd4.dll", "/src/plugins/codecs/cn/"},
+ {"/plugins/codecs/qjpcodecsd4.dll", "/src/plugins/codecs/jp/"},
+ {"/plugins/codecs/qkrcodecsd4.dll", "/src/plugins/codecs/kr/"},
+ {"/plugins/codecs/qtwcodecsd4.dll", "/src/plugins/codecs/tw/"},
+ {"/plugins/iconengines/qsvgicond4.dll", "/src/plugins/iconengines/svgiconengine/"},
+ {"/plugins/imageformats/qgifd4.dll", "/src/plugins/imageformats/gif/"},
+ {"/plugins/imageformats/qjpegd4.dll", "/src/plugins/imageformats/jpeg/"},
+ {"/plugins/imageformats/qmngd4.dll", "/src/plugins/imageformats/mng/"},
+ {"/plugins/imageformats/qsvgd4.dll", "/src/plugins/imageformats/svg/"},
+ {"/plugins/imageformats/qtiffd4.dll", "/src/plugins/imageformats/tiff/"},
+ {"/plugins/sqldrivers/qsqlited4.dll", "/src/plugins/sqldrivers/sqlite/"},
+// {"/plugins/sqldrivers/qsqlodbcd4.dll", "/src/plugins/sqldrivers/odbc/"}
+ };
+
+ for (int i = 0; i < sizeof(libraries)/sizeof(libraries[0]); i++) {
+ char fileName[FILENAME_MAX] = "";
+ strncpy(fileName, baseQtPath, sizeof(fileName));
+ fileName[sizeof(fileName)-1] = '\0';
+ strncat(fileName, libraries[i].fileName, sizeof(fileName) - strlen(fileName) - 1);
+ fileName[sizeof(fileName)-1] = '\0';
+
+ char oldSourcePath[FILENAME_MAX] =
+ "C:/qt-greenhouse/Trolltech/Code_less_create_more/Trolltech/Code_less_create_more/Troll/4.4.3";
+ strncat(oldSourcePath, libraries[i].sourceLocation, sizeof(oldSourcePath) - strlen(oldSourcePath) - 1);
+ oldSourcePath[sizeof(oldSourcePath)-1] = '\0';
+
+ char newSourcePath[FILENAME_MAX] = "";
+ strncpy(newSourcePath, baseQtPath, sizeof(newSourcePath));
+ newSourcePath[sizeof(newSourcePath)-1] = '\0';
+ strncat(newSourcePath, libraries[i].sourceLocation, sizeof(newSourcePath) - strlen(newSourcePath) - 1);
+ newSourcePath[sizeof(newSourcePath)-1] = '\0';
+
+ BinPatch binFile(fileName);
+ if (!binFile.patch(oldSourcePath, newSourcePath)) {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+}
+
+void patchQMakeSpec(const char *path)
+{
+ QString baseQtPath(path);
+ QFile f(baseQtPath + "/mkspecs/default/qmake.conf");
+ f.open(QIODevice::ReadOnly);
+ QTextStream in(&f);
+ QString all = in.readAll();
+ f.close();
+ // Old value is QMAKESPEC_ORIGINAL=C:/somepath/mkspecs/amakespce
+ // New value should be QMAKESPEC_ORIGINAL=baseQtPath/mkspec/amakespec
+ // We don't care to match the line end we simply match to the end of the file
+ QRegExp regExp("(QMAKESPEC_ORIGINAL=).*(/mkspecs/.*)");
+ all.replace(regExp, "\\1"+baseQtPath+"\\2");
+
+ f.open(QIODevice::WriteOnly);
+ QTextStream out(&f);
+ out << all;
+}
+
+int main(int argc, char *args[])
+{
+ if (argc != 2) {
+ printf("Please provide a QTDIR value as parameter.\n"
+ "This is also the location where the binaries are expected\n"
+ "in the \"/bin\" and \"/plugins\" subdirectories.\n");
+ return 1;
+ }
+
+ char baseQtPath[FILENAME_MAX] = "";
+ strncpy(baseQtPath, args[1], sizeof(baseQtPath));
+ baseQtPath[sizeof(baseQtPath)-1] = '\0';
+
+ // Convert backslash to slash
+ for (char *p = baseQtPath; *p != '\0'; p++)
+ if (*p == '\\')
+ *p = '/';
+
+ // Remove trailing slash(es)
+ for (char *p = baseQtPath + strlen(baseQtPath) - 1; p != baseQtPath; p--)
+ if (*p == '/')
+ *p = '\0';
+ else
+ break;
+
+ patchQMakeSpec(baseQtPath);
+ return patchBinariesWithQtPathes(baseQtPath) && patchDebugLibrariesWithQtPath(baseQtPath)?0:1;
+}