00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __BINRELOC_C__
00014 #define __BINRELOC_C__
00015
00016 #ifdef ENABLE_BINRELOC
00017 #include <sys/types.h>
00018 #include <sys/stat.h>
00019 #include <unistd.h>
00020 #endif
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <limits.h>
00024 #include <string.h>
00025 #include "ForIA/binreloc.h"
00026
00027 #ifdef __cplusplus
00028 extern "C" {
00029 #endif
00030
00031
00032
00038 static char *
00039 _br_find_exe (BrInitError *error)
00040 {
00041 #ifndef ENABLE_BINRELOC
00042 if (error)
00043 *error = BR_INIT_ERROR_DISABLED;
00044 return NULL;
00045 #else
00046 char *path, *path2, *line, *result;
00047 size_t buf_size;
00048 ssize_t size;
00049 struct stat stat_buf;
00050 FILE *f;
00051
00052
00053 if (sizeof (path) > SSIZE_MAX)
00054 buf_size = SSIZE_MAX - 1;
00055 else
00056 buf_size = PATH_MAX - 1;
00057 path = (char *) malloc (buf_size);
00058 if (path == NULL) {
00059
00060 if (error)
00061 *error = BR_INIT_ERROR_NOMEM;
00062 return NULL;
00063 }
00064 path2 = (char *) malloc (buf_size);
00065 if (path2 == NULL) {
00066
00067 if (error)
00068 *error = BR_INIT_ERROR_NOMEM;
00069 free (path);
00070 return NULL;
00071 }
00072
00073 strncpy (path2, "/proc/self/exe", buf_size - 1);
00074
00075 while (1) {
00076 int i;
00077
00078 size = readlink (path2, path, buf_size - 1);
00079 if (size == -1) {
00080
00081 free (path2);
00082 break;
00083 }
00084
00085
00086 path[size] = '\0';
00087
00088
00089
00090 i = stat (path, &stat_buf);
00091 if (i == -1) {
00092
00093 free (path2);
00094 break;
00095 }
00096
00097
00098 if (!S_ISLNK (stat_buf.st_mode)) {
00099
00100 free (path2);
00101 return path;
00102 }
00103
00104
00105 strncpy (path, path2, buf_size - 1);
00106 }
00107
00108
00109
00110
00111
00112 buf_size = PATH_MAX + 128;
00113 line = (char *) realloc (path, buf_size);
00114 if (line == NULL) {
00115
00116 free (path);
00117 if (error)
00118 *error = BR_INIT_ERROR_NOMEM;
00119 return NULL;
00120 }
00121
00122 f = fopen ("/proc/self/maps", "r");
00123 if (f == NULL) {
00124 free (line);
00125 if (error)
00126 *error = BR_INIT_ERROR_OPEN_MAPS;
00127 return NULL;
00128 }
00129
00130
00131 result = fgets (line, (int) buf_size, f);
00132 if (result == NULL) {
00133 fclose (f);
00134 free (line);
00135 if (error)
00136 *error = BR_INIT_ERROR_READ_MAPS;
00137 return NULL;
00138 }
00139
00140
00141 buf_size = strlen (line);
00142 if (buf_size <= 0) {
00143
00144 fclose (f);
00145 free (line);
00146 if (error)
00147 *error = BR_INIT_ERROR_INVALID_MAPS;
00148 return NULL;
00149 }
00150 if (line[buf_size - 1] == 10)
00151 line[buf_size - 1] = 0;
00152
00153
00154 path = strchr (line, '/');
00155
00156
00157 if (strstr (line, " r-xp ") == NULL || path == NULL) {
00158 fclose (f);
00159 free (line);
00160 if (error)
00161 *error = BR_INIT_ERROR_INVALID_MAPS;
00162 return NULL;
00163 }
00164
00165 path = strdup (path);
00166 free (line);
00167 fclose (f);
00168 return path;
00169 #endif
00170 }
00171
00172
00177 static char *
00178 _br_find_exe_for_symbol (const void *symbol, BrInitError *error)
00179 {
00180 #ifndef ENABLE_BINRELOC
00181 if (error)
00182 *error = BR_INIT_ERROR_DISABLED;
00183 return (char *) NULL;
00184 #else
00185 #define SIZE PATH_MAX + 100
00186 FILE *f;
00187 size_t address_string_len;
00188 char *address_string, line[SIZE], *found;
00189
00190 if (symbol == NULL)
00191 return (char *) NULL;
00192
00193 f = fopen ("/proc/self/maps", "r");
00194 if (f == NULL)
00195 return (char *) NULL;
00196
00197 address_string_len = 4;
00198 address_string = (char *) malloc (address_string_len);
00199
00200 if (!address_string)
00201 {
00202 if (error)
00203 *error = BR_INIT_ERROR_NOMEM;
00204 return (char *) NULL;
00205 }
00206 found = (char *) NULL;
00207
00208 while (!feof (f)) {
00209 char *start_addr, *end_addr, *end_addr_end, *file;
00210 void *start_addr_p, *end_addr_p;
00211 size_t len;
00212
00213 if (fgets (line, SIZE, f) == NULL)
00214 break;
00215
00216
00217 if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
00218 continue;
00219
00220
00221 start_addr = line;
00222 end_addr = strchr (line, '-');
00223 file = strchr (line, '/');
00224
00225
00226 if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
00227 continue;
00228
00229 end_addr[0] = '\0';
00230 end_addr++;
00231 end_addr_end = strchr (end_addr, ' ');
00232 if (end_addr_end == NULL)
00233 continue;
00234
00235 end_addr_end[0] = '\0';
00236 len = strlen (file);
00237 if (len == 0)
00238 continue;
00239 if (file[len - 1] == '\n')
00240 file[len - 1] = '\0';
00241
00242
00243 len = strlen (file);
00244 if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
00245 file[len - 10] = '\0';
00246
00247
00248 len = strlen (start_addr);
00249 if (len != strlen (end_addr))
00250 continue;
00251
00252
00253
00254
00255 if (address_string_len < len + 3) {
00256 address_string_len = len + 3;
00257 address_string = (char *) realloc (address_string, address_string_len);
00258
00259 if (!address_string)
00260 {
00261 if (error)
00262 *error = BR_INIT_ERROR_NOMEM;
00263 return (char *) NULL;
00264 }
00265 }
00266
00267 memcpy (address_string, "0x", 2);
00268 memcpy (address_string + 2, start_addr, len);
00269 address_string[2 + len] = '\0';
00270 sscanf (address_string, "%p", &start_addr_p);
00271
00272 memcpy (address_string, "0x", 2);
00273 memcpy (address_string + 2, end_addr, len);
00274 address_string[2 + len] = '\0';
00275 sscanf (address_string, "%p", &end_addr_p);
00276
00277
00278 if (symbol >= start_addr_p && symbol < end_addr_p) {
00279 found = file;
00280 break;
00281 }
00282 }
00283
00284 free (address_string);
00285 fclose (f);
00286
00287 if (found == NULL)
00288 return (char *) NULL;
00289 else
00290 return strdup (found);
00291 #endif
00292 }
00293
00294
00295 #ifndef BINRELOC_RUNNING_DOXYGEN
00296 #undef NULL
00297 #define NULL ((char *) 0)
00298 #endif
00299
00300 static char *exe = (char *) NULL;
00301
00302
00319 int
00320 br_init (BrInitError *error)
00321 {
00322 exe = _br_find_exe (error);
00323 return exe != NULL;
00324 }
00325
00326
00343 int
00344 br_init_lib (BrInitError *error)
00345 {
00346 exe = _br_find_exe_for_symbol ((const void *) "", error);
00347 return exe != NULL;
00348 }
00349
00350
00360 char *
00361 br_find_exe (const char *default_exe)
00362 {
00363 if (exe == (char *) NULL) {
00364
00365 if (default_exe != (const char *) NULL)
00366 return strdup (default_exe);
00367 else
00368 return (char *) NULL;
00369 }
00370 return strdup (exe);
00371 }
00372
00373
00388 char *
00389 br_find_exe_dir (const char *default_dir)
00390 {
00391 if (exe == NULL) {
00392
00393 if (default_dir != NULL)
00394 return strdup (default_dir);
00395 else
00396 return NULL;
00397 }
00398
00399 return br_dirname (exe);
00400 }
00401
00402
00416 char *
00417 br_find_prefix (const char *default_prefix)
00418 {
00419 char *dir1, *dir2;
00420
00421 if (exe == (char *) NULL) {
00422
00423 if (default_prefix != (const char *) NULL)
00424 return strdup (default_prefix);
00425 else
00426 return (char *) NULL;
00427 }
00428
00429 dir1 = br_dirname (exe);
00430 dir2 = br_dirname (dir1);
00431 free (dir1);
00432 return dir2;
00433 }
00434
00435
00449 char *
00450 br_find_bin_dir (const char *default_bin_dir)
00451 {
00452 char *prefix, *dir;
00453
00454 prefix = br_find_prefix ((const char *) NULL);
00455 if (prefix == (char *) NULL) {
00456
00457 if (default_bin_dir != (const char *) NULL)
00458 return strdup (default_bin_dir);
00459 else
00460 return (char *) NULL;
00461 }
00462
00463 dir = br_build_path (prefix, "bin");
00464 free (prefix);
00465 return dir;
00466 }
00467
00468
00482 char *
00483 br_find_sbin_dir (const char *default_sbin_dir)
00484 {
00485 char *prefix, *dir;
00486
00487 prefix = br_find_prefix ((const char *) NULL);
00488 if (prefix == (char *) NULL) {
00489
00490 if (default_sbin_dir != (const char *) NULL)
00491 return strdup (default_sbin_dir);
00492 else
00493 return (char *) NULL;
00494 }
00495
00496 dir = br_build_path (prefix, "sbin");
00497 free (prefix);
00498 return dir;
00499 }
00500
00501
00516 char *
00517 br_find_data_dir (const char *default_data_dir)
00518 {
00519 char *prefix, *dir;
00520
00521 prefix = br_find_prefix ((const char *) NULL);
00522 if (prefix == (char *) NULL) {
00523
00524 if (default_data_dir != (const char *) NULL)
00525 return strdup (default_data_dir);
00526 else
00527 return (char *) NULL;
00528 }
00529
00530 dir = br_build_path (prefix, "share");
00531 free (prefix);
00532 return dir;
00533 }
00534
00535
00549 char *
00550 br_find_locale_dir (const char *default_locale_dir)
00551 {
00552 char *data_dir, *dir;
00553
00554 data_dir = br_find_data_dir ((const char *) NULL);
00555 if (data_dir == (char *) NULL) {
00556
00557 if (default_locale_dir != (const char *) NULL)
00558 return strdup (default_locale_dir);
00559 else
00560 return (char *) NULL;
00561 }
00562
00563 dir = br_build_path (data_dir, "locale");
00564 free (data_dir);
00565 return dir;
00566 }
00567
00568
00582 char *
00583 br_find_lib_dir (const char *default_lib_dir)
00584 {
00585 char *prefix, *dir;
00586
00587 prefix = br_find_prefix ((const char *) NULL);
00588 if (prefix == (char *) NULL) {
00589
00590 if (default_lib_dir != (const char *) NULL)
00591 return strdup (default_lib_dir);
00592 else
00593 return (char *) NULL;
00594 }
00595
00596 dir = br_build_path (prefix, "lib");
00597 free (prefix);
00598 return dir;
00599 }
00600
00601
00615 char *
00616 br_find_libexec_dir (const char *default_libexec_dir)
00617 {
00618 char *prefix, *dir;
00619
00620 prefix = br_find_prefix ((const char *) NULL);
00621 if (prefix == (char *) NULL) {
00622
00623 if (default_libexec_dir != (const char *) NULL)
00624 return strdup (default_libexec_dir);
00625 else
00626 return (char *) NULL;
00627 }
00628
00629 dir = br_build_path (prefix, "libexec");
00630 free (prefix);
00631 return dir;
00632 }
00633
00634
00648 char *
00649 br_find_etc_dir (const char *default_etc_dir)
00650 {
00651 char *prefix, *dir;
00652
00653 prefix = br_find_prefix ((const char *) NULL);
00654 if (prefix == (char *) NULL) {
00655
00656 if (default_etc_dir != (const char *) NULL)
00657 return strdup (default_etc_dir);
00658 else
00659 return (char *) NULL;
00660 }
00661
00662 dir = br_build_path (prefix, "etc");
00663 free (prefix);
00664 return dir;
00665 }
00666
00667
00668
00669
00670
00671
00678 char *
00679 br_strcat (const char *str1, const char *str2)
00680 {
00681 char *result;
00682 size_t len1, len2;
00683
00684 if (str1 == NULL)
00685 str1 = "";
00686 if (str2 == NULL)
00687 str2 = "";
00688
00689 len1 = strlen (str1);
00690 len2 = strlen (str2);
00691
00692 result = (char *) malloc (len1 + len2 + 1);
00693
00694 if (result)
00695 {
00696 memcpy (result, str1, len1);
00697 memcpy (result + len1, str2, len2);
00698 result[len1 + len2] = '\0';
00699 }
00700 return result;
00701 }
00702
00703
00704 char *
00705 br_build_path (const char *dir, const char *file)
00706 {
00707 char *dir2, *result;
00708 size_t len;
00709 int must_free = 0;
00710
00711 len = strlen (dir);
00712 if (len > 0 && dir[len - 1] != '/') {
00713 dir2 = br_strcat (dir, "/");
00714 must_free = 1;
00715 } else
00716 dir2 = (char *) dir;
00717
00718 result = br_strcat (dir2, file);
00719 if (must_free)
00720 free (dir2);
00721 return result;
00722 }
00723
00724
00725
00726 static char *
00727 br_strndup (const char *str, size_t size)
00728 {
00729 char *result = (char *) NULL;
00730 size_t len;
00731
00732 if (str == (const char *) NULL)
00733 return (char *) NULL;
00734
00735 len = strlen (str);
00736 if (len == 0)
00737 return strdup ("");
00738 if (size > len)
00739 size = len;
00740
00741 result = (char *) malloc (len + 1);
00742
00743 if (result)
00744 {
00745 memcpy (result, str, size);
00746 result[size] = '\0';
00747 }
00748 return result;
00749 }
00750
00751
00764 char *
00765 br_dirname (const char *path)
00766 {
00767 char *end, *result;
00768
00769 if (path == (const char *) NULL)
00770 return (char *) NULL;
00771
00772 end = strrchr (path, '/');
00773 if (end == (const char *) NULL)
00774 return strdup (".");
00775
00776 while (end > path && *end == '/')
00777 end--;
00778 result = br_strndup (path, end - path + 1);
00779 if (result[0] == 0) {
00780 free (result);
00781 return strdup ("/");
00782 } else
00783 return result;
00784 }
00785
00786
00787 #ifdef __cplusplus
00788 }
00789 #endif
00790
00791 #endif