~ubuntu-branches/ubuntu/raring/geany/raring-proposed

« back to all changes in this revision

Viewing changes to src/prefix.c

  • Committer: Bazaar Package Importer
  • Author(s): Damián Viano
  • Date: 2008-05-02 11:37:45 UTC
  • mto: (3.1.1 lenny) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20080502113745-7q62rqhl2ku02ptu
Import upstream version 0.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * BinReloc - a library for creating relocatable executables
 
3
 * Written by: Mike Hearn <mike@theoretic.com>
 
4
 *             Hongli Lai <h.lai@chello.nl>
 
5
 * http://autopackage.org/
 
6
 *
 
7
 * This source code is public domain. You can relicense this code
 
8
 * under whatever license you want.
 
9
 *
 
10
 * NOTE: if you're using C++ and are getting "undefined reference
 
11
 * to br_*", try renaming prefix.c to prefix.cpp
 
12
 */
 
13
 
 
14
 
 
15
#ifdef HAVE_CONFIG_H
 
16
# include "config.h"
 
17
#endif
 
18
 
 
19
 
 
20
/*
 
21
 * enrico - all the code below is only compiled and used if ENABLE_BINRELOC is set in config.h,
 
22
 *          this only happens if configure option --enable-binreloc was used
 
23
 */
 
24
#ifdef ENABLE_BINRELOC
 
25
 
 
26
 
 
27
 
 
28
#include <stdlib.h>
 
29
#include <stdio.h>
 
30
#include <limits.h>
 
31
#include <string.h>
 
32
#include <glib.h>
 
33
#include "prefix.h"
 
34
 
 
35
 
 
36
#undef NULL
 
37
#define NULL ((void *) 0)
 
38
 
 
39
#ifdef __GNUC__
 
40
        #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
 
41
#else
 
42
        #define br_return_val_if_fail(expr,val) if (!(expr)) return val
 
43
#endif /* __GNUC__ */
 
44
 
 
45
 
 
46
#include <sys/types.h>
 
47
#include <sys/stat.h>
 
48
#include <sys/param.h>
 
49
#include <unistd.h>
 
50
 
 
51
 
 
52
static char *br_last_value = (char*)NULL;
 
53
 
 
54
 
 
55
static void
 
56
br_free_last_value ()
 
57
{
 
58
    if (br_last_value)
 
59
        free (br_last_value);
 
60
}
 
61
 
 
62
/**
 
63
 * br_thread_local_store:
 
64
 * str: A dynamically allocated string.
 
65
 * Returns: str. This return value must not be freed.
 
66
 *
 
67
 * Store str in a thread-local variable and return str. The next
 
68
 * you run this function, that variable is freed too.
 
69
 * This function is created so you don't have to worry about freeing
 
70
 * strings.
 
71
 *
 
72
 * Example:
 
73
 * char *foo;
 
74
 * foo = thread_local_store (strdup ("hello")); --> foo == "hello"
 
75
 * foo = thread_local_store (strdup ("world")); --> foo == "world"; "hello" is now freed.
 
76
 */
 
77
const char *
 
78
br_thread_local_store (char *str)
 
79
{
 
80
        static int initialized = 0;
 
81
 
 
82
 
 
83
        if (!initialized)
 
84
        {
 
85
                atexit (br_free_last_value);
 
86
                initialized = 1;
 
87
        }
 
88
 
 
89
        if (br_last_value)
 
90
                free (br_last_value);
 
91
        br_last_value = str;
 
92
 
 
93
        return (const char *) str;
 
94
}
 
95
 
 
96
 
 
97
/**
 
98
 * br_locate:
 
99
 * symbol: A symbol that belongs to the app/library you want to locate.
 
100
 * Returns: A newly allocated string containing the full path of the
 
101
 *          app/library that func belongs to, or NULL on error. This
 
102
 *          string should be freed when not when no longer needed.
 
103
 *
 
104
 * Finds out to which application or library symbol belongs, then locate
 
105
 * the full path of that application or library.
 
106
 * Note that symbol cannot be a pointer to a function. That will not work.
 
107
 *
 
108
 * Example:
 
109
 * --> main.c
 
110
 * #include "prefix.h"
 
111
 * #include "libfoo.h"
 
112
 *
 
113
 * int main (int argc, char *argv[]) {
 
114
 *      printf ("Full path of this app: %s\n", br_locate (&argc));
 
115
 *      libfoo_start ();
 
116
 *      return 0;
 
117
 * }
 
118
 *
 
119
 * --> libfoo.c starts here
 
120
 * #include "prefix.h"
 
121
 *
 
122
 * void libfoo_start () {
 
123
 *      --> "" is a symbol that belongs to libfoo (because it's called
 
124
 *      --> from libfoo_start()); that's why this works.
 
125
 *      printf ("libfoo is located in: %s\n", br_locate (""));
 
126
 * }
 
127
 */
 
128
char *
 
129
br_locate (void *symbol)
 
130
{
 
131
        char line[5000];
 
132
        FILE *f;
 
133
        char *path;
 
134
 
 
135
        br_return_val_if_fail (symbol != NULL, NULL);
 
136
 
 
137
        f = fopen ("/proc/self/maps", "r");
 
138
        if (!f)
 
139
                return NULL;
 
140
 
 
141
        while (!feof (f))
 
142
        {
 
143
                unsigned long start, end;
 
144
 
 
145
                if (!fgets (line, sizeof (line), f))
 
146
                        continue;
 
147
                if (!strstr (line, " r-xp ") || !strchr (line, '/'))
 
148
                        continue;
 
149
 
 
150
                sscanf (line, "%lx-%lx ", &start, &end);
 
151
                if (symbol >= (void *) start && symbol < (void *) end)
 
152
                {
 
153
                        char *tmp;
 
154
                        size_t len;
 
155
 
 
156
                        /* Extract the filename; it is always an absolute path */
 
157
                        path = strchr (line, '/');
 
158
 
 
159
                        /* Get rid of the newline */
 
160
                        tmp = strrchr (path, '\n');
 
161
                        if (tmp) *tmp = 0;
 
162
 
 
163
                        /* Get rid of "(deleted)" */
 
164
                        len = strlen (path);
 
165
                        if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
 
166
                        {
 
167
                                tmp = path + len - 10;
 
168
                                *tmp = 0;
 
169
                        }
 
170
 
 
171
                        fclose(f);
 
172
                        return strdup (path);
 
173
                }
 
174
        }
 
175
 
 
176
        fclose (f);
 
177
        return NULL;
 
178
}
 
179
 
 
180
 
 
181
/**
 
182
 * br_extract_prefix:
 
183
 * path: The full path of an executable or library.
 
184
 * Returns: The prefix, or NULL on error. This string should be freed when no longer needed.
 
185
 *
 
186
 * Extracts the prefix from path. This function assumes that your executable
 
187
 * or library is installed in an LSB-compatible directory structure.
 
188
 *
 
189
 * Example:
 
190
 * br_extract_prefix ("/usr/bin/gnome-panel");       --> Returns "/usr"
 
191
 * br_extract_prefix ("/usr/local/lib/libfoo.so");   --> Returns "/usr/local"
 
192
 * br_extract_prefix ("/usr/local/libfoo.so");       --> Returns "/usr"
 
193
 */
 
194
char *
 
195
br_extract_prefix (const char *path)
 
196
{
 
197
        char *end, *tmp, *result;
 
198
 
 
199
        br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
 
200
 
 
201
        if (!*path) return strdup ("/");
 
202
        end = strrchr (path, '/');
 
203
        if (!end) return strdup (path);
 
204
 
 
205
        tmp = g_strndup ((char *) path, end - path);
 
206
        if (!*tmp)
 
207
        {
 
208
                free (tmp);
 
209
                return strdup ("/");
 
210
        }
 
211
        end = strrchr (tmp, '/');
 
212
        if (!end) return tmp;
 
213
 
 
214
        result = g_strndup (tmp, end - tmp);
 
215
        free (tmp);
 
216
 
 
217
        if (!*result)
 
218
        {
 
219
                free (result);
 
220
                result = strdup ("/");
 
221
        }
 
222
 
 
223
        return result;
 
224
}
 
225
 
 
226
 
 
227
/**
 
228
 * br_locate_prefix:
 
229
 * symbol: A symbol that belongs to the app/library you want to locate.
 
230
 * Returns: A prefix. This string should be freed when no longer needed.
 
231
 *
 
232
 * Locates the full path of the app/library that symbol belongs to, and return
 
233
 * the prefix of that path, or NULL on error.
 
234
 * Note that symbol cannot be a pointer to a function. That will not work.
 
235
 *
 
236
 * Example:
 
237
 * --> This application is located in /usr/bin/foo
 
238
 * br_locate_prefix (&argc);   --> returns: "/usr"
 
239
 */
 
240
char *
 
241
br_locate_prefix (void *symbol)
 
242
{
 
243
        char *path, *prefix;
 
244
 
 
245
        br_return_val_if_fail (symbol != NULL, NULL);
 
246
 
 
247
        path = br_locate (symbol);
 
248
        if (!path) return NULL;
 
249
 
 
250
        prefix = br_extract_prefix (path);
 
251
        free (path);
 
252
        return prefix;
 
253
}
 
254
 
 
255
 
 
256
/**
 
257
 * br_prepend_prefix:
 
258
 * symbol: A symbol that belongs to the app/library you want to locate.
 
259
 * path: The path that you want to prepend the prefix to.
 
260
 * Returns: The new path, or NULL on error. This string should be freed when no
 
261
 *          longer needed.
 
262
 *
 
263
 * Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path.
 
264
 * Note that symbol cannot be a pointer to a function. That will not work.
 
265
 *
 
266
 * Example:
 
267
 * --> The application is /usr/bin/foo
 
268
 * br_prepend_prefix (&argc, "/share/foo/data.png");   --> Returns "/usr/share/foo/data.png"
 
269
 */
 
270
char *
 
271
br_prepend_prefix (void *symbol, char *path)
 
272
{
 
273
        char *tmp, *newpath;
 
274
 
 
275
        br_return_val_if_fail (symbol != NULL, NULL);
 
276
        br_return_val_if_fail (path != NULL, NULL);
 
277
 
 
278
        tmp = br_locate_prefix (symbol);
 
279
        if (!tmp) return NULL;
 
280
 
 
281
        if (strcmp (tmp, "/") == 0)
 
282
                newpath = strdup (path);
 
283
        else
 
284
                newpath = g_strconcat (tmp, path, NULL);
 
285
 
 
286
        free (tmp);
 
287
        return newpath;
 
288
}
 
289
 
 
290
#else /* ENABLE_BINRELOC */
 
291
 
 
292
typedef int iso_c_forbids_an_empty_source_file;
 
293
 
 
294
#endif /* ENABLE_BINRELOC */