LCOV - code coverage report
Current view: top level - LHAPDF/lhapdf5.5.1/src - binreloc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 138 0.0 %
Date: 2016-06-14 17:26:59 Functions: 0 18 0.0 %

          Line data    Source code
       1             : /*
       2             :  * BinReloc - a library for creating relocatable executables
       3             :  * Written by: Hongli Lai <h.lai@chello.nl>
       4             :  * http://autopackage.org/
       5             :  *
       6             :  * This source code is public domain. You can relicense this code
       7             :  * under whatever license you want.
       8             :  *
       9             :  * See http://autopackage.org/docs/binreloc/ for
      10             :  * more information and how to use this.
      11             :  */
      12             : 
      13             : #ifndef __BINRELOC_C__
      14             : #define __BINRELOC_C__
      15             : 
      16             : #ifdef ENABLE_BINRELOC
      17             :         #include <sys/types.h>
      18             :         #include <sys/stat.h>
      19             :         #include <unistd.h>
      20             : #endif /* ENABLE_BINRELOC */
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <limits.h>
      24             : #include <string.h>
      25             : #include "binreloc.h"
      26             : 
      27             : #ifdef __cplusplus
      28             : extern "C" {
      29             : #endif /* __cplusplus */
      30             : 
      31             : extern char* strdup(const char*);
      32             : 
      33             : /** @internal
      34             :  * Find the canonical filename of the executable. Returns the filename
      35             :  * (which must be freed) or NULL on error. If the parameter 'error' is
      36             :  * not NULL, the error code will be stored there, if an error occured.
      37             :  */
      38             : static char *
      39             : _br_find_exe (BrInitError *error)
      40             : {
      41             : #ifndef ENABLE_BINRELOC
      42           0 :         if (error)
      43           0 :                 *error = BR_INIT_ERROR_DISABLED;
      44           0 :         return NULL;
      45             : #else
      46             :         char *path, *path2, *line, *result;
      47             :         size_t buf_size;
      48             :         ssize_t size;
      49             :         struct stat stat_buf;
      50             :         FILE *f;
      51             : 
      52             :         /* Read from /proc/self/exe (symlink) */
      53             :         if (sizeof (path) > SSIZE_MAX)
      54             :                 buf_size = SSIZE_MAX - 1;
      55             :         else
      56             :                 buf_size = PATH_MAX - 1;
      57             :         path = (char *) malloc (buf_size);
      58             :         if (path == NULL) {
      59             :                 /* Cannot allocate memory. */
      60             :                 if (error)
      61             :                         *error = BR_INIT_ERROR_NOMEM;
      62             :                 return NULL;
      63             :         }
      64             :         path2 = (char *) malloc (buf_size);
      65             :         if (path2 == NULL) {
      66             :                 /* Cannot allocate memory. */
      67             :                 if (error)
      68             :                         *error = BR_INIT_ERROR_NOMEM;
      69             :                 free (path);
      70             :                 return NULL;
      71             :         }
      72             : 
      73             :         strncpy (path2, "/proc/self/exe", buf_size - 1);
      74             : 
      75             :         while (1) {
      76             :                 int i;
      77             : 
      78             :                 size = readlink (path2, path, buf_size - 1);
      79             :                 if (size == -1) {
      80             :                         /* Error. */
      81             :                         free (path2);
      82             :                         break;
      83             :                 }
      84             : 
      85             :                 /* readlink() success. */
      86             :                 path[size] = '\0';
      87             : 
      88             :                 /* Check whether the symlink's target is also a symlink.
      89             :                  * We want to get the final target. */
      90             :                 i = stat (path, &stat_buf);
      91             :                 if (i == -1) {
      92             :                         /* Error. */
      93             :                         free (path2);
      94             :                         break;
      95             :                 }
      96             : 
      97             :                 /* stat() success. */
      98             :                 if (!S_ISLNK (stat_buf.st_mode)) {
      99             :                         /* path is not a symlink. Done. */
     100             :                         free (path2);
     101             :                         return path;
     102             :                 }
     103             : 
     104             :                 /* path is a symlink. Continue loop and resolve this. */
     105             :                 strncpy (path, path2, buf_size - 1);
     106             :         }
     107             : 
     108             : 
     109             :         /* readlink() or stat() failed; this can happen when the program is
     110             :          * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */
     111             : 
     112             :         buf_size = PATH_MAX + 128;
     113             :         line = (char *) realloc (path, buf_size);
     114             :         if (line == NULL) {
     115             :                 /* Cannot allocate memory. */
     116             :                 free (path);
     117             :                 if (error)
     118             :                         *error = BR_INIT_ERROR_NOMEM;
     119             :                 return NULL;
     120             :         }
     121             : 
     122             :         f = fopen ("/proc/self/maps", "r");
     123             :         if (f == NULL) {
     124             :                 free (line);
     125             :                 if (error)
     126             :                         *error = BR_INIT_ERROR_OPEN_MAPS;
     127             :                 return NULL;
     128             :         }
     129             : 
     130             :         /* The first entry should be the executable name. */
     131             :         result = fgets (line, (int) buf_size, f);
     132             :         if (result == NULL) {
     133             :                 fclose (f);
     134             :                 free (line);
     135             :                 if (error)
     136             :                         *error = BR_INIT_ERROR_READ_MAPS;
     137             :                 return NULL;
     138             :         }
     139             : 
     140             :         /* Get rid of newline character. */
     141             :         buf_size = strlen (line);
     142             :         if (buf_size <= 0) {
     143             :                 /* Huh? An empty string? */
     144             :                 fclose (f);
     145             :                 free (line);
     146             :                 if (error)
     147             :                         *error = BR_INIT_ERROR_INVALID_MAPS;
     148             :                 return NULL;
     149             :         }
     150             :         if (line[buf_size - 1] == 10)
     151             :                 line[buf_size - 1] = 0;
     152             : 
     153             :         /* Extract the filename; it is always an absolute path. */
     154             :         path = strchr (line, '/');
     155             : 
     156             :         /* Sanity check. */
     157             :         if (strstr (line, " r-xp ") == NULL || path == NULL) {
     158             :                 fclose (f);
     159             :                 free (line);
     160             :                 if (error)
     161             :                         *error = BR_INIT_ERROR_INVALID_MAPS;
     162             :                 return NULL;
     163             :         }
     164             : 
     165             :         path = strdup (path);
     166             :         free (line);
     167             :         fclose (f);
     168             :         return path;
     169             : #endif /* ENABLE_BINRELOC */
     170             : }
     171             : 
     172             : 
     173             : /** @internal
     174             :  * Find the canonical filename of the executable which owns symbol.
     175             :  * Returns a filename which must be freed, or NULL on error.
     176             :  */
     177             : static char *
     178             : _br_find_exe_for_symbol (const void *symbol, BrInitError *error)
     179             : {
     180             : #ifndef ENABLE_BINRELOC
     181           0 :         if (error)
     182           0 :                 *error = BR_INIT_ERROR_DISABLED;
     183           0 :         return (char *) NULL;
     184             : #else
     185             :         #define SIZE PATH_MAX + 100
     186             :         FILE *f;
     187             :         size_t address_string_len;
     188             :         char *address_string, line[SIZE], *found;
     189             : 
     190             :         if (symbol == NULL)
     191             :                 return (char *) NULL;
     192             : 
     193             :         f = fopen ("/proc/self/maps", "r");
     194             :         if (f == NULL)
     195             :                 return (char *) NULL;
     196             : 
     197             :         address_string_len = 4;
     198             :         address_string = (char *) malloc (address_string_len);
     199             :         found = (char *) NULL;
     200             : 
     201             :         while (!feof (f)) {
     202             :                 char *start_addr, *end_addr, *end_addr_end, *file;
     203             :                 void *start_addr_p, *end_addr_p;
     204             :                 size_t len;
     205             : 
     206             :                 if (fgets (line, SIZE, f) == NULL)
     207             :                         break;
     208             : 
     209             :                 /* Sanity check. */
     210             :                 if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
     211             :                         continue;
     212             : 
     213             :                 /* Parse line. */
     214             :                 start_addr = line;
     215             :                 end_addr = strchr (line, '-');
     216             :                 file = strchr (line, '/');
     217             : 
     218             :                 /* More sanity check. */
     219             :                 if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
     220             :                         continue;
     221             : 
     222             :                 end_addr[0] = '\0';
     223             :                 end_addr++;
     224             :                 end_addr_end = strchr (end_addr, ' ');
     225             :                 if (end_addr_end == NULL)
     226             :                         continue;
     227             : 
     228             :                 end_addr_end[0] = '\0';
     229             :                 len = strlen (file);
     230             :                 if (len == 0)
     231             :                         continue;
     232             :                 if (file[len - 1] == '\n')
     233             :                         file[len - 1] = '\0';
     234             : 
     235             :                 /* Get rid of "(deleted)" from the filename. */
     236             :                 len = strlen (file);
     237             :                 if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
     238             :                         file[len - 10] = '\0';
     239             : 
     240             :                 /* I don't know whether this can happen but better safe than sorry. */
     241             :                 len = strlen (start_addr);
     242             :                 if (len != strlen (end_addr))
     243             :                         continue;
     244             : 
     245             : 
     246             :                 /* Transform the addresses into a string in the form of 0xdeadbeef,
     247             :                  * then transform that into a pointer. */
     248             :                 if (address_string_len < len + 3) {
     249             :                         address_string_len = len + 3;
     250             :                         address_string = (char *) realloc (address_string, address_string_len);
     251             :                 }
     252             : 
     253             :                 memcpy (address_string, "0x", 2);
     254             :                 memcpy (address_string + 2, start_addr, len);
     255             :                 address_string[2 + len] = '\0';
     256             :                 sscanf (address_string, "%p", &start_addr_p);
     257             : 
     258             :                 memcpy (address_string, "0x", 2);
     259             :                 memcpy (address_string + 2, end_addr, len);
     260             :                 address_string[2 + len] = '\0';
     261             :                 sscanf (address_string, "%p", &end_addr_p);
     262             : 
     263             : 
     264             :                 if (symbol >= start_addr_p && symbol < end_addr_p) {
     265             :                         found = file;
     266             :                         break;
     267             :                 }
     268             :         }
     269             : 
     270             :         free (address_string);
     271             :         fclose (f);
     272             : 
     273             :         if (found == NULL)
     274             :                 return (char *) NULL;
     275             :         else
     276             :                 return strdup (found);
     277             : #endif /* ENABLE_BINRELOC */
     278             : }
     279             : 
     280             : 
     281             : #ifndef BINRELOC_RUNNING_DOXYGEN
     282             :         #undef NULL
     283             :         #define NULL ((void *) 0) /* typecasted as char* for C++ type safeness */
     284             : #endif
     285             : 
     286             : static char *exe = (char *) NULL;
     287             : 
     288             : 
     289             : /** Initialize the BinReloc library (for applications).
     290             :  *
     291             :  * This function must be called before using any other BinReloc functions.
     292             :  * It attempts to locate the application's canonical filename.
     293             :  *
     294             :  * @note If you want to use BinReloc for a library, then you should call
     295             :  *       br_init_lib() instead.
     296             :  *
     297             :  * @param error  If BinReloc failed to initialize, then the error code will
     298             :  *               be stored in this variable. Set to NULL if you want to
     299             :  *               ignore this. See #BrInitError for a list of error codes.
     300             :  *
     301             :  * @returns 1 on success, 0 if BinReloc failed to initialize.
     302             :  */
     303             : int
     304             : br_init (BrInitError *error)
     305             : {
     306           0 :         exe = _br_find_exe (error);
     307           0 :         return exe != NULL;
     308             : }
     309             : 
     310             : 
     311             : /** Initialize the BinReloc library (for libraries).
     312             :  *
     313             :  * This function must be called before using any other BinReloc functions.
     314             :  * It attempts to locate the calling library's canonical filename.
     315             :  *
     316             :  * @note The BinReloc source code MUST be included in your library, or this
     317             :  *       function won't work correctly.
     318             :  *
     319             :  * @param error  If BinReloc failed to initialize, then the error code will
     320             :  *               be stored in this variable. Set to NULL if you want to
     321             :  *               ignore this. See #BrInitError for a list of error codes.
     322             :  *
     323             :  * @returns 1 on success, 0 if a filename cannot be found.
     324             :  */
     325             : int
     326             : br_init_lib (BrInitError *error)
     327             : {
     328           0 :         exe = _br_find_exe_for_symbol ((const void *) "", error);
     329           0 :         return exe != NULL;
     330             : }
     331             : 
     332             : 
     333             : /** Find the canonical filename of the current application.
     334             :  *
     335             :  * @param default_exe  A default filename which will be used as fallback.
     336             :  * @returns A string containing the application's canonical filename,
     337             :  *          which must be freed when no longer necessary. If BinReloc is
     338             :  *          not initialized, or if br_init() failed, then a copy of
     339             :  *          default_exe will be returned. If default_exe is NULL, then
     340             :  *          NULL will be returned.
     341             :  */
     342             : char *
     343             : br_find_exe (const char *default_exe)
     344             : {
     345           0 :         if (exe == (char *) NULL) {
     346             :                 /* BinReloc is not initialized. */
     347           0 :                 if (default_exe != (const char *) NULL)
     348           0 :                         return strdup (default_exe);
     349             :                 else
     350           0 :                         return (char *) NULL;
     351             :         }
     352           0 :         return strdup (exe);
     353           0 : }
     354             : 
     355             : 
     356             : /** Locate the directory in which the current application is installed.
     357             :  *
     358             :  * The prefix is generated by the following pseudo-code evaluation:
     359             :  * \code
     360             :  * dirname(exename)
     361             :  * \endcode
     362             :  *
     363             :  * @param default_dir  A default directory which will used as fallback.
     364             :  * @return A string containing the directory, which must be freed when no
     365             :  *         longer necessary. If BinReloc is not initialized, or if the
     366             :  *         initialization function failed, then a copy of default_dir
     367             :  *         will be returned. If default_dir is NULL, then NULL will be
     368             :  *         returned.
     369             :  */
     370             : char *
     371             : br_find_exe_dir (const char *default_dir)
     372             : {
     373           0 :         if (exe == NULL) {
     374             :                 /* BinReloc not initialized. */
     375           0 :                 if (default_dir != NULL)
     376           0 :                         return strdup (default_dir);
     377             :                 else
     378           0 :                         return NULL;
     379             :         }
     380             : 
     381           0 :         return br_dirname (exe);
     382           0 : }
     383             : 
     384             : 
     385             : /** Locate the prefix in which the current application is installed.
     386             :  *
     387             :  * The prefix is generated by the following pseudo-code evaluation:
     388             :  * \code
     389             :  * dirname(dirname(exename))
     390             :  * \endcode
     391             :  *
     392             :  * @param default_prefix  A default prefix which will used as fallback.
     393             :  * @return A string containing the prefix, which must be freed when no
     394             :  *         longer necessary. If BinReloc is not initialized, or if
     395             :  *         the initialization function failed, then a copy of default_prefix
     396             :  *         will be returned. If default_prefix is NULL, then NULL will be returned.
     397             :  */
     398             : char *
     399             : br_find_prefix (const char *default_prefix)
     400             : {
     401             :         char *dir1, *dir2;
     402             : 
     403           0 :         if (exe == (char *) NULL) {
     404             :                 /* BinReloc not initialized. */
     405           0 :                 if (default_prefix != (const char *) NULL)
     406           0 :                         return strdup (default_prefix);
     407             :                 else
     408           0 :                         return (char *) NULL;
     409             :         }
     410             : 
     411           0 :         dir1 = br_dirname (exe);
     412           0 :         dir2 = br_dirname (dir1);
     413           0 :         free (dir1);
     414           0 :         return dir2;
     415           0 : }
     416             : 
     417             : 
     418             : /** Locate the application's binary folder.
     419             :  *
     420             :  * The path is generated by the following pseudo-code evaluation:
     421             :  * \code
     422             :  * prefix + "/bin"
     423             :  * \endcode
     424             :  *
     425             :  * @param default_bin_dir  A default path which will used as fallback.
     426             :  * @return A string containing the bin folder's path, which must be freed when
     427             :  *         no longer necessary. If BinReloc is not initialized, or if
     428             :  *         the initialization function failed, then a copy of default_bin_dir will
     429             :  *         be returned. If default_bin_dir is NULL, then NULL will be returned.
     430             :  */
     431             : char *
     432             : br_find_bin_dir (const char *default_bin_dir)
     433             : {
     434             :         char *prefix, *dir;
     435             : 
     436           0 :         prefix = br_find_prefix ((const char *) NULL);
     437           0 :         if (prefix == (char *) NULL) {
     438             :                 /* BinReloc not initialized. */
     439           0 :                 if (default_bin_dir != (const char *) NULL)
     440           0 :                         return strdup (default_bin_dir);
     441             :                 else
     442           0 :                         return (char *) NULL;
     443             :         }
     444             : 
     445           0 :         dir = br_build_path (prefix, "bin");
     446           0 :         free (prefix);
     447           0 :         return dir;
     448           0 : }
     449             : 
     450             : 
     451             : /** Locate the application's superuser binary folder.
     452             :  *
     453             :  * The path is generated by the following pseudo-code evaluation:
     454             :  * \code
     455             :  * prefix + "/sbin"
     456             :  * \endcode
     457             :  *
     458             :  * @param default_sbin_dir  A default path which will used as fallback.
     459             :  * @return A string containing the sbin folder's path, which must be freed when
     460             :  *         no longer necessary. If BinReloc is not initialized, or if the
     461             :  *         initialization function failed, then a copy of default_sbin_dir will
     462             :  *         be returned. If default_bin_dir is NULL, then NULL will be returned.
     463             :  */
     464             : char *
     465             : br_find_sbin_dir (const char *default_sbin_dir)
     466             : {
     467             :         char *prefix, *dir;
     468             : 
     469           0 :         prefix = br_find_prefix ((const char *) NULL);
     470           0 :         if (prefix == (char *) NULL) {
     471             :                 /* BinReloc not initialized. */
     472           0 :                 if (default_sbin_dir != (const char *) NULL)
     473           0 :                         return strdup (default_sbin_dir);
     474             :                 else
     475           0 :                         return (char *) NULL;
     476             :         }
     477             : 
     478           0 :         dir = br_build_path (prefix, "sbin");
     479           0 :         free (prefix);
     480           0 :         return dir;
     481           0 : }
     482             : 
     483             : 
     484             : /** Locate the application's data folder.
     485             :  *
     486             :  * The path is generated by the following pseudo-code evaluation:
     487             :  * \code
     488             :  * prefix + "/share"
     489             :  * \endcode
     490             :  *
     491             :  * @param default_data_dir  A default path which will used as fallback.
     492             :  * @return A string containing the data folder's path, which must be freed when
     493             :  *         no longer necessary. If BinReloc is not initialized, or if the
     494             :  *         initialization function failed, then a copy of default_data_dir
     495             :  *         will be returned. If default_data_dir is NULL, then NULL will be
     496             :  *         returned.
     497             :  */
     498             : char *
     499             : br_find_data_dir (const char *default_data_dir)
     500             : {
     501             :         char *prefix, *dir;
     502             : 
     503           0 :         prefix = br_find_prefix ((const char *) NULL);
     504           0 :         if (prefix == (char *) NULL) {
     505             :                 /* BinReloc not initialized. */
     506           0 :                 if (default_data_dir != (const char *) NULL)
     507           0 :                         return strdup (default_data_dir);
     508             :                 else
     509           0 :                         return (char *) NULL;
     510             :         }
     511             : 
     512           0 :         dir = br_build_path (prefix, "share");
     513           0 :         free (prefix);
     514           0 :         return dir;
     515           0 : }
     516             : 
     517             : 
     518             : /** Locate the application's localization folder.
     519             :  *
     520             :  * The path is generated by the following pseudo-code evaluation:
     521             :  * \code
     522             :  * prefix + "/share/locale"
     523             :  * \endcode
     524             :  *
     525             :  * @param default_locale_dir  A default path which will used as fallback.
     526             :  * @return A string containing the localization folder's path, which must be freed when
     527             :  *         no longer necessary. If BinReloc is not initialized, or if the
     528             :  *         initialization function failed, then a copy of default_locale_dir will be returned.
     529             :  *         If default_locale_dir is NULL, then NULL will be returned.
     530             :  */
     531             : char *
     532             : br_find_locale_dir (const char *default_locale_dir)
     533             : {
     534             :         char *data_dir, *dir;
     535             : 
     536           0 :         data_dir = br_find_data_dir ((const char *) NULL);
     537           0 :         if (data_dir == (char *) NULL) {
     538             :                 /* BinReloc not initialized. */
     539           0 :                 if (default_locale_dir != (const char *) NULL)
     540           0 :                         return strdup (default_locale_dir);
     541             :                 else
     542           0 :                         return (char *) NULL;
     543             :         }
     544             : 
     545           0 :         dir = br_build_path (data_dir, "locale");
     546           0 :         free (data_dir);
     547           0 :         return dir;
     548           0 : }
     549             : 
     550             : 
     551             : /** Locate the application's library folder.
     552             :  *
     553             :  * The path is generated by the following pseudo-code evaluation:
     554             :  * \code
     555             :  * prefix + "/lib"
     556             :  * \endcode
     557             :  *
     558             :  * @param default_lib_dir  A default path which will used as fallback.
     559             :  * @return A string containing the library folder's path, which must be freed when
     560             :  *         no longer necessary. If BinReloc is not initialized, or if the initialization
     561             :  *         function failed, then a copy of default_lib_dir will be returned.
     562             :  *         If default_lib_dir is NULL, then NULL will be returned.
     563             :  */
     564             : char *
     565             : br_find_lib_dir (const char *default_lib_dir)
     566             : {
     567             :         char *prefix, *dir;
     568             : 
     569           0 :         prefix = br_find_prefix ((const char *) NULL);
     570           0 :         if (prefix == (char *) NULL) {
     571             :                 /* BinReloc not initialized. */
     572           0 :                 if (default_lib_dir != (const char *) NULL)
     573           0 :                         return strdup (default_lib_dir);
     574             :                 else
     575           0 :                         return (char *) NULL;
     576             :         }
     577             : 
     578           0 :         dir = br_build_path (prefix, "lib");
     579           0 :         free (prefix);
     580           0 :         return dir;
     581           0 : }
     582             : 
     583             : 
     584             : /** Locate the application's libexec folder.
     585             :  *
     586             :  * The path is generated by the following pseudo-code evaluation:
     587             :  * \code
     588             :  * prefix + "/libexec"
     589             :  * \endcode
     590             :  *
     591             :  * @param default_libexec_dir  A default path which will used as fallback.
     592             :  * @return A string containing the libexec folder's path, which must be freed when
     593             :  *         no longer necessary. If BinReloc is not initialized, or if the initialization
     594             :  *         function failed, then a copy of default_libexec_dir will be returned.
     595             :  *         If default_libexec_dir is NULL, then NULL will be returned.
     596             :  */
     597             : char *
     598             : br_find_libexec_dir (const char *default_libexec_dir)
     599             : {
     600             :         char *prefix, *dir;
     601             : 
     602           0 :         prefix = br_find_prefix ((const char *) NULL);
     603           0 :         if (prefix == (char *) NULL) {
     604             :                 /* BinReloc not initialized. */
     605           0 :                 if (default_libexec_dir != (const char *) NULL)
     606           0 :                         return strdup (default_libexec_dir);
     607             :                 else
     608           0 :                         return (char *) NULL;
     609             :         }
     610             : 
     611           0 :         dir = br_build_path (prefix, "libexec");
     612           0 :         free (prefix);
     613           0 :         return dir;
     614           0 : }
     615             : 
     616             : 
     617             : /** Locate the application's configuration files folder.
     618             :  *
     619             :  * The path is generated by the following pseudo-code evaluation:
     620             :  * \code
     621             :  * prefix + "/etc"
     622             :  * \endcode
     623             :  *
     624             :  * @param default_etc_dir  A default path which will used as fallback.
     625             :  * @return A string containing the etc folder's path, which must be freed when
     626             :  *         no longer necessary. If BinReloc is not initialized, or if the initialization
     627             :  *         function failed, then a copy of default_etc_dir will be returned.
     628             :  *         If default_etc_dir is NULL, then NULL will be returned.
     629             :  */
     630             : char *
     631             : br_find_etc_dir (const char *default_etc_dir)
     632             : {
     633             :         char *prefix, *dir;
     634             : 
     635           0 :         prefix = br_find_prefix ((const char *) NULL);
     636           0 :         if (prefix == (char *) NULL) {
     637             :                 /* BinReloc not initialized. */
     638           0 :                 if (default_etc_dir != (const char *) NULL)
     639           0 :                         return strdup (default_etc_dir);
     640             :                 else
     641           0 :                         return (char *) NULL;
     642             :         }
     643             : 
     644           0 :         dir = br_build_path (prefix, "etc");
     645           0 :         free (prefix);
     646           0 :         return dir;
     647           0 : }
     648             : 
     649             : 
     650             : /***********************
     651             :  * Utility functions
     652             :  ***********************/
     653             : 
     654             : /** Concatenate str1 and str2 to a newly allocated string.
     655             :  *
     656             :  * @param str1 A string.
     657             :  * @param str2 Another string.
     658             :  * @returns A newly-allocated string. This string should be freed when no longer needed.
     659             :  */
     660             : char *
     661             : br_strcat (const char *str1, const char *str2)
     662             : {
     663             :         char *result;
     664             :         size_t len1, len2;
     665             : 
     666           0 :         if (str1 == NULL)
     667           0 :                 str1 = "";
     668           0 :         if (str2 == NULL)
     669           0 :                 str2 = "";
     670             : 
     671           0 :         len1 = strlen (str1);
     672           0 :         len2 = strlen (str2);
     673             : 
     674           0 :         result = (char *) malloc (len1 + len2 + 1);
     675           0 :         memcpy (result, str1, len1);
     676           0 :         memcpy (result + len1, str2, len2);
     677           0 :         result[len1 + len2] = '\0';
     678             : 
     679           0 :         return result;
     680             : }
     681             : 
     682             : 
     683             : char *
     684             : br_build_path (const char *dir, const char *file)
     685             : {
     686             :         char *dir2, *result;
     687             :         size_t len;
     688             :         int must_free = 0;
     689             : 
     690           0 :         len = strlen (dir);
     691           0 :         if (len > 0 && dir[len - 1] != '/') {
     692           0 :                 dir2 = br_strcat (dir, "/");
     693             :                 must_free = 1;
     694           0 :         } else
     695             :                 dir2 = (char *) dir;
     696             : 
     697           0 :         result = br_strcat (dir2, file);
     698           0 :         if (must_free)
     699           0 :                 free (dir2);
     700           0 :         return result;
     701             : }
     702             : 
     703             : 
     704             : /* Emulates glibc's strndup() */
     705             : static char *
     706             : br_strndup (const char *str, size_t size)
     707             : {
     708             :         char *result = (char *) NULL;
     709             :         size_t len;
     710             : 
     711           0 :         if (str == (const char *) NULL)
     712           0 :                 return (char *) NULL;
     713             : 
     714           0 :         len = strlen (str);
     715           0 :         if (len == 0)
     716           0 :                 return strdup ("");
     717           0 :         if (size > len)
     718           0 :                 size = len;
     719             : 
     720           0 :         result = (char *) malloc (len + 1);
     721           0 :         memcpy (result, str, size);
     722           0 :         result[size] = '\0';
     723           0 :         return result;
     724           0 : }
     725             : 
     726             : 
     727             : /** Extracts the directory component of a path.
     728             :  *
     729             :  * Similar to g_dirname() or the dirname commandline application.
     730             :  *
     731             :  * Example:
     732             :  * \code
     733             :  * br_dirname ("/usr/local/foobar");  --> Returns: "/usr/local"
     734             :  * \endcode
     735             :  *
     736             :  * @param path  A path.
     737             :  * @returns     A directory name. This string should be freed when no longer needed.
     738             :  */
     739             : char *
     740             : br_dirname (const char *path)
     741             : {
     742             :         char *end, *result;
     743             : 
     744           0 :         if (path == (const char *) NULL)
     745           0 :                 return (char *) NULL;
     746             : 
     747           0 :         end = strrchr (path, '/');
     748           0 :         if (end == (const char *) NULL)
     749           0 :                 return strdup (".");
     750             : 
     751           0 :         while (end > path && *end == '/')
     752           0 :                 end--;
     753           0 :         result = br_strndup (path, end - path + 1);
     754           0 :         if (result[0] == 0) {
     755           0 :                 free (result);
     756           0 :                 return strdup ("/");
     757             :         } else
     758           0 :                 return result;
     759           0 : }
     760             : 
     761             : 
     762             : #ifdef __cplusplus
     763             : }
     764             : #endif /* __cplusplus */
     765             : 
     766             : #endif /* __BINRELOC_C__ */

Generated by: LCOV version 1.11