102 lines
3.1 KiB
C++
102 lines
3.1 KiB
C++
#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
|
||
}
|