📄 qlibrary.cpp
字号:
for the QT_PLUGIN_VERIFICATION_DATA. The advantage of this approach is that we can get the verification data without have to actually load the library. This lets us detect mismatches more safely. Returns false if version/key information is not present, or if the information could not be read. Returns true if version/key information is present and successfully read.*/static bool qt_unix_query(const QString &library, uint *version, bool *debug, QByteArray *key, QLibraryPrivate *lib = 0){ QFile file(library); if (!file.open(QIODevice::ReadOnly)) { if (lib) lib->errorString = file.errorString(); if (qt_debug_component()) { qWarning("%s: %s", (const char*) QFile::encodeName(library), qPrintable(qt_error_string(errno))); } return false; } QByteArray data; char *filedata = 0; ulong fdlen = 0;#ifdef USE_MMAP char *mapaddr = 0; size_t maplen = file.size(); mapaddr = (char *) mmap(mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0); if (mapaddr != MAP_FAILED) { // mmap succeeded filedata = mapaddr; fdlen = maplen; } else { // mmap failed if (qt_debug_component()) { qWarning("mmap: %s", qPrintable(qt_error_string(errno))); } if (lib) lib->errorString = QLibrary::tr("Could not mmap '%1': %2") .arg(library) .arg(qt_error_string());#endif // USE_MMAP // try reading the data into memory instead data = file.readAll(); filedata = data.data(); fdlen = data.size();#ifdef USE_MMAP }#endif // USE_MMAP // verify that the pattern is present in the plugin const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA"; const ulong plen = qstrlen(pattern); long pos = qt_find_pattern(filedata, fdlen, pattern, plen); bool ret = false; if (pos >= 0) ret = qt_parse_pattern(filedata + pos, version, debug, key); if (!ret && lib) lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);#ifdef USE_MMAP if (mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0) { if (qt_debug_component()) qWarning("munmap: %s", qPrintable(qt_error_string(errno))); if (lib) lib->errorString = QLibrary::tr("Could not unmap '%1': %2") .arg(library) .arg( qt_error_string() ); }#endif // USE_MMAP file.close(); return ret;}#endif // Q_OS_UNIX && !Q_OS_MACtypedef QMap<QString, QLibraryPrivate*> LibraryMap;Q_GLOBAL_STATIC(LibraryMap, libraryMap)QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, int verNum) :pHnd(0), fileName(canonicalFileName), majorVerNum(verNum), instance(0), qt_version(0), libraryRefCount(1), libraryUnloadCount(0), pluginState(MightBeAPlugin){ libraryMap()->insert(canonicalFileName, this); }QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, int verNum){ QMutexLocker locker(qt_library_mutex()); if (QLibraryPrivate *lib = libraryMap()->value(fileName)) { lib->libraryRefCount.ref(); return lib; } return new QLibraryPrivate(fileName, verNum);}QLibraryPrivate::~QLibraryPrivate(){ LibraryMap * const map = libraryMap(); if (map) { QLibraryPrivate *that = map->take(fileName); Q_ASSERT(this == that); Q_UNUSED(that); }}void *QLibraryPrivate::resolve(const char *symbol){ if (!pHnd) return 0; return resolve_sys(symbol);}bool QLibraryPrivate::load(){ libraryUnloadCount.ref(); if (pHnd) return true; if (fileName.isEmpty()) return false; return load_sys();}bool QLibraryPrivate::unload(){ if (!pHnd) return false; if (!libraryUnloadCount.deref()) // only unload if ALL QLibrary instance wanted to if (unload_sys()) { instance = 0; pHnd = 0; } return (pHnd == 0);}void QLibraryPrivate::release(){ QMutexLocker locker(qt_library_mutex()); if (!libraryRefCount.deref()) delete this;}bool QLibraryPrivate::loadPlugin(){ if (instance) { libraryUnloadCount.ref(); return true; } if (load()) { instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance"); return instance; } return false;}/*! Returns true if \a fileName has a valid suffix for a loadable library; otherwise returns false. \table \header \i Platform \i Valid suffixes \row \i Windows \i \c .dll \row \i Unix/Linux \i \c .so \row \i AIX \i \c .a \row \i HP-UX \i \c .sl \row \i Mac OS X \i \c .dylib, \c .bundle, \c .so \endtable Trailing versioning numbers on Unix are ignored. */bool QLibrary::isLibrary(const QString &fileName){#if defined(Q_OS_WIN32) return fileName.endsWith(QLatin1String(".dll"));#else QString completeSuffix = QFileInfo(fileName).completeSuffix(); if (completeSuffix.isEmpty()) return false; QStringList suffixes = completeSuffix.split(QLatin1Char('.')); QString suffix = suffixes.first();# if defined(Q_OS_DARWIN) // On Mac, libs look like libmylib.1.0.0.dylib const QString lastSuffix = suffixes.at(suffixes.count() - 1); const QString firstSuffix = suffixes.at(0); bool valid = (lastSuffix == QLatin1String("dylib") || firstSuffix == QLatin1String("so") || firstSuffix == QLatin1String("bundle")); return valid;# elif defined(Q_OS_HPUX)/* See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF": "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit), the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix." */ bool valid = (suffix == QLatin1String("sl"));# if defined __ia64 valid = valid || (suffix == QLatin1String("so"));# endif# elif defined(Q_OS_AIX) bool valid = (suffix == QLatin1String("a") || suffix == QLatin1String("so"));# elif defined(Q_OS_UNIX) bool valid = (suffix == QLatin1String("so"));# else bool valid = false;# endif for (int i = 1; i < suffixes.count() && valid; ++i) suffixes.at(i).toInt(&valid); return valid;#endif}bool QLibraryPrivate::isPlugin(){ if (pluginState != MightBeAPlugin) return pluginState == IsAPlugin;#ifndef QT_NO_PLUGIN_CHECK bool debug = !QLIBRARY_AS_DEBUG; QByteArray key; bool success = false; QFileInfo fileinfo(fileName);#ifndef QT_NO_DATESTRING lastModified = fileinfo.lastModified().toString(Qt::ISODate);#endif QString regkey = QString::fromLatin1("Qt Plugin Cache %1.%2.%3/%4") .arg((QT_VERSION & 0xff0000) >> 16) .arg((QT_VERSION & 0xff00) >> 8) .arg(QLIBRARY_AS_DEBUG ? QLatin1String("debug") : QLatin1String("false")) .arg(fileName); QStringList reg; QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); reg = settings.value(regkey).toStringList(); if (reg.count() == 4 && lastModified == reg.at(3)) { qt_version = reg.at(0).toUInt(0, 16); debug = bool(reg.at(1).toInt()); key = reg.at(2).toLatin1(); success = qt_version != 0; } else {#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) if (!pHnd) { // use unix shortcut to avoid loading the library success = qt_unix_query(fileName, &qt_version, &debug, &key, this); } else#endif { bool temporary_load = false; if (!pHnd) temporary_load = load_sys();# ifdef Q_CC_BOR typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)();# else typedef const char * (*QtPluginQueryVerificationDataFunction)();# endif QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); if (!qtPluginQueryVerificationDataFunction || !qt_parse_pattern(qtPluginQueryVerificationDataFunction(), &qt_version, &debug, &key)) { qt_version = 0; key = "unknown"; if (temporary_load) unload_sys(); } else { success = true; } } QStringList queried; queried << QString::number(qt_version,16) << QString::number((int)debug) << QLatin1String(key) << lastModified; settings.setValue(regkey, queried); } if (!success) { if (fileName.isEmpty()) { errorString = QLibrary::tr("The shared library was not found."); } else { errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName); } return false; } pluginState = IsNotAPlugin; // be pessimistic if ((qt_version > QT_VERSION) || ((QT_VERSION & 0xff0000) > (qt_version & 0xff0000))) { if (qt_debug_component()) { qWarning("In %s:\n" " Plugin uses incompatible Qt library (%d.%d.%d) [%s]", (const char*) QFile::encodeName(fileName), (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff, debug ? "debug" : "release"); } errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]") .arg(fileName) .arg((qt_version&0xff0000) >> 16) .arg((qt_version&0xff00) >> 8) .arg(qt_version&0xff) .arg(debug ? QLatin1String("debug") : QLatin1String("release")); } else if (key != QT_BUILD_KEY) { if (qt_debug_component()) { qWarning("In %s:\n" " Plugin uses incompatible Qt library\n" " expected build key \"%s\", got \"%s\"", (const char*) QFile::encodeName(fileName), QT_BUILD_KEY, key.isEmpty() ? "<null>" : (const char *) key); } errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library." " Expected build key \"%2\", got \"%3\"") .arg(fileName) .arg(QLatin1String(QT_BUILD_KEY)) .arg(key.isEmpty() ? QLatin1String("<null>") : QLatin1String((const char *) key));#ifndef QT_NO_DEBUG_PLUGIN_CHECK } else if(debug != QLIBRARY_AS_DEBUG) { //don't issue a qWarning since we will hopefully find a non-debug? --Sam errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library." " (Cannot mix debug and release libraries.)").arg(fileName);#endif } else { pluginState = IsAPlugin; } return pluginState == IsAPlugin;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -