minecraft-pi-reborn/launcher/src/patchelf.c

141 lines
4.2 KiB
C
Raw Normal View History

2022-03-25 02:47:34 +00:00
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <libreborn/libreborn.h>
#include "bootstrap.h"
#include "patchelf.h"
// Duplicate MCPI Executable Into /tmp
2022-05-14 02:36:12 +00:00
#define TMP_DIR "/tmp/.minecraft-pi-patched"
2022-05-30 02:54:57 +00:00
static void duplicate_mcpi_executable(const char *original_path) {
2022-04-24 01:10:44 +00:00
// Ensure Temporary Directory
{
// Check If It Exists
struct stat tmp_stat;
int exists = stat(TMP_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
if (!exists) {
// Doesn't Exist
if (mkdir(TMP_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
ERR("Unable To Create Temporary Folder: %s", strerror(errno));
}
}
}
2022-03-25 02:47:34 +00:00
// Generate New File
2022-04-24 01:10:44 +00:00
char new_path[] = TMP_DIR "/XXXXXX";
2022-03-25 02:47:34 +00:00
int new_file_fd = mkstemp(new_path);
if (new_file_fd == -1) {
ERR("Unable To Create Temporary File: %s", strerror(errno));
}
FILE *new_file = fdopen(new_file_fd, "wb");
if (new_file == NULL) {
ERR("Unable To Open Temporary File: %s", strerror(errno));
}
set_and_print_env("MCPI_EXECUTABLE_PATH", new_path);
// Copy Original File
{
// Open Original File
FILE *original_file = fopen(original_path, "rb");
if (original_file == NULL) {
ERR("Unable To Open File: %s", original_path);
}
// Copy
#define BUFFER_SIZE 1024
char buf[BUFFER_SIZE];
size_t bytes_read = 0;
while ((bytes_read = fread((void *) buf, 1, BUFFER_SIZE, original_file)) > 0) {
fwrite((void *) buf, 1, bytes_read, new_file);
if (ferror(new_file) != 0) {
ERR("Unable To Write File: %s", new_path);
}
}
if (ferror(original_file) != 0) {
ERR("Unable To Read File: %s", original_path);
}
// Close Original File
fclose(original_file);
}
// Close New File
fclose(new_file);
close(new_file_fd);
}
// Fix MCPI Dependencies
2022-04-15 01:12:42 +00:00
#define patch_mcpi_elf_dependencies_with_extra_patchelf_args(...) \
({ \
const char *const _macro_command[] = { \
"patchelf", \
##__VA_ARGS__, \
"--remove-needed", "libbcm_host.so", \
"--remove-needed", "libX11.so.6", \
"--remove-needed", "libEGL.so", \
"--replace-needed", "libGLESv2.so", "libGLESv1_CM.so.1", \
exe, \
NULL \
}; \
int _macro_return_code = 0; \
char *_macro_output = run_command(_macro_command, &_macro_return_code); \
if (_macro_output != NULL) { \
free(_macro_output); \
} \
_macro_return_code; \
})
2022-05-30 02:54:57 +00:00
void patch_mcpi_elf_dependencies(const char *original_path, const char *linker) {
2022-03-25 02:47:34 +00:00
// Duplicate MCPI executable into /tmp so it can be modified.
2022-05-30 02:54:57 +00:00
duplicate_mcpi_executable(original_path);
2022-03-25 02:47:34 +00:00
2022-03-25 03:03:59 +00:00
// Get Path
char *exe = getenv("MCPI_EXECUTABLE_PATH");
2022-03-25 02:47:34 +00:00
// Run patchelf
2022-04-15 01:12:42 +00:00
int return_code;
if (linker == NULL) {
return_code = patch_mcpi_elf_dependencies_with_extra_patchelf_args();
} else {
return_code = patch_mcpi_elf_dependencies_with_extra_patchelf_args("--set-interpreter", linker);
2022-03-25 02:47:34 +00:00
}
2022-05-15 17:51:28 +00:00
if (!is_exit_status_success(return_code)) {
char *exit_status_line = NULL;
get_exit_status_string(return_code, &exit_status_line);
ERR("patchelf Failed%s", exit_status_line);
2022-03-25 02:47:34 +00:00
}
2022-03-25 03:03:59 +00:00
// Fix Permissions
if (chmod(exe, S_IRUSR | S_IXUSR) != 0) {
ERR("Unable To Set File Permissions: %s: %s", exe, strerror(errno));
}
2022-03-25 02:47:34 +00:00
}
2022-05-03 02:44:10 +00:00
// Get Interpreter
char *patch_get_interpreter(const char *file) {
// Run
const char *const command[] = {
"patchelf",
"--print-interpreter",
file,
NULL
};
2022-05-15 19:16:45 +00:00
int return_code;
char *output = run_command(command, &return_code);
if (!is_exit_status_success(return_code)) {
char *exit_status_line = NULL;
get_exit_status_string(return_code, &exit_status_line);
ERR("patchelf Failed%s", exit_status_line);
}
2022-05-03 02:44:10 +00:00
if (output != NULL) {
// Trim
int length = strlen(output);
if (output[length - 1] == '\n') {
output[length - 1] = '\0';
}
}
// Return
return output;
}