File indexing completed on 2024-11-10 04:05:17
0001 /** 0002 * SPDX-FileCopyrightText: 2022 Dmitry Kazakov <dimula73@gmail.com> 0003 * SPDX-FileCopyrightText: 2004-2018 Simon Peter 0004 * SPDX-FileCopyrightText: 2010 RazZziel 0005 * 0006 * SPDX-License-Identifier: MIT 0007 */ 0008 0009 #define _GNU_SOURCE 0010 0011 #include <limits.h> 0012 #include <link.h> 0013 #include <stdlib.h> 0014 #include <string.h> 0015 #include <stdio.h> 0016 #include <libgen.h> 0017 #include <unistd.h> 0018 #include <errno.h> 0019 0020 void split_version(const char *version, int values[4]) 0021 { 0022 char *ver = strdup(version); 0023 0024 // printf(" ver: %s\n", ver); 0025 0026 int index = 0; 0027 char *token = strtok(ver, "."); 0028 0029 while (token && index < 4) { 0030 const int value = atoi(token); 0031 0032 // printf("value: %s -> %d\n", token, value); 0033 0034 values[index] = value; 0035 index++; 0036 token = strtok(0, "."); 0037 } 0038 0039 while (index < 4) { 0040 values[index] = 0; 0041 index++; 0042 } 0043 0044 free (ver); 0045 } 0046 0047 int needs_replace_library(const char *library, const char *base_library) 0048 { 0049 int base_value[4]; 0050 int value[4]; 0051 0052 split_version(base_library, base_value); 0053 split_version(library, value); 0054 0055 int result = 0; 0056 0057 for (int i = 0; i < 4; i++) { 0058 if (base_value[i] < value[i]) { 0059 break; 0060 } else if (base_value[i] > value[i]) { 0061 result = 1; 0062 break; 0063 } 0064 } 0065 0066 return result; 0067 } 0068 0069 #define die(...) \ 0070 do { \ 0071 fprintf(stderr, "Error: " __VA_ARGS__); \ 0072 exit(1); \ 0073 } while(0); 0074 0075 #define SET_NEW_ENV(str,len,fmt,...) \ 0076 format = fmt; \ 0077 length = strlen(format) + (len); \ 0078 char *str = calloc(length, sizeof(char)); \ 0079 snprintf(str, length, format, __VA_ARGS__); \ 0080 putenv(str); 0081 0082 void try_replace_library(const char *library_name, const char *fallback_dir_name) 0083 { 0084 char buf[PATH_MAX] = ""; 0085 char real_library_path[PATH_MAX]; 0086 0087 void *handle = dlopen(library_name, RTLD_LAZY); 0088 0089 if (handle) { 0090 struct link_map *info; 0091 int result = dlinfo(handle, RTLD_DI_LINKMAP, &info); 0092 0093 if (result == 0) { 0094 if (realpath(info->l_name, real_library_path)) { 0095 // noop 0096 } else { 0097 die("Couldn't resolve the name of system %s", library_name); 0098 } 0099 } else { 0100 die("Couldn't get info for %s", library_name); 0101 } 0102 } else { 0103 die("Couldn't load %s", library_name); 0104 } 0105 0106 char appdir_buf[PATH_MAX] = ""; 0107 char *appdir = dirname(realpath("/proc/self/exe", appdir_buf)); 0108 if (!appdir) { 0109 die("Could not access /proc/self/exe\n"); 0110 } 0111 0112 char fallback_library[PATH_MAX] = ""; 0113 snprintf(fallback_library, PATH_MAX, "%s/usr/%s/%s", appdir, fallback_dir_name, library_name); 0114 0115 if (realpath(fallback_library, buf)) { 0116 strcpy(fallback_library, buf); 0117 } else { 0118 die("Could not access $(APPDIR)/usr/%s/%s\n", fallback_dir_name, library_name); 0119 } 0120 0121 0122 const int version_offset = strlen(library_name) + 1; 0123 char *fallback_library_name = strstr(fallback_library, library_name); 0124 char *real_library_name = strstr(real_library_path, library_name); 0125 0126 // printf("fallback_library_name %s\n", fallback_library_name); 0127 // printf("real_library_name %s\n", real_library_name); 0128 0129 char *old_env; 0130 size_t length; 0131 const char *format; 0132 0133 if (needs_replace_library(real_library_name + version_offset, fallback_library_name + version_offset)) { 0134 printf("Replacing %s with the fallback version: %s -> %s\n", library_name, real_library_name, fallback_library_name); 0135 0136 old_env = getenv("LD_LIBRARY_PATH"); 0137 if (!old_env) old_env = ""; 0138 0139 SET_NEW_ENV(new_ld_library_path, 0140 strlen(appdir) + strlen(fallback_dir_name) + strlen(old_env), 0141 "LD_LIBRARY_PATH=%s/usr/%s/:%s", appdir, fallback_dir_name, old_env); 0142 old_env = getenv("LD_LIBRARY_PATH") ?: ""; 0143 } 0144 } 0145 0146 0147 int main(int argc, char **argv) 0148 { 0149 char appdir_buf[PATH_MAX] = ""; 0150 char *appdir = dirname(realpath("/proc/self/exe", appdir_buf)); 0151 if (!appdir) { 0152 die("Could not access /proc/self/exe\n"); 0153 } 0154 0155 try_replace_library("libstdc++.so.6", "libstdcpp-fallback"); 0156 0157 char exec_path[PATH_MAX] = ""; 0158 strcpy(exec_path, appdir); 0159 strcat(exec_path, "/usr/bin/krita"); 0160 0161 char *exec_args[argc + 1]; 0162 exec_args[0] = exec_path; 0163 0164 for (int i = 1; i < argc; i++) { 0165 exec_args[i] = argv[i]; 0166 } 0167 0168 exec_args[argc] = 0; 0169 0170 int ret = execvp(exec_path, exec_args); 0171 0172 if (ret == -1) { 0173 int error = errno; 0174 die("Error executing '%s': %s\n", exec_path, strerror(error)); 0175 } 0176 0177 return 0; 0178 }