src/include/binreloc.c File Reference

#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 Documentation

#define NULL   ((void *) 0)

Definition at line 283 of file binreloc.c.


Function Documentation

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"

Parameters:
path A path.
Returns:
A directory name. This string should be freed when no longer needed.

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"

Parameters:
default_bin_dir A default path which will used as fallback.
Returns:
A string containing the bin folder's path, which must be freed when no longer necessary. If BinReloc is not initialized, or if the initialization function failed, then a copy of default_bin_dir will be returned. If default_bin_dir is NULL, then NULL will be returned.

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"

Parameters:
default_data_dir A default path which will used as fallback.
Returns:
A string containing the data folder's path, which must be freed when no longer necessary. If BinReloc is not initialized, or if the initialization function failed, then a copy of default_data_dir will be returned. If default_data_dir is NULL, then NULL will be returned.

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"

Parameters:
default_etc_dir A default path which will used as fallback.
Returns:
A string containing the etc folder's path, which must be freed when no longer necessary. If BinReloc is not initialized, or if the initialization function failed, then a copy of default_etc_dir will be returned. If default_etc_dir is NULL, then NULL will be returned.

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.

Parameters:
default_exe A default filename which will be used as fallback.
Returns:
A string containing the application's canonical filename, which must be freed when no longer necessary. If BinReloc is not initialized, or if br_init() failed, then a copy of default_exe will be returned. If default_exe is NULL, then NULL will be returned.

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)

Parameters:
default_dir A default directory which will used as fallback.
Returns:
A string containing the directory, which must be freed when no longer necessary. If BinReloc is not initialized, or if the initialization function failed, then a copy of default_dir will be returned. If default_dir is NULL, then NULL will be returned.

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"

Parameters:
default_lib_dir A default path which will used as fallback.
Returns:
A string containing the library folder's path, which must be freed when no longer necessary. If BinReloc is not initialized, or if the initialization function failed, then a copy of default_lib_dir will be returned. If default_lib_dir is NULL, then NULL will be returned.

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"

Parameters:
default_libexec_dir A default path which will used as fallback.
Returns:
A string containing the libexec folder's path, which must be freed when no longer necessary. If BinReloc is not initialized, or if the initialization function failed, then a copy of default_libexec_dir will be returned. If default_libexec_dir is NULL, then NULL will be returned.

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"

Parameters:
default_locale_dir A default path which will used as fallback.
Returns:
A string containing the localization folder's path, which must be freed when no longer necessary. If BinReloc is not initialized, or if the initialization function failed, then a copy of default_locale_dir will be returned. If default_locale_dir is NULL, then NULL will be returned.

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))

Parameters:
default_prefix A default prefix which will used as fallback.
Returns:
A string containing the prefix, which must be freed when no longer necessary. If BinReloc is not initialized, or if the initialization function failed, then a copy of default_prefix will be returned. If default_prefix is NULL, then NULL will be returned.

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"

Parameters:
default_sbin_dir A default path which will used as fallback.
Returns:
A string containing the sbin folder's path, which must be freed when no longer necessary. If BinReloc is not initialized, or if the initialization function failed, then a copy of default_sbin_dir will be returned. If default_bin_dir is NULL, then NULL will be returned.

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.

Note:
If you want to use BinReloc for a library, then you should call br_init_lib() instead.
Parameters:
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.
Returns:
1 on success, 0 if BinReloc failed to initialize.

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.

Note:
The BinReloc source code MUST be included in your library, or this function won't work correctly.
Parameters:
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.
Returns:
1 on success, 0 if a filename cannot be found.

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.

Parameters:
str1 A string.
str2 Another string.
Returns:
A newly-allocated string. This string should be freed when no longer needed.

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:


Variable Documentation

char* exe = (char *) NULL [static]

Definition at line 286 of file binreloc.c.


Generated on Mon Jan 1 13:19:17 2007 for Wormux by  doxygen 1.4.7