Update displayed copyright years
[geany-mirror.git] / src / prefix.c
blob147594627af9a2a68cf1837341abde49b496057d
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
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
19 * enrico - all the code below is only compiled and used if ENABLE_BINRELOC is set in config.h,
20 * this only happens if configure option --enable-binreloc was used
22 #ifdef ENABLE_BINRELOC
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <limits.h>
29 #include <string.h>
30 #include <glib.h>
31 #include "prefix.h"
34 #undef NULL
35 #define NULL ((void *) 0)
37 #ifdef __GNUC__
38 #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
39 #else
40 #define br_return_val_if_fail(expr, val) if (!(expr)) return val
41 #endif /* __GNUC__ */
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <sys/param.h>
47 #include <unistd.h>
50 static char *br_last_value = (char*)NULL;
53 static void
54 br_free_last_value (void)
56 if (br_last_value)
57 free (br_last_value);
61 /**
62 * br_thread_local_store:
63 * str: A dynamically allocated string.
64 * Returns: str. This return value must not be freed.
66 * Store str in a thread-local variable and return str. The next
67 * you run this function, that variable is freed too.
68 * This function is created so you don't have to worry about freeing
69 * strings.
71 * Example:
72 * char *foo;
73 * foo = thread_local_store (strdup ("hello")); --> foo == "hello"
74 * foo = thread_local_store (strdup ("world")); --> foo == "world"; "hello" is now freed.
76 const char *
77 br_thread_local_store (char *str)
79 static int initialized = 0;
82 if (!initialized)
84 atexit (br_free_last_value);
85 initialized = 1;
88 if (br_last_value)
89 free (br_last_value);
90 br_last_value = str;
92 return (const char *) str;
96 /**
97 * br_locate:
98 * symbol: A symbol that belongs to the app/library you want to locate.
99 * Returns: A newly allocated string containing the full path of the
100 * app/library that func belongs to, or NULL on error. This
101 * string should be freed when not when no longer needed.
103 * Finds out to which application or library symbol belongs, then locate
104 * the full path of that application or library.
105 * Note that symbol cannot be a pointer to a function. That will not work.
107 * Example:
108 * --> main.c
109 * #include "prefix.h"
110 * #include "libfoo.h"
112 * int main (int argc, char *argv[]) {
113 * printf ("Full path of this app: %s\n", br_locate (&argc));
114 * libfoo_start ();
115 * return 0;
118 * --> libfoo.c starts here
119 * #include "prefix.h"
121 * void libfoo_start () {
122 * --> "" is a symbol that belongs to libfoo (because it's called
123 * --> from libfoo_start()); that's why this works.
124 * printf ("libfoo is located in: %s\n", br_locate (""));
127 char *
128 br_locate (void *symbol)
130 char line[5000];
131 FILE *f;
132 char *path;
134 br_return_val_if_fail (symbol != NULL, NULL);
136 f = fopen ("/proc/self/maps", "r");
137 if (!f)
138 return NULL;
140 while (!feof (f))
142 unsigned long start, end;
144 if (!fgets (line, sizeof (line), f))
145 continue;
146 if (!strstr (line, " r-xp ") || !strchr (line, '/'))
147 continue;
149 sscanf (line, "%lx-%lx ", &start, &end);
150 if (symbol >= (void *) start && symbol < (void *) end)
152 char *tmp;
153 gsize len;
155 /* Extract the filename; it is always an absolute path */
156 path = strchr (line, '/');
158 /* Get rid of the newline */
159 tmp = strrchr (path, '\n');
160 if (tmp) *tmp = 0;
162 /* Get rid of "(deleted)" */
163 len = strlen (path);
164 if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
166 tmp = path + len - 10;
167 *tmp = 0;
170 fclose(f);
171 return strdup (path);
175 fclose (f);
176 return NULL;
181 * br_extract_prefix:
182 * path: The full path of an executable or library.
183 * Returns: The prefix, or NULL on error. This string should be freed when no longer needed.
185 * Extracts the prefix from path. This function assumes that your executable
186 * or library is installed in an LSB-compatible directory structure.
188 * Example:
189 * br_extract_prefix ("/usr/bin/gnome-panel"); --> Returns "/usr"
190 * br_extract_prefix ("/usr/local/lib/libfoo.so"); --> Returns "/usr/local"
191 * br_extract_prefix ("/usr/local/libfoo.so"); --> Returns "/usr"
193 char *
194 br_extract_prefix (const char *path)
196 char *end, *tmp, *result;
198 br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
200 if (!*path) return strdup ("/");
201 end = strrchr (path, '/');
202 if (!end) return strdup (path);
204 tmp = g_strndup ((char *) path, end - path);
205 if (!*tmp)
207 g_free (tmp);
208 return strdup ("/");
210 end = strrchr (tmp, '/');
211 if (!end) return tmp;
213 result = g_strndup (tmp, end - tmp);
214 g_free (tmp);
216 if (!*result)
218 g_free (result);
219 result = strdup ("/");
222 return result;
227 * br_locate_prefix:
228 * symbol: A symbol that belongs to the app/library you want to locate.
229 * Returns: A prefix. This string should be freed when no longer needed.
231 * Locates the full path of the app/library that symbol belongs to, and return
232 * the prefix of that path, or NULL on error.
233 * Note that symbol cannot be a pointer to a function. That will not work.
235 * Example:
236 * --> This application is located in /usr/bin/foo
237 * br_locate_prefix (&argc); --> returns: "/usr"
239 char *
240 br_locate_prefix (void *symbol)
242 char *path, *prefix;
244 br_return_val_if_fail (symbol != NULL, NULL);
246 path = br_locate (symbol);
247 if (!path) return NULL;
249 prefix = br_extract_prefix (path);
250 free (path);
251 return prefix;
256 * br_prepend_prefix:
257 * symbol: A symbol that belongs to the app/library you want to locate.
258 * path: The path that you want to prepend the prefix to.
259 * Returns: The new path, or NULL on error. This string should be freed when no
260 * longer needed.
262 * Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path.
263 * Note that symbol cannot be a pointer to a function. That will not work.
265 * Example:
266 * --> The application is /usr/bin/foo
267 * br_prepend_prefix (&argc, "/share/foo/data.png"); --> Returns "/usr/share/foo/data.png"
269 char *
270 br_prepend_prefix (void *symbol, char *path)
272 char *tmp, *newpath;
274 br_return_val_if_fail (symbol != NULL, NULL);
275 br_return_val_if_fail (path != NULL, NULL);
277 tmp = br_locate_prefix (symbol);
278 if (!tmp) return NULL;
280 if (strcmp (tmp, "/") == 0)
281 newpath = strdup (path);
282 else
283 newpath = g_strconcat (tmp, path, NULL);
285 free (tmp);
286 return newpath;
290 #else /* ENABLE_BINRELOC */
292 typedef int iso_c_forbids_an_empty_source_file;
294 #endif /* ENABLE_BINRELOC */