From f571457523d2986687017a8469ce4173fe46ec99 Mon Sep 17 00:00:00 2001 From: goro <qtc-committer@nokia.com> Date: Fri, 16 Jan 2009 13:31:00 +0100 Subject: [PATCH] Check in qtlibspatcher from change 321515 plus compile fixes --- src/tools/qtlibspatcher/binpatch.cpp | 210 +++++++++++++++++ src/tools/qtlibspatcher/binpatch.h | 74 ++++++ src/tools/qtlibspatcher/qtlibspatcher.pro | 15 ++ src/tools/qtlibspatcher/qtlibspatchermain.cpp | 219 ++++++++++++++++++ 4 files changed, 518 insertions(+) create mode 100644 src/tools/qtlibspatcher/binpatch.cpp create mode 100644 src/tools/qtlibspatcher/binpatch.h create mode 100644 src/tools/qtlibspatcher/qtlibspatcher.pro create mode 100644 src/tools/qtlibspatcher/qtlibspatchermain.cpp diff --git a/src/tools/qtlibspatcher/binpatch.cpp b/src/tools/qtlibspatcher/binpatch.cpp new file mode 100644 index 00000000000..e2fd4cc2f2e --- /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 00000000000..a6867d39fbd --- /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 00000000000..fb0b51c9c9e --- /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 00000000000..f6b2da18f36 --- /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; +} -- GitLab