Version bump.
[geany-mirror.git] / src / prefix.c
blobf06380d062064087b3537a4fb3363608c153e339
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/
7 * This source code is public domain. You can relicense this code
8 * under whatever license you want.
10 * NOTE: if you're using C++ and are getting "undefined reference
11 * to br_*", try renaming prefix.c to prefix.cpp
15 #ifdef HAVE_CONFIG_H
16 # include "config.h"
17 #endif
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
24 #ifdef ENABLE_BINRELOC
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <limits.h>
31 #include <string.h>
32 #include <glib.h>
33 #include "prefix.h"
36 #undef NULL
37 #define NULL ((void *) 0)
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__ */
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <sys/param.h>
49 #include <unistd.h>
52 static char *br_last_value = (char*)NULL;
55 static void
56 br_free_last_value ()
58 if (br_last_value)
59 free (br_last_value);
63 /**
64 * br_thread_local_store:
65 * str: A dynamically allocated string.
66 * Returns: str. This return value must not be freed.
68 * Store str in a thread-local variable and return str. The next
69 * you run this function, that variable is freed too.
70 * This function is created so you don't have to worry about freeing
71 * strings.
73 * Example:
74 * char *foo;
75 * foo = thread_local_store (strdup ("hello")); --> foo == "hello"
76 * foo = thread_local_store (strdup ("world")); --> foo == "world"; "hello" is now freed.
78 const char *
79 br_thread_local_store (char *str)
81 static int initialized = 0;
84 if (!initialized)
86 atexit (br_free_last_value);
87 initialized = 1;
90 if (br_last_value)
91 free (br_last_value);
92 br_last_value = str;
94 return (const char *) str;
98 /**
99 * br_locate:
100 * symbol: A symbol that belongs to the app/library you want to locate.
101 * Returns: A newly allocated string containing the full path of the
102 * app/library that func belongs to, or NULL on error. This
103 * string should be freed when not when no longer needed.
105 * Finds out to which application or library symbol belongs, then locate
106 * the full path of that application or library.
107 * Note that symbol cannot be a pointer to a function. That will not work.
109 * Example:
110 * --> main.c
111 * #include "prefix.h"
112 * #include "libfoo.h"
114 * int main (int argc, char *argv[]) {
115 * printf ("Full path of this app: %s\n", br_locate (&argc));
116 * libfoo_start ();
117 * return 0;
120 * --> libfoo.c starts here
121 * #include "prefix.h"
123 * void libfoo_start () {
124 * --> "" is a symbol that belongs to libfoo (because it's called
125 * --> from libfoo_start()); that's why this works.
126 * printf ("libfoo is located in: %s\n", br_locate (""));
129 char *
130 br_locate (void *symbol)
132 char line[5000];
133 FILE *f;
134 char *path;
136 br_return_val_if_fail (symbol != NULL, NULL);
138 f = fopen ("/proc/self/maps", "r");
139 if (!f)
140 return NULL;
142 while (!feof (f))
144 unsigned long start, end;
146 if (!fgets (line, sizeof (line), f))
147 continue;
148 if (!strstr (line, " r-xp ") || !strchr (line, '/'))
149 continue;
151 sscanf (line, "%lx-%lx ", &start, &end);
152 if (symbol >= (void *) start && symbol < (void *) end)
154 char *tmp;
155 size_t len;
157 /* Extract the filename; it is always an absolute path */
158 path = strchr (line, '/');
160 /* Get rid of the newline */
161 tmp = strrchr (path, '\n');
162 if (tmp) *tmp = 0;
164 /* Get rid of "(deleted)" */
165 len = strlen (path);
166 if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
168 tmp = path + len - 10;
169 *tmp = 0;
172 fclose(f);
173 return strdup (path);
177 fclose (f);
178 return NULL;
183 * br_extract_prefix:
184 * path: The full path of an executable or library.
185 * Returns: The prefix, or NULL on error. This string should be freed when no longer needed.
187 * Extracts the prefix from path. This function assumes that your executable
188 * or library is installed in an LSB-compatible directory structure.
190 * Example:
191 * br_extract_prefix ("/usr/bin/gnome-panel"); --> Returns "/usr"
192 * br_extract_prefix ("/usr/local/lib/libfoo.so"); --> Returns "/usr/local"
193 * br_extract_prefix ("/usr/local/libfoo.so"); --> Returns "/usr"
195 char *
196 br_extract_prefix (const char *path)
198 char *end, *tmp, *result;
200 br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
202 if (!*path) return strdup ("/");
203 end = strrchr (path, '/');
204 if (!end) return strdup (path);
206 tmp = g_strndup ((char *) path, end - path);
207 if (!*tmp)
209 g_free (tmp);
210 return strdup ("/");
212 end = strrchr (tmp, '/');
213 if (!end) return tmp;
215 result = g_strndup (tmp, end - tmp);
216 g_free (tmp);
218 if (!*result)
220 g_free (result);
221 result = strdup ("/");
224 return result;
229 * br_locate_prefix:
230 * symbol: A symbol that belongs to the app/library you want to locate.
231 * Returns: A prefix. This string should be freed when no longer needed.
233 * Locates the full path of the app/library that symbol belongs to, and return
234 * the prefix of that path, or NULL on error.
235 * Note that symbol cannot be a pointer to a function. That will not work.
237 * Example:
238 * --> This application is located in /usr/bin/foo
239 * br_locate_prefix (&argc); --> returns: "/usr"
241 char *
242 br_locate_prefix (void *symbol)
244 char *path, *prefix;
246 br_return_val_if_fail (symbol != NULL, NULL);
248 path = br_locate (symbol);
249 if (!path) return NULL;
251 prefix = br_extract_prefix (path);
252 free (path);
253 return prefix;
258 * br_prepend_prefix:
259 * symbol: A symbol that belongs to the app/library you want to locate.
260 * path: The path that you want to prepend the prefix to.
261 * Returns: The new path, or NULL on error. This string should be freed when no
262 * longer needed.
264 * Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path.
265 * Note that symbol cannot be a pointer to a function. That will not work.
267 * Example:
268 * --> The application is /usr/bin/foo
269 * br_prepend_prefix (&argc, "/share/foo/data.png"); --> Returns "/usr/share/foo/data.png"
271 char *
272 br_prepend_prefix (void *symbol, char *path)
274 char *tmp, *newpath;
276 br_return_val_if_fail (symbol != NULL, NULL);
277 br_return_val_if_fail (path != NULL, NULL);
279 tmp = br_locate_prefix (symbol);
280 if (!tmp) return NULL;
282 if (strcmp (tmp, "/") == 0)
283 newpath = strdup (path);
284 else
285 newpath = g_strconcat (tmp, path, NULL);
287 free (tmp);
288 return newpath;
292 #else /* ENABLE_BINRELOC */
294 typedef int iso_c_forbids_an_empty_source_file;
296 #endif /* ENABLE_BINRELOC */