logo

Inkscape

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files

prefix.cpp

Go to the documentation of this file.
00001 /*
00002  * BinReloc - a library for creating relocatable executables
00003  * Written by: Mike Hearn <mike@theoretic.com>
00004  *             Hongli Lai <h.lai@chello.nl>
00005  * http://autopackage.org/
00006  *
00007  * This source code is public domain. You can relicense this code
00008  * under whatever license you want.
00009  *
00010  * NOTE: if you're using C++ and are getting "undefined reference
00011  * to br_*", try renaming prefix.c to prefix.cpp
00012  */
00013 
00014 /* WARNING, BEFORE YOU MODIFY PREFIX.C:
00015  *
00016  * If you make changes to any of the functions in prefix.c, you MUST
00017  * change the BR_NAMESPACE macro (in prefix.h).
00018  * This way you can avoid symbol table conflicts with other libraries
00019  * that also happen to use BinReloc.
00020  *
00021  * Example:
00022  * #define BR_NAMESPACE(funcName) foobar_ ## funcName
00023  * --> expands br_locate to foobar_br_locate
00024  */
00025 
00026 #ifndef _PREFIX_C_
00027 #define _PREFIX_C_
00028 
00029 #ifdef HAVE_CONFIG_H
00030 # include "config.h"
00031 #endif
00032 
00033 
00034 /* PLEASE NOTE:  We use GThreads now for portability */
00035 /* @see http://developer.gnome.org/doc/API/2.0/glib/glib-Threads.html */
00036 #ifndef BR_THREADS
00037     /* Change 1 to 0 if you don't want thread support */
00038     #define BR_THREADS 1
00039     #include <glib.h> //for GThreads
00040 #endif /* BR_THREADS */
00041 
00042 #include <cstdlib>
00043 #include <cstdio>
00044 #include <cstring>
00045 #include <limits.h>
00046 #include "prefix.h"
00047 
00048 
00049 #ifdef __cplusplus
00050 extern "C" {
00051 #endif /* __cplusplus */
00052 
00053 
00054 #undef NULL
00055 #define NULL ((void *) 0)
00056 
00057 #ifdef __GNUC__
00058     #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
00059 #else
00060     #define br_return_val_if_fail(expr,val) if (!(expr)) return val
00061 #endif /* __GNUC__ */
00062 
00063 
00064 #ifdef ENABLE_BINRELOC
00065 
00066 #include <sys/types.h>
00067 #include <sys/stat.h>
00068 #include <sys/param.h>
00069 #include <unistd.h>
00070 
00102 char *
00103 br_locate (void *symbol)
00104 {
00105     char line[5000];
00106     FILE *f;
00107     char *path;
00108 
00109     br_return_val_if_fail (symbol != NULL, NULL);
00110 
00111     f = fopen ("/proc/self/maps", "r");
00112     if (!f)
00113         return NULL;
00114 
00115     while (!feof (f))
00116     {
00117         unsigned long start, end;
00118 
00119         if (!fgets (line, sizeof (line), f))
00120             continue;
00121         if (!strstr (line, " r-xp ") || !strchr (line, '/'))
00122             continue;
00123 
00124         sscanf (line, "%lx-%lx ", &start, &end);
00125         if (symbol >= (void *) start && symbol < (void *) end)
00126         {
00127             char *tmp;
00128             size_t len;
00129 
00130             /* Extract the filename; it is always an absolute path */
00131             path = strchr (line, '/');
00132 
00133             /* Get rid of the newline */
00134             tmp = strrchr (path, '\n');
00135             if (tmp) *tmp = 0;
00136 
00137             /* Get rid of "(deleted)" */
00138             len = strlen (path);
00139             if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
00140             {
00141                 tmp = path + len - 10;
00142                 *tmp = 0;
00143             }
00144 
00145             fclose(f);
00146             return strdup (path);
00147         }
00148     }
00149 
00150     fclose (f);
00151     return NULL;
00152 }
00153 
00154 
00168 char *
00169 br_locate_prefix (void *symbol)
00170 {
00171     char *path, *prefix;
00172 
00173     br_return_val_if_fail (symbol != NULL, NULL);
00174 
00175     path = br_locate (symbol);
00176     if (!path) return NULL;
00177 
00178     prefix = br_extract_prefix (path);
00179     free (path);
00180     return prefix;
00181 }
00182 
00183 
00198 char *
00199 br_prepend_prefix (void *symbol, char *path)
00200 {
00201     char *tmp, *newpath;
00202 
00203     br_return_val_if_fail (symbol != NULL, NULL);
00204     br_return_val_if_fail (path != NULL, NULL);
00205 
00206     tmp = br_locate_prefix (symbol);
00207     if (!tmp) return NULL;
00208 
00209     if (strcmp (tmp, "/") == 0)
00210         newpath = strdup (path);
00211     else
00212         newpath = br_strcat (tmp, path);
00213 
00214     /* Get rid of compiler warning ("br_prepend_prefix never used") */
00215     if (0) br_prepend_prefix (NULL, NULL);
00216 
00217     free (tmp);
00218     return newpath;
00219 }
00220 
00221 #endif /* ENABLE_BINRELOC */
00222 
00223 
00224 /* Thread stuff for thread safetiness */
00225 #if BR_THREADS
00226 
00227 GPrivate* br_thread_key = (GPrivate *)NULL;
00228 
00229 /*
00230    We do not need local store init() or fini(), because
00231    g_private_new (g_free) will take care of all of that
00232    for us.  Isn't GLib wonderful?
00233 */
00234 
00235 #else /* !BR_THREADS */
00236 
00237 static char *br_last_value = (char*)NULL;
00238 
00239 static void
00240 br_free_last_value ()
00241 {
00242     if (br_last_value)
00243         free (br_last_value);
00244 }
00245 
00246 #endif /* BR_THREADS */
00247 
00248 
00264 const char *
00265 br_thread_local_store (char *str)
00266 {
00267     #if BR_THREADS
00268                 if (!g_thread_supported ())
00269                     {
00270                     g_thread_init ((GThreadFunctions *)NULL);
00271                     br_thread_key = g_private_new (g_free);
00272                     }
00273 
00274         char *specific = (char *) g_private_get (br_thread_key);
00275         if (specific)
00276                     free (specific);
00277                 g_private_set (br_thread_key, str);
00278 
00279     #else /* !BR_THREADS */
00280         static int initialized = 0;
00281 
00282         if (!initialized)
00283         {
00284             atexit (br_free_last_value);
00285             initialized = 1;
00286         }
00287 
00288         if (br_last_value)
00289             free (br_last_value);
00290         br_last_value = str;
00291     #endif /* BR_THREADS */
00292 
00293     return (const char *) str;
00294 }
00295 
00296 
00305 char *
00306 br_strcat (const char *str1, const char *str2)
00307 {
00308     char *result;
00309     size_t len1, len2;
00310 
00311     if (!str1) str1 = "";
00312     if (!str2) str2 = "";
00313 
00314     len1 = strlen (str1);
00315     len2 = strlen (str2);
00316 
00317     result = (char *) malloc (len1 + len2 + 1);
00318     memcpy (result, str1, len1);
00319     memcpy (result + len1, str2, len2);
00320     result[len1 + len2] = '\0';
00321 
00322     return result;
00323 }
00324 
00325 
00326 /* Emulates glibc's strndup() */
00327 static char *
00328 br_strndup (char *str, size_t size)
00329 {
00330     char *result = (char*)NULL;
00331     size_t len;
00332 
00333     br_return_val_if_fail (str != (char*)NULL, (char*)NULL);
00334 
00335     len = strlen (str);
00336     if (!len) return strdup ("");
00337     if (size > len) size = len;
00338 
00339     result = (char *) calloc (sizeof (char), len + 1);
00340     memcpy (result, str, size);
00341     return result;
00342 }
00343 
00344 
00356 char *
00357 br_extract_dir (const char *path)
00358 {
00359     char *end, *result;
00360 
00361     br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
00362 
00363     end = strrchr (path, '/');
00364     if (!end) return strdup (".");
00365 
00366     while (end > path && *end == '/')
00367         end--;
00368     result = br_strndup ((char *) path, end - path + 1);
00369     if (!*result)
00370     {
00371         free (result);
00372         return strdup ("/");
00373     } else
00374         return result;
00375 }
00376 
00377 
00391 char *
00392 br_extract_prefix (const char *path)
00393 {
00394     char *end, *tmp, *result;
00395 
00396     br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
00397 
00398     if (!*path) return strdup ("/");
00399     end = strrchr (path, '/');
00400     if (!end) return strdup (path);
00401 
00402     tmp = br_strndup ((char *) path, end - path);
00403     if (!*tmp)
00404     {
00405         free (tmp);
00406         return strdup ("/");
00407     }
00408     end = strrchr (tmp, '/');
00409     if (!end) return tmp;
00410 
00411     result = br_strndup (tmp, end - tmp);
00412     free (tmp);
00413 
00414     if (!*result)
00415     {
00416         free (result);
00417         result = strdup ("/");
00418     }
00419 
00420     return result;
00421 }
00422 
00423 
00424 #ifdef __cplusplus
00425 }
00426 #endif /* __cplusplus */
00427 
00428 
00429 
00430 #ifdef __WIN32__
00431 
00437 #include <windows.h>
00438 #include <glibmm/ustring.h>
00439 
00443 static Glib::ustring win32_getExePath()
00444 {
00445     char exeName[MAX_PATH+1];
00446     GetModuleFileName(NULL, exeName, MAX_PATH);
00447     char *slashPos = strrchr(exeName, '\\');
00448     if (slashPos)
00449         *slashPos = '\0';
00450     Glib::ustring s = exeName;
00451     return s;
00452 }
00453 
00454 
00459 static Glib::ustring win32_getDataDir()
00460 {
00461     Glib::ustring dir = win32_getExePath();
00462     if (INKSCAPE_DATADIR  && *INKSCAPE_DATADIR &&
00463         strcmp(INKSCAPE_DATADIR, ".") != 0)
00464         {
00465         dir += "\\";
00466         dir += INKSCAPE_DATADIR;
00467         }
00468     return dir;
00469 }
00470 
00471 static Glib::ustring win32_getResourcePath(const Glib::ustring &childPath)
00472 {
00473     Glib::ustring dir = win32_getDataDir();
00474     if (childPath.size() > 0)
00475         {
00476         dir += "\\";
00477         dir += childPath;
00478         }
00479     return dir;
00480 }
00481 
00482 
00486 char *win32_relative_path(const char *childPath)
00487 {
00488     static char *returnPath = NULL;
00489     if (!childPath)
00490         childPath = "";
00491     Glib::ustring resourcePath = win32_getResourcePath(childPath);
00492     if (returnPath)
00493         free(returnPath);
00494     returnPath = strdup(resourcePath.c_str());
00495     return returnPath;
00496 }
00497 #endif /* __WIN32__ */
00498 
00499 
00500 
00501 
00502 #endif /* _PREFIX_C */