forge on linux fix

This commit is contained in:
2026-08-28 00:13:59 +03:00
parent af41017446
commit bbc8633257
5 changed files with 389 additions and 32 deletions
+101
View File
@@ -0,0 +1,101 @@
#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
}