diff options
Diffstat (limited to 'hardinfo2/util/binreloc.c')
| -rw-r--r-- | hardinfo2/util/binreloc.c | 672 | 
1 files changed, 0 insertions, 672 deletions
diff --git a/hardinfo2/util/binreloc.c b/hardinfo2/util/binreloc.c deleted file mode 100644 index 1d1acfe6..00000000 --- a/hardinfo2/util/binreloc.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * BinReloc - a library for creating relocatable executables - * Written by: Hongli Lai <h.lai@chello.nl> - * http://autopackage.org/ - * - * This source code is public domain. You can relicense this code - * under whatever license you want. - * - * See http://autopackage.org/docs/binreloc/ for - * more information and how to use this. - */ - -#ifndef __BINRELOC_C__ -#define __BINRELOC_C__ - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <string.h> -#include "binreloc.h" -#include "config.h" - -G_BEGIN_DECLS -/** @internal - * Find the canonical filename of the executable. Returns the filename - * (which must be freed) or NULL on error. If the parameter 'error' is - * not NULL, the error code will be stored there, if an error occured. - */ -static char *_br_find_exe(GbrInitError * error) -{ -    char *path, *path2, *line, *result; -    size_t buf_size; -    ssize_t size; -    struct stat stat_buf; -    FILE *f; - -    /* Read from /proc/self/exe (symlink) */ -    if (sizeof(path) > SSIZE_MAX) -	buf_size = SSIZE_MAX - 1; -    else -	buf_size = PATH_MAX - 1; -    path = (char *) g_try_malloc(buf_size); -    if (path == NULL) { -	/* Cannot allocate memory. */ -	if (error) -	    *error = GBR_INIT_ERROR_NOMEM; -	return NULL; -    } -    path2 = (char *) g_try_malloc(buf_size); -    if (path2 == NULL) { -	/* Cannot allocate memory. */ -	if (error) -	    *error = GBR_INIT_ERROR_NOMEM; -	g_free(path); -	return NULL; -    } - -    strncpy(path2, "/proc/self/exe", buf_size - 1); - -    while (1) { -	int i; - -	size = readlink(path2, path, buf_size - 1); -	if (size == -1) { -	    /* Error. */ -	    g_free(path2); -	    break; -	} - -	/* readlink() success. */ -	path[size] = '\0'; - -	/* Check whether the symlink's target is also a symlink. -	 * We want to get the final target. */ -	i = stat(path, &stat_buf); -	if (i == -1) { -	    /* Error. */ -	    g_free(path2); -	    break; -	} - -	/* stat() success. */ -	if (!S_ISLNK(stat_buf.st_mode)) { -	    /* path is not a symlink. Done. */ -	    g_free(path2); -	    return path; -	} - -	/* path is a symlink. Continue loop and resolve this. */ -	strncpy(path, path2, buf_size - 1); -    } - - -    /* readlink() or stat() failed; this can happen when the program is -     * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */ - -    buf_size = PATH_MAX + 128; -    line = (char *) g_try_realloc(path, buf_size); -    if (line == NULL) { -	/* Cannot allocate memory. */ -	g_free(path); -	if (error) -	    *error = GBR_INIT_ERROR_NOMEM; -	return NULL; -    } - -    f = fopen("/proc/self/maps", "r"); -    if (f == NULL) { -	g_free(line); -	if (error) -	    *error = GBR_INIT_ERROR_OPEN_MAPS; -	return NULL; -    } - -    /* The first entry should be the executable name. */ -    result = fgets(line, (int) buf_size, f); -    if (result == NULL) { -	fclose(f); -	g_free(line); -	if (error) -	    *error = GBR_INIT_ERROR_READ_MAPS; -	return NULL; -    } - -    /* Get rid of newline character. */ -    buf_size = strlen(line); -    if (buf_size <= 0) { -	/* Huh? An empty string? */ -	fclose(f); -	g_free(line); -	if (error) -	    *error = GBR_INIT_ERROR_INVALID_MAPS; -	return NULL; -    } -    if (line[buf_size - 1] == 10) -	line[buf_size - 1] = 0; - -    /* Extract the filename; it is always an absolute path. */ -    path = strchr(line, '/'); - -    /* Sanity check. */ -    if (strstr(line, " r-xp ") == NULL || path == NULL) { -	fclose(f); -	g_free(line); -	if (error) -	    *error = GBR_INIT_ERROR_INVALID_MAPS; -	return NULL; -    } - -    path = g_strdup(path); -    g_free(line); -    fclose(f); -    return path; -} - - -/** @internal - * Find the canonical filename of the executable which owns symbol. - * Returns a filename which must be freed, or NULL on error. - */ -static char *_br_find_exe_for_symbol(const void *symbol, -				     GbrInitError * error) -{ -#define SIZE PATH_MAX + 100 -    FILE *f; -    size_t address_string_len; -    char *address_string, line[SIZE], *found; - -    if (symbol == NULL) -	return (char *) NULL; - -    f = fopen("/proc/self/maps", "r"); -    if (f == NULL) -	return (char *) NULL; - -    address_string_len = 4; -    address_string = (char *) g_try_malloc(address_string_len); -    found = (char *) NULL; - -    while (!feof(f)) { -	char *start_addr, *end_addr, *end_addr_end, *file; -	void *start_addr_p, *end_addr_p; -	size_t len; - -	if (fgets(line, SIZE, f) == NULL) -	    break; - -	/* Sanity check. */ -	if (strstr(line, " r-xp ") == NULL || strchr(line, '/') == NULL) -	    continue; - -	/* Parse line. */ -	start_addr = line; -	end_addr = strchr(line, '-'); -	file = strchr(line, '/'); - -	/* More sanity check. */ -	if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-')) -	    continue; - -	end_addr[0] = '\0'; -	end_addr++; -	end_addr_end = strchr(end_addr, ' '); -	if (end_addr_end == NULL) -	    continue; - -	end_addr_end[0] = '\0'; -	len = strlen(file); -	if (len == 0) -	    continue; -	if (file[len - 1] == '\n') -	    file[len - 1] = '\0'; - -	/* Get rid of "(deleted)" from the filename. */ -	len = strlen(file); -	if (len > 10 && strcmp(file + len - 10, " (deleted)") == 0) -	    file[len - 10] = '\0'; - -	/* I don't know whether this can happen but better safe than sorry. */ -	len = strlen(start_addr); -	if (len != strlen(end_addr)) -	    continue; - - -	/* Transform the addresses into a string in the form of 0xdeadbeef, -	 * then transform that into a pointer. */ -	if (address_string_len < len + 3) { -	    address_string_len = len + 3; -	    address_string = -		(char *) g_try_realloc(address_string, address_string_len); -	} - -	memcpy(address_string, "0x", 2); -	memcpy(address_string + 2, start_addr, len); -	address_string[2 + len] = '\0'; -	sscanf(address_string, "%p", &start_addr_p); - -	memcpy(address_string, "0x", 2); -	memcpy(address_string + 2, end_addr, len); -	address_string[2 + len] = '\0'; -	sscanf(address_string, "%p", &end_addr_p); - - -	if (symbol >= start_addr_p && symbol < end_addr_p) { -	    found = file; -	    break; -	} -    } - -    g_free(address_string); -    fclose(f); - -    if (found == NULL) -	return (char *) NULL; -    else -	return g_strdup(found); -} - - -static gchar *exe = NULL; - -static void set_gerror(GError ** error, GbrInitError errcode); - - -/** 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 - *       gbr_init_lib() instead. - * - * @param error  If BinReloc failed to initialize, then the error report will - *               be stored in this variable. Set to NULL if you don't want an - *               error report. See the #GbrInitError for a list of error - *               codes. - * - * @returns TRUE on success, FALSE if BinReloc failed to initialize. - */ -gboolean gbr_init(GError ** error) -{ -    GbrInitError errcode = 0; - -    /* Locate the application's filename. */ -    exe = _br_find_exe(&errcode); -    if (exe != NULL) -	/* Success! */ -	return TRUE; -    else { -	/* Failed :-( */ -	set_gerror(error, errcode); -	return FALSE; -    } -} - - -/** 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. - * - * @returns TRUE on success, FALSE if a filename cannot be found. - */ -gboolean gbr_init_lib(GError ** error) -{ -    GbrInitError errcode = 0; - -    exe = _br_find_exe_for_symbol((const void *) "", &errcode); -    if (exe != NULL) -	/* Success! */ -	return TRUE; -    else { -	/* Failed :-( */ -	set_gerror(error, errcode); -	return exe != NULL; -    } -} - - -static void set_gerror(GError ** error, GbrInitError errcode) -{ -    gchar *error_message; - -    if (error == NULL) -	return; - -    switch (errcode) { -    case GBR_INIT_ERROR_NOMEM: -	error_message = "Cannot allocate memory."; -	break; -    case GBR_INIT_ERROR_OPEN_MAPS: -	error_message = "Unable to open /proc/self/maps for reading."; -	break; -    case GBR_INIT_ERROR_READ_MAPS: -	error_message = "Unable to read from /proc/self/maps."; -	break; -    case GBR_INIT_ERROR_INVALID_MAPS: -	error_message = "The file format of /proc/self/maps is invalid."; -	break; -    case GBR_INIT_ERROR_DISABLED: -	error_message = "Binary relocation support is disabled."; -	break; -    default: -	error_message = "Unknown error."; -	break; -    }; -    g_set_error(error, g_quark_from_static_string("GBinReloc"), -		errcode, "%s", error_message); -} - - -/** Find the canonical filename of the current application. - * - * @param 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 the initialization function failed, - *          then a copy of default_exe will be returned. If default_exe - *          is NULL, then NULL will be returned. - */ -gchar *gbr_find_exe(const gchar * default_exe) -{ -    if (exe == NULL) { -	/* BinReloc is not initialized. */ -	if (default_exe != NULL) -	    return g_strdup(default_exe); -	else -	    return NULL; -    } -    return g_strdup(exe); -} - - -/** Locate the directory in which the current application is installed. - * - * The prefix is generated by the following pseudo-code evaluation: - * \code - * dirname(exename) - * \endcode - * - * @param default_dir  A default directory which will used as fallback. - * @return 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. - */ -gchar *gbr_find_exe_dir(const gchar * default_dir) -{ -    if (exe == NULL) { -	/* BinReloc not initialized. */ -	if (default_dir != NULL) -	    return g_strdup(default_dir); -	else -	    return NULL; -    } - -    return g_path_get_dirname(exe); -} - - -/** Locate the prefix in which the current application is installed. - * - * The prefix is generated by the following pseudo-code evaluation: - * \code - * dirname(dirname(exename)) - * \endcode - * - * @param default_prefix  A default prefix which will used as fallback. - * @return 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. - */ -gchar *gbr_find_prefix(const gchar * default_prefix) -{ -    gchar *dir1, *dir2; - -    if (exe == NULL) { -	/* BinReloc not initialized. */ -	if (default_prefix != NULL) -	    return g_strdup(default_prefix); -	else -	    return NULL; -    } - -    dir1 = g_path_get_dirname(exe); -    dir2 = g_path_get_dirname(dir1); -    g_free(dir1); -    return dir2; -} - - -/** Locate the application's binary folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/bin" - * \endcode - * - * @param default_bin_dir  A default path which will used as fallback. - * @return 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. - */ -gchar *gbr_find_bin_dir(const gchar * default_bin_dir) -{ -    gchar *prefix, *dir; - -    prefix = gbr_find_prefix(NULL); -    if (prefix == NULL) { -	/* BinReloc not initialized. */ -	if (default_bin_dir != NULL) -	    return g_strdup(default_bin_dir); -	else -	    return NULL; -    } - -    dir = g_build_filename(prefix, "bin", NULL); -    g_free(prefix); -    return dir; -} - - -/** Locate the application's superuser binary folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/sbin" - * \endcode - * - * @param default_sbin_dir  A default path which will used as fallback. - * @return 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. - */ -gchar *gbr_find_sbin_dir(const gchar * default_sbin_dir) -{ -    gchar *prefix, *dir; - -    prefix = gbr_find_prefix(NULL); -    if (prefix == NULL) { -	/* BinReloc not initialized. */ -	if (default_sbin_dir != NULL) -	    return g_strdup(default_sbin_dir); -	else -	    return NULL; -    } - -    dir = g_build_filename(prefix, "sbin", NULL); -    g_free(prefix); -    return dir; -} - - -/** Locate the application's data folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/share" - * \endcode - * - * @param default_data_dir  A default path which will used as fallback. - * @return 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. - */ -gchar *gbr_find_data_dir(const gchar * default_data_dir) -{ -    gchar *prefix, *dir; - -    prefix = gbr_find_prefix(NULL); -    if (prefix == NULL) { -	/* BinReloc not initialized. */ -	if (default_data_dir != NULL) -	    return g_strdup(default_data_dir); -	else -	    return NULL; -    } - -    dir = g_build_filename(prefix, "share", NULL); -    g_free(prefix); -    return dir; -} - - -/** Locate the application's localization folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/share/locale" - * \endcode - * - * @param default_locale_dir  A default path which will used as fallback. - * @return 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. - */ -gchar *gbr_find_locale_dir(const gchar * default_locale_dir) -{ -    gchar *data_dir, *dir; - -    data_dir = gbr_find_data_dir(NULL); -    if (data_dir == NULL) { -	/* BinReloc not initialized. */ -	if (default_locale_dir != NULL) -	    return g_strdup(default_locale_dir); -	else -	    return NULL; -    } - -    dir = g_build_filename(data_dir, "locale", NULL); -    g_free(data_dir); -    return dir; -} - - -/** Locate the application's library folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/lib" - * \endcode - * - * @param default_lib_dir  A default path which will used as fallback. - * @return 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. - */ -gchar *gbr_find_lib_dir(const gchar * default_lib_dir) -{ -    gchar *prefix, *dir; - -    prefix = gbr_find_prefix(NULL); -    if (prefix == NULL) { -	/* BinReloc not initialized. */ -	if (default_lib_dir != NULL) -	    return g_strdup(default_lib_dir); -	else -	    return NULL; -    } - -#ifdef ARCH_x86_64 -    dir = g_build_filename(prefix, "lib64", NULL); -#else -    dir = g_build_filename(prefix, "lib", NULL); -#endif - -    g_free(prefix); -    return dir; -} - - -/** Locate the application's libexec folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/libexec" - * \endcode - * - * @param default_libexec_dir  A default path which will used as fallback. - * @return 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. - */ -gchar *gbr_find_libexec_dir(const gchar * default_libexec_dir) -{ -    gchar *prefix, *dir; - -    prefix = gbr_find_prefix(NULL); -    if (prefix == NULL) { -	/* BinReloc not initialized. */ -	if (default_libexec_dir != NULL) -	    return g_strdup(default_libexec_dir); -	else -	    return NULL; -    } - -    dir = g_build_filename(prefix, "libexec", NULL); -    g_free(prefix); -    return dir; -} - - -/** Locate the application's configuration files folder. - * - * The path is generated by the following pseudo-code evaluation: - * \code - * prefix + "/etc" - * \endcode - * - * @param default_etc_dir  A default path which will used as fallback. - * @return 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. - */ -gchar *gbr_find_etc_dir(const gchar * default_etc_dir) -{ -    gchar *prefix, *dir; - -    prefix = gbr_find_prefix(NULL); -    if (prefix == NULL) { -	/* BinReloc not initialized. */ -	if (default_etc_dir != NULL) -	    return g_strdup(default_etc_dir); -	else -	    return NULL; -    } - -    dir = g_build_filename(prefix, "etc", NULL); -    g_free(prefix); -    return dir; -} - - -G_END_DECLS -#endif				/* __BINRELOC_C__ */  | 
