#include "zlibreference.h" #include #include #include #include #include #include #if defined(Q_OS_LINUX) #include #endif namespace { QString translate(const char *text) { return QCoreApplication::translate("ZlibReference", text); } } // namespace bool ZlibReference::systemIsZlibNg() { #if defined(Q_OS_LINUX) // Спрашиваем ровно ту библиотеку, которую подберёт ld.so процессу java. // zlib-ng в режиме совместимости честно пишет о себе в zlibVersion(). static const bool result = [] { void *handle = dlopen("libz.so.1", RTLD_LAZY); if (!handle) return false; using VersionFn = const char *(*)(); const auto zlibVersion = reinterpret_cast(dlsym(handle, "zlibVersion")); const QString version = zlibVersion ? QString::fromLatin1(zlibVersion()) : QString(); dlclose(handle); return version.contains(QLatin1String("zlib-ng"), Qt::CaseInsensitive); }(); return result; #else return false; #endif } QString ZlibReference::bundledPath() { #if defined(Q_OS_LINUX) static const QString path = [] { QStringList candidates; const QString appDir = QCoreApplication::applicationDirPath(); if (!appDir.isEmpty()) { candidates << appDir + QStringLiteral("/zlib/libz.so.1") // дерево сборки << appDir + QStringLiteral("/../lib/galeonLauncher/libz.so.1"); } #ifdef LAUNCHER_ZLIB_INSTALL_DIR candidates << QStringLiteral(LAUNCHER_ZLIB_INSTALL_DIR) + QStringLiteral("/libz.so.1"); #endif for (const QString &candidate : std::as_const(candidates)) { const QFileInfo info(candidate); if (info.exists() && info.isFile()) return info.canonicalFilePath(); } return QString(); }(); return path; #else return {}; #endif } bool ZlibReference::applyTo(QProcessEnvironment &env, QString *note) { #if defined(Q_OS_LINUX) if (!systemIsZlibNg()) { if (note) note->clear(); return true; } const QString path = bundledPath(); if (path.isEmpty()) { if (note) *note = translate("В системе zlib-ng, а эталонный libz.so.1 рядом с лаунчером " "не найден — установщик почти наверняка не сойдётся по sha1."); return false; } // Не затираем чужой LD_PRELOAD: наш идёт первым, остальное остаётся. const QString existing = env.value(QStringLiteral("LD_PRELOAD")); env.insert(QStringLiteral("LD_PRELOAD"), existing.isEmpty() ? path : path + u':' + existing); if (note) *note = translate("Системный zlib-ng подменён эталонным zlib: %1") .arg(QDir::toNativeSeparators(path)); return true; #else Q_UNUSED(env); if (note) note->clear(); return true; #endif }