#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include "binreloc.h"
Include dependency graph for binreloc.c:
Go to the source code of this file.
Defines | |
#define | NULL ((void *) 0) |
Functions | |
static char * | _br_find_exe (BrInitError *error) |
static char * | _br_find_exe_for_symbol (const void *symbol, BrInitError *error) |
int | br_init (BrInitError *error) |
int | br_init_lib (BrInitError *error) |
char * | br_find_exe (const char *default_exe) |
char * | br_find_exe_dir (const char *default_dir) |
char * | br_find_prefix (const char *default_prefix) |
char * | br_find_bin_dir (const char *default_bin_dir) |
char * | br_find_sbin_dir (const char *default_sbin_dir) |
char * | br_find_data_dir (const char *default_data_dir) |
char * | br_find_locale_dir (const char *default_locale_dir) |
char * | br_find_lib_dir (const char *default_lib_dir) |
char * | br_find_libexec_dir (const char *default_libexec_dir) |
char * | br_find_etc_dir (const char *default_etc_dir) |
char * | br_strcat (const char *str1, const char *str2) |
char * | br_build_path (const char *dir, const char *file) |
static char * | br_strndup (const char *str, size_t size) |
char * | br_dirname (const char *path) |
Variables | |
static char * | exe = (char *) NULL |
#define NULL ((void *) 0) |
Definition at line 283 of file binreloc.c.
static char* _br_find_exe | ( | BrInitError * | error | ) | [static] |
Definition at line 39 of file binreloc.c.
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 /* Read from /proc/self/exe (symlink) */ 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 /* Cannot allocate memory. */ 00060 if (error) 00061 *error = BR_INIT_ERROR_NOMEM; 00062 return NULL; 00063 } 00064 path2 = (char *) malloc (buf_size); 00065 if (path2 == NULL) { 00066 /* Cannot allocate memory. */ 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 /* Error. */ 00081 free (path2); 00082 break; 00083 } 00084 00085 /* readlink() success. */ 00086 path[size] = '\0'; 00087 00088 /* Check whether the symlink's target is also a symlink. 00089 * We want to get the final target. */ 00090 i = stat (path, &stat_buf); 00091 if (i == -1) { 00092 /* Error. */ 00093 free (path2); 00094 break; 00095 } 00096 00097 /* stat() success. */ 00098 if (!S_ISLNK (stat_buf.st_mode)) { 00099 /* path is not a symlink. Done. */ 00100 free (path2); 00101 return path; 00102 } 00103 00104 /* path is a symlink. Continue loop and resolve this. */ 00105 strncpy (path, path2, buf_size - 1); 00106 } 00107 00108 00109 /* readlink() or stat() failed; this can happen when the program is 00110 * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */ 00111 00112 buf_size = PATH_MAX + 128; 00113 line = (char *) realloc (path, buf_size); 00114 if (line == NULL) { 00115 /* Cannot allocate memory. */ 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 /* The first entry should be the executable name. */ 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 /* Get rid of newline character. */ 00141 buf_size = strlen (line); 00142 if (buf_size <= 0) { 00143 /* Huh? An empty string? */ 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 /* Extract the filename; it is always an absolute path. */ 00154 path = strchr (line, '/'); 00155 00156 /* Sanity check. */ 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 /* ENABLE_BINRELOC */ 00170 }
Here is the caller graph for this function:
static char* _br_find_exe_for_symbol | ( | const void * | symbol, | |
BrInitError * | error | |||
) | [static] |
Definition at line 178 of file binreloc.c.
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 found = (char *) NULL; 00200 00201 while (!feof (f)) { 00202 char *start_addr, *end_addr, *end_addr_end, *file; 00203 void *start_addr_p, *end_addr_p; 00204 size_t len; 00205 00206 if (fgets (line, SIZE, f) == NULL) 00207 break; 00208 00209 /* Sanity check. */ 00210 if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL) 00211 continue; 00212 00213 /* Parse line. */ 00214 start_addr = line; 00215 end_addr = strchr (line, '-'); 00216 file = strchr (line, '/'); 00217 00218 /* More sanity check. */ 00219 if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-')) 00220 continue; 00221 00222 end_addr[0] = '\0'; 00223 end_addr++; 00224 end_addr_end = strchr (end_addr, ' '); 00225 if (end_addr_end == NULL) 00226 continue; 00227 00228 end_addr_end[0] = '\0'; 00229 len = strlen (file); 00230 if (len == 0) 00231 continue; 00232 if (file[len - 1] == '\n') 00233 file[len - 1] = '\0'; 00234 00235 /* Get rid of "(deleted)" from the filename. */ 00236 len = strlen (file); 00237 if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0) 00238 file[len - 10] = '\0'; 00239 00240 /* I don't know whether this can happen but better safe than sorry. */ 00241 len = strlen (start_addr); 00242 if (len != strlen (end_addr)) 00243 continue; 00244 00245 00246 /* Transform the addresses into a string in the form of 0xdeadbeef, 00247 * then transform that into a pointer. */ 00248 if (address_string_len < len + 3) { 00249 address_string_len = len + 3; 00250 address_string = (char *) realloc (address_string, address_string_len); 00251 } 00252 00253 memcpy (address_string, "0x", 2); 00254 memcpy (address_string + 2, start_addr, len); 00255 address_string[2 + len] = '\0'; 00256 sscanf (address_string, "%p", &start_addr_p); 00257 00258 memcpy (address_string, "0x", 2); 00259 memcpy (address_string + 2, end_addr, len); 00260 address_string[2 + len] = '\0'; 00261 sscanf (address_string, "%p", &end_addr_p); 00262 00263 00264 if (symbol >= start_addr_p && symbol < end_addr_p) { 00265 found = file; 00266 break; 00267 } 00268 } 00269 00270 free (address_string); 00271 fclose (f); 00272 00273 if (found == NULL) 00274 return (char *) NULL; 00275 else 00276 return strdup (found); 00277 #endif /* ENABLE_BINRELOC */ 00278 }
Here is the caller graph for this function:
char* br_build_path | ( | const char * | dir, | |
const char * | file | |||
) |
Definition at line 684 of file binreloc.c.
00685 { 00686 char *dir2, *result; 00687 size_t len; 00688 int must_free = 0; 00689 00690 len = strlen (dir); 00691 if (len > 0 && dir[len - 1] != '/') { 00692 dir2 = br_strcat (dir, "/"); 00693 must_free = 1; 00694 } else 00695 dir2 = (char *) dir; 00696 00697 result = br_strcat (dir2, file); 00698 if (must_free) 00699 free (dir2); 00700 return result; 00701 }
char* br_dirname | ( | const char * | path | ) |
Extracts the directory component of a path.
Similar to g_dirname() or the dirname commandline application.
Example:
br_dirname ("/usr/local/foobar"); --> Returns: "/usr/local"
path | A path. |
Definition at line 740 of file binreloc.c.
00741 { 00742 char *end, *result; 00743 00744 if (path == (const char *) NULL) 00745 return (char *) NULL; 00746 00747 end = strrchr (path, '/'); 00748 if (end == (const char *) NULL) 00749 return strdup ("."); 00750 00751 while (end > path && *end == '/') 00752 end--; 00753 result = br_strndup (path, end - path + 1); 00754 if (result[0] == 0) { 00755 free (result); 00756 return strdup ("/"); 00757 } else 00758 return result; 00759 }
Here is the call graph for this function:
char* br_find_bin_dir | ( | const char * | default_bin_dir | ) |
Locate the application's binary folder.
The path is generated by the following pseudo-code evaluation:
prefix + "/bin"
default_bin_dir | A default path which will used as fallback. |
Definition at line 432 of file binreloc.c.
00433 { 00434 char *prefix, *dir; 00435 00436 prefix = br_find_prefix ((const char *) NULL); 00437 if (prefix == (char *) NULL) { 00438 /* BinReloc not initialized. */ 00439 if (default_bin_dir != (const char *) NULL) 00440 return strdup (default_bin_dir); 00441 else 00442 return (char *) NULL; 00443 } 00444 00445 dir = br_build_path (prefix, "bin"); 00446 free (prefix); 00447 return dir; 00448 }
char* br_find_data_dir | ( | const char * | default_data_dir | ) |
Locate the application's data folder.
The path is generated by the following pseudo-code evaluation:
prefix + "/share"
default_data_dir | A default path which will used as fallback. |
Definition at line 499 of file binreloc.c.
00500 { 00501 char *prefix, *dir; 00502 00503 prefix = br_find_prefix ((const char *) NULL); 00504 if (prefix == (char *) NULL) { 00505 /* BinReloc not initialized. */ 00506 if (default_data_dir != (const char *) NULL) 00507 return strdup (default_data_dir); 00508 else 00509 return (char *) NULL; 00510 } 00511 00512 dir = br_build_path (prefix, "share"); 00513 free (prefix); 00514 return dir; 00515 }
char* br_find_etc_dir | ( | const char * | default_etc_dir | ) |
Locate the application's configuration files folder.
The path is generated by the following pseudo-code evaluation:
prefix + "/etc"
default_etc_dir | A default path which will used as fallback. |
Definition at line 631 of file binreloc.c.
00632 { 00633 char *prefix, *dir; 00634 00635 prefix = br_find_prefix ((const char *) NULL); 00636 if (prefix == (char *) NULL) { 00637 /* BinReloc not initialized. */ 00638 if (default_etc_dir != (const char *) NULL) 00639 return strdup (default_etc_dir); 00640 else 00641 return (char *) NULL; 00642 } 00643 00644 dir = br_build_path (prefix, "etc"); 00645 free (prefix); 00646 return dir; 00647 }
char* br_find_exe | ( | const char * | default_exe | ) |
Find the canonical filename of the current application.
default_exe | A default filename which will be used as fallback. |
Definition at line 343 of file binreloc.c.
00344 { 00345 if (exe == (char *) NULL) { 00346 /* BinReloc is not initialized. */ 00347 if (default_exe != (const char *) NULL) 00348 return strdup (default_exe); 00349 else 00350 return (char *) NULL; 00351 } 00352 return strdup (exe); 00353 }
char* br_find_exe_dir | ( | const char * | default_dir | ) |
Locate the directory in which the current application is installed.
The prefix is generated by the following pseudo-code evaluation:
dirname(exename)
default_dir | A default directory which will used as fallback. |
Definition at line 371 of file binreloc.c.
00372 { 00373 if (exe == NULL) { 00374 /* BinReloc not initialized. */ 00375 if (default_dir != NULL) 00376 return strdup (default_dir); 00377 else 00378 return NULL; 00379 } 00380 00381 return br_dirname (exe); 00382 }
char* br_find_lib_dir | ( | const char * | default_lib_dir | ) |
Locate the application's library folder.
The path is generated by the following pseudo-code evaluation:
prefix + "/lib"
default_lib_dir | A default path which will used as fallback. |
Definition at line 565 of file binreloc.c.
00566 { 00567 char *prefix, *dir; 00568 00569 prefix = br_find_prefix ((const char *) NULL); 00570 if (prefix == (char *) NULL) { 00571 /* BinReloc not initialized. */ 00572 if (default_lib_dir != (const char *) NULL) 00573 return strdup (default_lib_dir); 00574 else 00575 return (char *) NULL; 00576 } 00577 00578 dir = br_build_path (prefix, "lib"); 00579 free (prefix); 00580 return dir; 00581 }
char* br_find_libexec_dir | ( | const char * | default_libexec_dir | ) |
Locate the application's libexec folder.
The path is generated by the following pseudo-code evaluation:
prefix + "/libexec"
default_libexec_dir | A default path which will used as fallback. |
Definition at line 598 of file binreloc.c.
00599 { 00600 char *prefix, *dir; 00601 00602 prefix = br_find_prefix ((const char *) NULL); 00603 if (prefix == (char *) NULL) { 00604 /* BinReloc not initialized. */ 00605 if (default_libexec_dir != (const char *) NULL) 00606 return strdup (default_libexec_dir); 00607 else 00608 return (char *) NULL; 00609 } 00610 00611 dir = br_build_path (prefix, "libexec"); 00612 free (prefix); 00613 return dir; 00614 }
char* br_find_locale_dir | ( | const char * | default_locale_dir | ) |
Locate the application's localization folder.
The path is generated by the following pseudo-code evaluation:
prefix + "/share/locale"
default_locale_dir | A default path which will used as fallback. |
Definition at line 532 of file binreloc.c.
00533 { 00534 char *data_dir, *dir; 00535 00536 data_dir = br_find_data_dir ((const char *) NULL); 00537 if (data_dir == (char *) NULL) { 00538 /* BinReloc not initialized. */ 00539 if (default_locale_dir != (const char *) NULL) 00540 return strdup (default_locale_dir); 00541 else 00542 return (char *) NULL; 00543 } 00544 00545 dir = br_build_path (data_dir, "locale"); 00546 free (data_dir); 00547 return dir; 00548 }
char* br_find_prefix | ( | const char * | default_prefix | ) |
Locate the prefix in which the current application is installed.
The prefix is generated by the following pseudo-code evaluation:
dirname(dirname(exename))
default_prefix | A default prefix which will used as fallback. |
Definition at line 399 of file binreloc.c.
00400 { 00401 char *dir1, *dir2; 00402 00403 if (exe == (char *) NULL) { 00404 /* BinReloc not initialized. */ 00405 if (default_prefix != (const char *) NULL) 00406 return strdup (default_prefix); 00407 else 00408 return (char *) NULL; 00409 } 00410 00411 dir1 = br_dirname (exe); 00412 dir2 = br_dirname (dir1); 00413 free (dir1); 00414 return dir2; 00415 }
char* br_find_sbin_dir | ( | const char * | default_sbin_dir | ) |
Locate the application's superuser binary folder.
The path is generated by the following pseudo-code evaluation:
prefix + "/sbin"
default_sbin_dir | A default path which will used as fallback. |
Definition at line 465 of file binreloc.c.
00466 { 00467 char *prefix, *dir; 00468 00469 prefix = br_find_prefix ((const char *) NULL); 00470 if (prefix == (char *) NULL) { 00471 /* BinReloc not initialized. */ 00472 if (default_sbin_dir != (const char *) NULL) 00473 return strdup (default_sbin_dir); 00474 else 00475 return (char *) NULL; 00476 } 00477 00478 dir = br_build_path (prefix, "sbin"); 00479 free (prefix); 00480 return dir; 00481 }
int br_init | ( | BrInitError * | error | ) |
Initialize the BinReloc library (for applications).
This function must be called before using any other BinReloc functions. It attempts to locate the application's canonical filename.
error | If BinReloc failed to initialize, then the error code will be stored in this variable. Set to NULL if you want to ignore this. See BrInitError for a list of error codes. |
Definition at line 304 of file binreloc.c.
00305 { 00306 exe = _br_find_exe (error); 00307 return exe != NULL; 00308 }
Here is the call graph for this function:
int br_init_lib | ( | BrInitError * | error | ) |
Initialize the BinReloc library (for libraries).
This function must be called before using any other BinReloc functions. It attempts to locate the calling library's canonical filename.
error | If BinReloc failed to initialize, then the error code will be stored in this variable. Set to NULL if you want to ignore this. See BrInitError for a list of error codes. |
Definition at line 326 of file binreloc.c.
00327 { 00328 exe = _br_find_exe_for_symbol ((const void *) "", error); 00329 return exe != NULL; 00330 }
Here is the call graph for this function:
char* br_strcat | ( | const char * | str1, | |
const char * | str2 | |||
) |
Concatenate str1 and str2 to a newly allocated string.
str1 | A string. | |
str2 | Another string. |
Definition at line 661 of file binreloc.c.
00662 { 00663 char *result; 00664 size_t len1, len2; 00665 00666 if (str1 == NULL) 00667 str1 = ""; 00668 if (str2 == NULL) 00669 str2 = ""; 00670 00671 len1 = strlen (str1); 00672 len2 = strlen (str2); 00673 00674 result = (char *) malloc (len1 + len2 + 1); 00675 memcpy (result, str1, len1); 00676 memcpy (result + len1, str2, len2); 00677 result[len1 + len2] = '\0'; 00678 00679 return result; 00680 }
static char* br_strndup | ( | const char * | str, | |
size_t | size | |||
) | [static] |
Definition at line 706 of file binreloc.c.
00707 { 00708 char *result = (char *) NULL; 00709 size_t len; 00710 00711 if (str == (const char *) NULL) 00712 return (char *) NULL; 00713 00714 len = strlen (str); 00715 if (len == 0) 00716 return strdup (""); 00717 if (size > len) 00718 size = len; 00719 00720 result = (char *) malloc (len + 1); 00721 memcpy (result, str, size); 00722 result[size] = '\0'; 00723 return result; 00724 }
Here is the caller graph for this function:
char* exe = (char *) NULL [static] |
Definition at line 286 of file binreloc.c.