77 lines
4.5 KiB
Markdown
77 lines
4.5 KiB
Markdown
|
|
# zlibreference.h — ZlibReference
|
||
|
|
|
||
|
|
## Обзор
|
||
|
|
|
||
|
|
`Minecraft_launcher` умеет ставить модлоадеры Forge и NeoForge, а их установщики — это Java-программы,
|
||
|
|
которые собирают часть jar-файлов прямо на машине пользователя и сверяют sha1 каждого собранного
|
||
|
|
файла с эталоном из `install_profile.json`.
|
||
|
|
|
||
|
|
Эталон посчитан на обычном zlib. Дистрибутивы вроде CachyOS и Fedora подставляют вместо него
|
||
|
|
zlib-ng: сжатие корректное, но побайтово другое — поэтому установка падает на любой версии игры
|
||
|
|
сообщением «Processor failed, invalid outputs». Сменить Java не выйдет: сборки OpenJDK под Linux
|
||
|
|
берут `libz.so.1` из системы.
|
||
|
|
|
||
|
|
`ZlibReference` — обход этой проблемы. Рядом с лаунчером лежит собранный обычный zlib, и процессу
|
||
|
|
установщика он подсовывается через `LD_PRELOAD`. Системный zlib-ng при этом остаётся на месте:
|
||
|
|
подмена живёт ровно один процесс.
|
||
|
|
|
||
|
|
Пространство имён используется установщиком модлоадеров при подготовке окружения дочернего
|
||
|
|
процесса Java.
|
||
|
|
|
||
|
|
## Пространства имён
|
||
|
|
|
||
|
|
`ZlibReference` группирует три функции: проверку системной библиотеки, поиск собранного эталона и
|
||
|
|
подготовку окружения процесса. Состояния нет.
|
||
|
|
|
||
|
|
## Функции
|
||
|
|
|
||
|
|
#### bool systemIsZlibNg()
|
||
|
|
|
||
|
|
Отвечает на вопрос, окажется ли `libz.so.1`, который достанется процессу java, библиотекой zlib-ng.
|
||
|
|
От ответа зависит, нужна ли подмена вообще: на системе с обычным zlib она бессмысленна.
|
||
|
|
|
||
|
|
#### QString bundledPath()
|
||
|
|
|
||
|
|
Путь к собранному рядом эталонному `libz.so.1` или пустая строка, если его нет. Библиотека
|
||
|
|
собирается целью `launcher_zlib_reference` в `CMakeLists.txt` из исходников каталога `zlib/`,
|
||
|
|
которые лежат в репозитории, чтобы сборка не зависела от сети, а версия была зафиксирована — от
|
||
|
|
неё зависит побайтовый результат сжатия. Собирается только на Linux: на Windows и macOS проблемы
|
||
|
|
подмены системного zlib нет.
|
||
|
|
|
||
|
|
#### bool applyTo(QProcessEnvironment &env, QString *note = nullptr)
|
||
|
|
|
||
|
|
Дописывает `LD_PRELOAD` в переданное окружение, если подмена нужна. Изменяет `env` на месте.
|
||
|
|
|
||
|
|
Возвращает `true`, когда окружение готово, — в том числе в случае, когда подменять нечего:
|
||
|
|
система с обычным zlib или платформа, где вопрос не стоит. `false` означает, что подмена нужна, но
|
||
|
|
эталонной библиотеки нет на месте.
|
||
|
|
|
||
|
|
Необязательный параметр `note` заполняется строкой, пригодной и для журнала, и для текста ошибки:
|
||
|
|
она объясняет, была ли подмена применена и почему.
|
||
|
|
|
||
|
|
## Зависимости
|
||
|
|
|
||
|
|
Подключает `QString`; `QProcessEnvironment` объявлен вперёд и используется только по ссылке.
|
||
|
|
Реализация опирается на макрос `LAUNCHER_ZLIB_INSTALL_DIR`, который `CMakeLists.txt` определяет на
|
||
|
|
Linux — это путь установки библиотеки в системе, помимо каталога рядом с исполняемым файлом.
|
||
|
|
|
||
|
|
## Пример использования
|
||
|
|
|
||
|
|
```cpp
|
||
|
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||
|
|
|
||
|
|
QString note;
|
||
|
|
if (!ZlibReference::applyTo(env, ¬e)) {
|
||
|
|
emit failed(note);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
QProcess installer;
|
||
|
|
installer.setProcessEnvironment(env);
|
||
|
|
installer.start(javaPath, arguments);
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
При создании этого документа использовался ИИ.
|