~ubuntu-branches/ubuntu/hardy/codeblocks/hardy-backports

« back to all changes in this revision

Viewing changes to src/src/prefix.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Casadevall
  • Date: 2008-07-17 04:39:23 UTC
  • Revision ID: james.westby@ubuntu.com-20080717043923-gmsy5cwkdjswghkm
Tags: upstream-8.02
ImportĀ upstreamĀ versionĀ 8.02

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
 
3
 * http://www.gnu.org/licenses/gpl-3.0.html
 
4
 *
 
5
 * $Revision: 4909 $
 
6
 * $Id: prefix.cpp 4909 2008-02-27 13:15:26Z mortenmacfly $
 
7
 * $HeadURL: svn://svn.berlios.de/codeblocks/tags/8.02/src/src/prefix.cpp $
 
8
 */
 
9
 
 
10
/*
 
11
 * BinReloc - a library for creating relocatable executables
 
12
 * Written by: Mike Hearn <mike@theoretic.com>
 
13
 *             Hongli Lai <h.lai@chello.nl>
 
14
 * http://autopackage.org/
 
15
 * 
 
16
 * This source code is public domain. You can relicense this code
 
17
 * under whatever license you want.
 
18
 *
 
19
 * NOTE: if you're using C++ and are getting "undefined reference
 
20
 * to br_*", try renaming prefix.c to prefix.cpp
 
21
 */
 
22
 
 
23
/* WARNING, BEFORE YOU MODIFY PREFIX.C:
 
24
 *
 
25
 * If you make changes to any of the functions in prefix.c, you MUST
 
26
 * change the BR_NAMESPACE macro (in prefix.h).
 
27
 * This way you can avoid symbol table conflicts with other libraries
 
28
 * that also happen to use BinReloc.
 
29
 *
 
30
 * Example:
 
31
 * #define BR_NAMESPACE(funcName) foobar_ ## funcName
 
32
 * --> expands br_locate to foobar_br_locate
 
33
 */
 
34
 
 
35
#ifndef _PREFIX_C_
 
36
#define _PREFIX_C_
 
37
 
 
38
#ifdef HAVE_CONFIG_H
 
39
        #include "config.h"
 
40
#endif
 
41
 
 
42
#ifndef BR_PTHREADS
 
43
        /* Change 1 to 0 if you don't want pthread support */
 
44
        #define BR_PTHREADS 1
 
45
#endif /* BR_PTHREADS */
 
46
 
 
47
#include <stdlib.h>
 
48
#include <stdio.h>
 
49
#include <limits.h>
 
50
#include <string.h>
 
51
#include "prefix.h"
 
52
 
 
53
#ifdef __cplusplus
 
54
extern "C" {
 
55
#endif /* __cplusplus */
 
56
 
 
57
 
 
58
#undef NULL
 
59
#define NULL ((void *) 0)
 
60
 
 
61
#ifdef __GNUC__
 
62
        #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
 
63
#else
 
64
        #define br_return_val_if_fail(expr,val) if (!(expr)) return val
 
65
#endif /* __GNUC__ */
 
66
 
 
67
 
 
68
#ifdef ENABLE_BINRELOC
 
69
#include <sys/types.h>
 
70
#include <sys/stat.h>
 
71
#include <sys/param.h>
 
72
#include <unistd.h>
 
73
 
 
74
 
 
75
/**
 
76
 * br_locate:
 
77
 * symbol: A symbol that belongs to the app/library you want to locate.
 
78
 * Returns: A newly allocated string containing the full path of the
 
79
 *          app/library that func belongs to, or NULL on error. This
 
80
 *          string should be freed when not when no longer needed.
 
81
 *
 
82
 * Finds out to which application or library symbol belongs, then locate
 
83
 * the full path of that application or library.
 
84
 * Note that symbol cannot be a pointer to a function. That will not work.
 
85
 *
 
86
 * Example:
 
87
 * --> main.c
 
88
 * #include "prefix.h"
 
89
 * #include "libfoo.h"
 
90
 *
 
91
 * int main (int argc, char *argv[]) {
 
92
 *      printf ("Full path of this app: %s\n", br_locate (&argc));
 
93
 *      libfoo_start ();
 
94
 *      return 0;
 
95
 * }
 
96
 *
 
97
 * --> libfoo.c starts here
 
98
 * #include "prefix.h"
 
99
 *
 
100
 * void libfoo_start () {
 
101
 *      --> "" is a symbol that belongs to libfoo (because it's called
 
102
 *      --> from libfoo_start()); that's why this works.
 
103
 *      printf ("libfoo is located in: %s\n", br_locate (""));
 
104
 * }
 
105
 */
 
106
char *
 
107
br_locate (void *symbol)
 
108
{
 
109
        char line[5000];
 
110
        FILE *f;
 
111
        char *path;
 
112
 
 
113
        br_return_val_if_fail (symbol != NULL, (char*)NULL);
 
114
 
 
115
        f = fopen ("/proc/self/maps", "r");
 
116
        if (!f)
 
117
                return (char*)NULL;
 
118
 
 
119
        while (!feof (f))
 
120
        {
 
121
                unsigned long start, end;
 
122
 
 
123
                if (!fgets (line, sizeof (line), f))
 
124
                        continue;
 
125
                if (!strstr (line, " r-xp ") || !strchr (line, '/'))
 
126
                        continue;
 
127
 
 
128
                sscanf (line, "%lx-%lx ", &start, &end);
 
129
                if (symbol >= (void *) start && symbol < (void *) end)
 
130
                {
 
131
                        char *tmp;
 
132
                        size_t len;
 
133
 
 
134
                        /* Extract the filename; it is always an absolute path */
 
135
                        path = strchr (line, '/');
 
136
 
 
137
                        /* Get rid of the newline */
 
138
                        tmp = strrchr (path, '\n');
 
139
                        if (tmp) *tmp = 0;
 
140
 
 
141
                        /* Get rid of "(deleted)" */
 
142
                        len = strlen (path);
 
143
                        if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
 
144
                        {
 
145
                                tmp = path + len - 10;
 
146
                                *tmp = 0;
 
147
                        }
 
148
 
 
149
                        fclose(f);
 
150
                        return strdup (path);
 
151
                }
 
152
        }
 
153
 
 
154
        fclose (f);
 
155
        return (char*)NULL;
 
156
}
 
157
 
 
158
 
 
159
/**
 
160
 * br_locate_prefix:
 
161
 * symbol: A symbol that belongs to the app/library you want to locate.
 
162
 * Returns: A prefix. This string should be freed when no longer needed.
 
163
 *
 
164
 * Locates the full path of the app/library that symbol belongs to, and return
 
165
 * the prefix of that path, or NULL on error.
 
166
 * Note that symbol cannot be a pointer to a function. That will not work.
 
167
 *
 
168
 * Example:
 
169
 * --> This application is located in /usr/bin/foo
 
170
 * br_locate_prefix (&argc);   --> returns: "/usr"
 
171
 */
 
172
char *
 
173
br_locate_prefix (void *symbol)
 
174
{
 
175
        char *path, *prefix;
 
176
 
 
177
        br_return_val_if_fail (symbol != NULL, (char*)NULL);
 
178
 
 
179
        path = br_locate (symbol);
 
180
        if (!path) return (char*)NULL;
 
181
 
 
182
        prefix = br_extract_prefix (path);
 
183
        free (path);
 
184
        return prefix;
 
185
}
 
186
 
 
187
 
 
188
/**
 
189
 * br_prepend_prefix:
 
190
 * symbol: A symbol that belongs to the app/library you want to locate.
 
191
 * path: The path that you want to prepend the prefix to.
 
192
 * Returns: The new path, or NULL on error. This string should be freed when no
 
193
 *          longer needed.
 
194
 *
 
195
 * Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path.
 
196
 * Note that symbol cannot be a pointer to a function. That will not work.
 
197
 *
 
198
 * Example:
 
199
 * --> The application is /usr/bin/foo
 
200
 * br_prepend_prefix (&argc, "/share/foo/data.png");   --> Returns "/usr/share/foo/data.png"
 
201
 */
 
202
char *
 
203
br_prepend_prefix (void *symbol, char *path)
 
204
{
 
205
        char *tmp, *newpath;
 
206
 
 
207
        br_return_val_if_fail (symbol != NULL, (char*)NULL);
 
208
        br_return_val_if_fail (path != NULL, (char*)NULL);
 
209
 
 
210
        tmp = br_locate_prefix (symbol);
 
211
        if (!tmp) return (char*)NULL;
 
212
 
 
213
        if (strcmp (tmp, "/") == 0)
 
214
                newpath = strdup (path);
 
215
        else
 
216
                newpath = br_strcat (tmp, path);
 
217
 
 
218
        /* Get rid of compiler warning ("br_prepend_prefix never used") */
 
219
        if (0) br_prepend_prefix (NULL,  (char*)NULL);
 
220
 
 
221
        free (tmp);
 
222
        return newpath;
 
223
}
 
224
 
 
225
#endif /* ENABLE_BINRELOC */
 
226
 
 
227
 
 
228
/* Pthread stuff for thread safetiness */
 
229
#if BR_PTHREADS
 
230
 
 
231
#include <pthread.h>
 
232
 
 
233
static pthread_key_t br_thread_key;
 
234
#ifdef __FreeBSD__
 
235
static pthread_once_t br_thread_key_once = {0, (pthread_mutex_t)NULL};//PTHREAD_ONCE_INIT;
 
236
#else
 
237
static pthread_once_t br_thread_key_once = PTHREAD_ONCE_INIT;
 
238
#endif
 
239
 
 
240
static void
 
241
br_thread_local_store_fini ()
 
242
{
 
243
        char *specific;
 
244
 
 
245
        specific = (char *) pthread_getspecific (br_thread_key);
 
246
        if (specific)
 
247
        {
 
248
                free (specific);
 
249
                pthread_setspecific (br_thread_key, NULL);
 
250
        }
 
251
        pthread_key_delete (br_thread_key);
 
252
        br_thread_key = 0;
 
253
}
 
254
 
 
255
 
 
256
static void
 
257
br_str_free (void *str)
 
258
{
 
259
        if (str)
 
260
                free (str);
 
261
}
 
262
 
 
263
 
 
264
static void
 
265
br_thread_local_store_init ()
 
266
{
 
267
        if (pthread_key_create (&br_thread_key, br_str_free) == 0)
 
268
                atexit (br_thread_local_store_fini);
 
269
}
 
270
 
 
271
#else /* BR_PTHREADS */
 
272
 
 
273
static char *br_last_value = (char *) NULL;
 
274
 
 
275
static void
 
276
br_free_last_value ()
 
277
{
 
278
        if (br_last_value)
 
279
                free (br_last_value);
 
280
}
 
281
 
 
282
#endif /* BR_PTHREADS */
 
283
 
 
284
 
 
285
/**
 
286
 * br_thread_local_store:
 
287
 * str: A dynamically allocated string.
 
288
 * Returns: str. This return value must not be freed.
 
289
 *
 
290
 * Store str in a thread-local variable and return str. The next
 
291
 * you run this function, that variable is freed too.
 
292
 * This function is created so you don't have to worry about freeing
 
293
 * strings.
 
294
 *
 
295
 * Example:
 
296
 * char *foo;
 
297
 * foo = thread_local_store (strdup ("hello")); --> foo == "hello"
 
298
 * foo = thread_local_store (strdup ("world")); --> foo == "world"; "hello" is now freed.
 
299
 */
 
300
const char *
 
301
br_thread_local_store (char *str)
 
302
{
 
303
        #if BR_PTHREADS
 
304
                char *specific;
 
305
 
 
306
                pthread_once (&br_thread_key_once, br_thread_local_store_init);
 
307
 
 
308
                specific = (char *) pthread_getspecific (br_thread_key);
 
309
                br_str_free (specific);
 
310
                pthread_setspecific (br_thread_key, str);
 
311
 
 
312
        #else /* BR_PTHREADS */
 
313
                static int initialized = 0;
 
314
 
 
315
                if (!initialized)
 
316
                {
 
317
                        atexit (br_free_last_value);
 
318
                        initialized = 1;
 
319
                }
 
320
 
 
321
                if (br_last_value)
 
322
                        free (br_last_value);
 
323
                br_last_value = str;
 
324
        #endif /* BR_PTHREADS */
 
325
 
 
326
        return (const char *) str;
 
327
}
 
328
 
 
329
 
 
330
/**
 
331
 * br_strcat:
 
332
 * str1: A string.
 
333
 * str2: Another string.
 
334
 * Returns: A newly-allocated string. This string should be freed when no longer needed.
 
335
 *
 
336
 * Concatenate str1 and str2 to a newly allocated string.
 
337
 */
 
338
char *
 
339
br_strcat (const char *str1, const char *str2)
 
340
{
 
341
        char *result;
 
342
        size_t len1, len2;
 
343
 
 
344
        if (!str1) str1 = "";
 
345
        if (!str2) str2 = "";
 
346
 
 
347
        len1 = strlen (str1);
 
348
        len2 = strlen (str2);
 
349
 
 
350
        result = (char *) malloc (len1 + len2 + 1);
 
351
        memcpy (result, str1, len1);
 
352
        memcpy (result + len1, str2, len2);
 
353
        result[len1 + len2] = '\0';
 
354
 
 
355
        return result;
 
356
}
 
357
 
 
358
 
 
359
/* Emulates glibc's strndup() */
 
360
static char *
 
361
br_strndup (char *str, size_t size)
 
362
{
 
363
        char *result = (char *) NULL;
 
364
        size_t len;
 
365
 
 
366
        br_return_val_if_fail (str != (char *) NULL, (char *) NULL);
 
367
 
 
368
        len = strlen (str);
 
369
        if (!len) return strdup ("");
 
370
        if (size > len) size = len;
 
371
 
 
372
        result = (char *) calloc (sizeof (char), len + 1);
 
373
        memcpy (result, str, size);
 
374
        return result;
 
375
}
 
376
 
 
377
 
 
378
/**
 
379
 * br_extract_dir:
 
380
 * path: A path.
 
381
 * Returns: A directory name. This string should be freed when no longer needed.
 
382
 *
 
383
 * Extracts the directory component of path. Similar to g_dirname() or the dirname
 
384
 * commandline application.
 
385
 *
 
386
 * Example:
 
387
 * br_extract_dir ("/usr/local/foobar");  --> Returns: "/usr/local"
 
388
 */
 
389
char *
 
390
br_extract_dir (const char *path)
 
391
{
 
392
        char *end, *result;
 
393
 
 
394
        br_return_val_if_fail (path != (char *) NULL, (char *) NULL);
 
395
 
 
396
        end = strrchr (path, '/');
 
397
        if (!end) return strdup (".");
 
398
 
 
399
        while (end > path && *end == '/')
 
400
                end--;
 
401
        result = br_strndup ((char *) path, end - path + 1);
 
402
        if (!*result)
 
403
        {
 
404
                free (result);
 
405
                return strdup ("/");
 
406
        } else
 
407
                return result;
 
408
}
 
409
 
 
410
 
 
411
/**
 
412
 * br_extract_prefix:
 
413
 * path: The full path of an executable or library.
 
414
 * Returns: The prefix, or NULL on error. This string should be freed when no longer needed.
 
415
 *
 
416
 * Extracts the prefix from path. This function assumes that your executable
 
417
 * or library is installed in an LSB-compatible directory structure.
 
418
 *
 
419
 * Example:
 
420
 * br_extract_prefix ("/usr/bin/gnome-panel");       --> Returns "/usr"
 
421
 * br_extract_prefix ("/usr/local/lib/libfoo.so");   --> Returns "/usr/local"
 
422
 * br_extract_prefix ("/usr/local/libfoo.so");       --> Returns "/usr"
 
423
 */
 
424
char *
 
425
br_extract_prefix (const char *path)
 
426
{
 
427
        char *end, *tmp, *result;
 
428
 
 
429
        br_return_val_if_fail (path != (char *) NULL, (char *) NULL);
 
430
 
 
431
        if (!*path) return strdup ("/");
 
432
        end = strrchr (path, '/');
 
433
        if (!end) return strdup (path);
 
434
 
 
435
        tmp = br_strndup ((char *) path, end - path);
 
436
        if (!*tmp)
 
437
        {
 
438
                free (tmp);
 
439
                return strdup ("/");
 
440
        }
 
441
        end = strrchr (tmp, '/');
 
442
        if (!end) return tmp;
 
443
 
 
444
        result = br_strndup (tmp, end - tmp);
 
445
        free (tmp);
 
446
 
 
447
        if (!*result)
 
448
        {
 
449
                free (result);
 
450
                result = strdup ("/");
 
451
        }
 
452
 
 
453
        return result;
 
454
}
 
455
 
 
456
 
 
457
#ifdef __cplusplus
 
458
}
 
459
#endif /* __cplusplus */
 
460
 
 
461
#endif /* _PREFIX_C */