Files
BiLauncher/zlibreference.cpp
T
2026-08-28 00:13:59 +03:00

102 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "zlibreference.h"
#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QProcessEnvironment>
#include <QStringList>
#include <utility>
#if defined(Q_OS_LINUX)
#include <dlfcn.h>
#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<VersionFn>(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
}