src/corelib/plugin/qlibrary.cpp File Reference

#include "qplatformdefs.h"
#include "qlibrary.h"
#include "qlibrary_p.h"
#include <qstringlist.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qmutex.h>
#include <qmap.h>
#include <qsettings.h>
#include <qdatetime.h>
#include <errno.h>
#include <qdebug.h>
#include <qvector.h>

Include dependency graph for qlibrary.cpp:

Go to the source code of this file.

Classes

struct  qt_token_info

Defines

#define QLIBRARY_AS_DEBUG   true
#define QT_NO_DEBUG_PLUGIN_CHECK

Typedefs

typedef QMap< QString, QLibraryPrivate * > LibraryMap

Functions

static int qt_tokenize (const char *s, ulong s_len, ulong *advance, qt_token_info &token_info)
static bool qt_parse_pattern (const char *s, uint *version, bool *debug, QByteArray *key)
static long qt_find_pattern (const char *s, ulong s_len, const char *pattern, ulong p_len)
static bool qt_unix_query (const QString &library, uint *version, bool *debug, QByteArray *key, QLibraryPrivate *lib=0)
bool qt_debug_component ()


Define Documentation

#define QLIBRARY_AS_DEBUG   true

Definition at line 51 of file qlibrary.cpp.

Referenced by QLibraryPrivate::isPlugin().

#define QT_NO_DEBUG_PLUGIN_CHECK

Definition at line 57 of file qlibrary.cpp.


Typedef Documentation

typedef QMap<QString, QLibraryPrivate*> LibraryMap

Definition at line 401 of file qlibrary.cpp.


Function Documentation

bool qt_debug_component (  ) 

Definition at line 985 of file qlibrary.cpp.

References qgetenv().

Referenced by QLibraryPrivate::isPlugin(), QFactoryLoader::QFactoryLoader(), qt_unix_query(), and QPluginLoader::setFileName().

00986 {
00987 #if defined(QT_DEBUG_COMPONENT)
00988     return true;    //compatibility?
00989 #else
00990     static int debug_env = -1;
00991     if (debug_env == -1)
00992        debug_env = ::qgetenv("QT_DEBUG_PLUGINS").toInt();
00993 
00994     return debug_env != 0;
00995 #endif
00996 }

Here is the call graph for this function:

static long qt_find_pattern ( const char *  s,
ulong  s_len,
const char *  pattern,
ulong  p_len 
) [static]

Definition at line 284 of file qlibrary.cpp.

References i, and QByteArray::qstrncmp().

Referenced by qt_unix_query().

00286 {
00287     /*
00288       we search from the end of the file because on the supported
00289       systems, the read-only data/text segments are placed at the end
00290       of the file.  HOWEVER, when building with debugging enabled, all
00291       the debug symbols are placed AFTER the data/text segments.
00292 
00293       what does this mean?  when building in release mode, the search
00294       is fast because the data we are looking for is at the end of the
00295       file... when building in debug mode, the search is slower
00296       because we have to skip over all the debugging symbols first
00297     */
00298 
00299     if (! s || ! pattern || p_len > s_len) return -1;
00300     ulong i, hs = 0, hp = 0, delta = s_len - p_len;
00301 
00302     for (i = 0; i < p_len; ++i) {
00303         hs += s[delta + i];
00304         hp += pattern[i];
00305     }
00306     i = delta;
00307     for (;;) {
00308         if (hs == hp && qstrncmp(s + i, pattern, p_len) == 0)
00309             return i;
00310         if (i == 0)
00311             break;
00312         --i;
00313         hs -= s[i + p_len];
00314         hs += s[i];
00315     }
00316 
00317     return -1;
00318 }

Here is the call graph for this function:

static bool qt_parse_pattern ( const char *  s,
uint *  version,
bool *  debug,
QByteArray key 
) [static]

Definition at line 234 of file qlibrary.cpp.

References key, qt_token_info::lengths, m, n, p, parse(), QByteArray::qstrlen(), QByteArray::qstrncmp(), qt_tokenize(), and qt_token_info::results.

Referenced by QLibraryPrivate::isPlugin(), and qt_unix_query().

00235 {
00236     bool ret = true;
00237 
00238     qt_token_info pinfo("=\n", 2);
00239     int parse;
00240     ulong at = 0, advance, parselen = qstrlen(s);
00241     do {
00242         parse = qt_tokenize(s + at, parselen, &advance, pinfo);
00243         if (parse == -1) {
00244             ret = false;
00245             break;
00246         }
00247 
00248         at += advance;
00249         parselen -= advance;
00250 
00251         if (qstrncmp("version", pinfo.results[0], pinfo.lengths[0]) == 0) {
00252             // parse version string
00253             qt_token_info pinfo2("..-", 3);
00254             if (qt_tokenize(pinfo.results[1], pinfo.lengths[1],
00255                               &advance, pinfo2) != -1) {
00256                 QByteArray m(pinfo2.results[0], pinfo2.lengths[0]);
00257                 QByteArray n(pinfo2.results[1], pinfo2.lengths[1]);
00258                 QByteArray p(pinfo2.results[2], pinfo2.lengths[2]);
00259                 *version  = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt();
00260             } else {
00261                 ret = false;
00262                 break;
00263             }
00264         } else if (qstrncmp("debug", pinfo.results[0], pinfo.lengths[0]) == 0) {
00265             *debug = qstrncmp("true", pinfo.results[1], pinfo.lengths[1]) == 0;
00266         } else if (qstrncmp("buildkey", pinfo.results[0],
00267                               pinfo.lengths[0]) == 0){
00268             // save buildkey
00269             *key = QByteArray(pinfo.results[1], pinfo.lengths[1] + 1);
00270         }
00271     } while (parse == 1 && parselen > 0);
00272 
00273     return ret;
00274 }

Here is the call graph for this function:

static int qt_tokenize ( const char *  s,
ulong  s_len,
ulong *  advance,
qt_token_info token_info 
) [static]

Definition at line 179 of file qlibrary.cpp.

References qt_token_info::field_count, qt_token_info::fields, qt_token_info::lengths, and qt_token_info::results.

Referenced by qt_parse_pattern().

00181 {
00182     ulong pos = 0, field = 0, fieldlen = 0;
00183     char current;
00184     int ret = -1;
00185     *advance = 0;
00186     for (;;) {
00187         current = s[pos];
00188 
00189         // next char
00190         ++pos;
00191         ++fieldlen;
00192         ++*advance;
00193 
00194         if (! current || pos == s_len + 1) {
00195             // save result
00196             token_info.results[(int)field] = s;
00197             token_info.lengths[(int)field] = fieldlen - 1;
00198 
00199             // end of string
00200             ret = 0;
00201             break;
00202         }
00203 
00204         if (current == token_info.fields[field]) {
00205             // save result
00206             token_info.results[(int)field] = s;
00207             token_info.lengths[(int)field] = fieldlen - 1;
00208 
00209             // end of field
00210             fieldlen = 0;
00211             ++field;
00212             if (field == token_info.field_count - 1) {
00213                 // parse ok
00214                 ret = 1;
00215             }
00216             if (field == token_info.field_count) {
00217                 // done parsing
00218                 break;
00219             }
00220 
00221             // reset string and its length
00222             s = s + pos;
00223             s_len -= pos;
00224             pos = 0;
00225         }
00226     }
00227 
00228     return ret;
00229 }

static bool qt_unix_query ( const QString library,
uint *  version,
bool *  debug,
QByteArray key,
QLibraryPrivate lib = 0 
) [static]

Definition at line 330 of file qlibrary.cpp.

References QFile::close(), data, QFile::encodeName(), QIODevice::errorString(), QFile::handle(), key, library, MAP_FAILED, QFile::open(), QByteArray::qstrlen(), qt_debug_component(), qt_error_string(), qt_find_pattern(), qt_parse_pattern(), qWarning(), QIODevice::readAll(), QIODevice::ReadOnly, and QFile::size().

Referenced by QLibraryPrivate::isPlugin().

00331 {
00332     QFile file(library);
00333     if (!file.open(QIODevice::ReadOnly)) {
00334         if (lib)
00335             lib->errorString = file.errorString();
00336         if (qt_debug_component()) {
00337             qWarning("%s: %s", (const char*) QFile::encodeName(library),
00338                 qPrintable(qt_error_string(errno)));
00339         }
00340         return false;
00341     }
00342 
00343     QByteArray data;
00344     char *filedata = 0;
00345     ulong fdlen = 0;
00346 
00347 #ifdef USE_MMAP
00348     char *mapaddr = 0;
00349     size_t maplen = file.size();
00350     mapaddr = (char *) mmap(mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0);
00351     if (mapaddr != MAP_FAILED) {
00352         // mmap succeeded
00353         filedata = mapaddr;
00354         fdlen = maplen;
00355     } else {
00356         // mmap failed
00357         if (qt_debug_component()) {
00358             qWarning("mmap: %s", qPrintable(qt_error_string(errno)));
00359         }
00360         if (lib)
00361             lib->errorString = QLibrary::tr("Could not mmap '%1': %2")
00362                 .arg(library)
00363                 .arg(qt_error_string());
00364 #endif // USE_MMAP
00365         // try reading the data into memory instead
00366         data = file.readAll();
00367         filedata = data.data();
00368         fdlen = data.size();
00369 #ifdef USE_MMAP
00370     }
00371 #endif // USE_MMAP
00372 
00373     // verify that the pattern is present in the plugin
00374     const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA";
00375     const ulong plen = qstrlen(pattern);
00376     long pos = qt_find_pattern(filedata, fdlen, pattern, plen);
00377 
00378     bool ret = false;
00379     if (pos >= 0)
00380         ret = qt_parse_pattern(filedata + pos, version, debug, key);
00381 
00382     if (!ret && lib)
00383         lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
00384 #ifdef USE_MMAP
00385     if (mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0) {
00386         if (qt_debug_component())
00387             qWarning("munmap: %s", qPrintable(qt_error_string(errno)));
00388         if (lib)
00389             lib->errorString = QLibrary::tr("Could not unmap '%1': %2")
00390                 .arg(library)
00391                 .arg( qt_error_string() );
00392     }
00393 #endif // USE_MMAP
00394 
00395     file.close();
00396     return ret;
00397 }

Here is the call graph for this function:


Generated on Thu Mar 15 12:44:50 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1