diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/eina/src/lib/eina_prefix.c | 726 |
1 files changed, 0 insertions, 726 deletions
diff --git a/libraries/eina/src/lib/eina_prefix.c b/libraries/eina/src/lib/eina_prefix.c deleted file mode 100644 index 2322311..0000000 --- a/libraries/eina/src/lib/eina_prefix.c +++ /dev/null | |||
@@ -1,726 +0,0 @@ | |||
1 | /* EINA - EFL data type library | ||
2 | * Copyright (C) 2011 Carsten Haitzler | ||
3 | * | ||
4 | * This library is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU Lesser General Public | ||
6 | * License as published by the Free Software Foundation; either | ||
7 | * version 2.1 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * This library is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * Lesser General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Lesser General Public | ||
15 | * License along with this library; | ||
16 | * if not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include "config.h" | ||
21 | #endif | ||
22 | |||
23 | #ifdef STDC_HEADERS | ||
24 | # include <stdlib.h> | ||
25 | # include <stddef.h> | ||
26 | #else | ||
27 | # ifdef HAVE_STDLIB_H | ||
28 | # include <stdlib.h> | ||
29 | # endif | ||
30 | #endif | ||
31 | #ifdef HAVE_ALLOCA_H | ||
32 | # include <alloca.h> | ||
33 | #elif !defined alloca | ||
34 | # ifdef __GNUC__ | ||
35 | # define alloca __builtin_alloca | ||
36 | # elif defined _AIX | ||
37 | # define alloca __alloca | ||
38 | # elif defined _MSC_VER | ||
39 | # include <malloc.h> | ||
40 | # define alloca _alloca | ||
41 | # elif !defined HAVE_ALLOCA | ||
42 | # ifdef __cplusplus | ||
43 | extern "C" | ||
44 | # endif | ||
45 | void *alloca (size_t); | ||
46 | # endif | ||
47 | #endif | ||
48 | |||
49 | #include <stdio.h> | ||
50 | #include <stdlib.h> | ||
51 | #include <string.h> | ||
52 | #include <sys/types.h> | ||
53 | #include <sys/stat.h> | ||
54 | #include <limits.h> | ||
55 | |||
56 | #ifdef HAVE_UNISTD_H | ||
57 | # include <unistd.h> | ||
58 | #endif | ||
59 | |||
60 | #ifdef HAVE_DLADDR | ||
61 | # include <dlfcn.h> | ||
62 | #endif | ||
63 | |||
64 | #ifdef HAVE_EVIL | ||
65 | # include <Evil.h> | ||
66 | #endif | ||
67 | |||
68 | #ifdef HAVE_ESCAPE | ||
69 | # include <Escape.h> | ||
70 | #endif | ||
71 | |||
72 | #include "eina_config.h" | ||
73 | #include "eina_private.h" | ||
74 | #include "eina_log.h" | ||
75 | #include "eina_prefix.h" | ||
76 | |||
77 | #ifdef _WIN32 | ||
78 | # define PSEP_C ';' | ||
79 | # define DSEP_C '\\' | ||
80 | # define DSEP_S "\\" | ||
81 | #else | ||
82 | # define PSEP_C ':' | ||
83 | # define DSEP_C '/' | ||
84 | # define DSEP_S "/" | ||
85 | #endif /* _WIN32 */ | ||
86 | |||
87 | /*============================================================================* | ||
88 | * Local * | ||
89 | *============================================================================*/ | ||
90 | |||
91 | /** | ||
92 | * @cond LOCAL | ||
93 | */ | ||
94 | |||
95 | struct _Eina_Prefix | ||
96 | { | ||
97 | char *exe_path; | ||
98 | |||
99 | char *prefix_path; | ||
100 | char *prefix_path_bin; | ||
101 | char *prefix_path_data; | ||
102 | char *prefix_path_lib; | ||
103 | char *prefix_path_locale; | ||
104 | |||
105 | unsigned char fallback : 1; | ||
106 | unsigned char no_common_prefix : 1; | ||
107 | unsigned char env_used : 1; | ||
108 | }; | ||
109 | |||
110 | #define STRDUP_REP(x, y) do { if (x) free(x); x = strdup(y); } while (0) | ||
111 | #define IF_FREE_NULL(p) do { if (p) { free(p); p = NULL; } } while (0) | ||
112 | |||
113 | #ifndef EINA_LOG_COLOR_DEFAULT | ||
114 | #define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN | ||
115 | #endif | ||
116 | |||
117 | #ifdef ERR | ||
118 | #undef ERR | ||
119 | #endif | ||
120 | #define ERR(...) EINA_LOG_DOM_ERR(_eina_prefix_log_dom, __VA_ARGS__) | ||
121 | |||
122 | #ifdef WRN | ||
123 | #undef WRN | ||
124 | #endif | ||
125 | #define WRN(...) EINA_LOG_DOM_WARN(_eina_prefix_log_dom, __VA_ARGS__) | ||
126 | |||
127 | #ifdef INF | ||
128 | #undef INF | ||
129 | #endif | ||
130 | #define INF(...) EINA_LOG_DOM_INFO(_eina_prefix_log_dom, __VA_ARGS__) | ||
131 | |||
132 | #ifdef DBG | ||
133 | #undef DBG | ||
134 | #endif | ||
135 | #define DBG(...) EINA_LOG_DOM_DBG(_eina_prefix_log_dom, __VA_ARGS__) | ||
136 | |||
137 | static int _eina_prefix_log_dom = -1; | ||
138 | |||
139 | static int | ||
140 | _fallback(Eina_Prefix *pfx, const char *pkg_bin, const char *pkg_lib, | ||
141 | const char *pkg_data, const char *pkg_locale, const char *envprefix) | ||
142 | { | ||
143 | char *p; | ||
144 | |||
145 | STRDUP_REP(pfx->prefix_path, pkg_bin); | ||
146 | if (!pfx->prefix_path) return 0; | ||
147 | p = strrchr(pfx->prefix_path, DSEP_C); | ||
148 | if (p) *p = 0; | ||
149 | STRDUP_REP(pfx->prefix_path_bin, pkg_bin); | ||
150 | STRDUP_REP(pfx->prefix_path_lib, pkg_lib); | ||
151 | STRDUP_REP(pfx->prefix_path_data, pkg_data); | ||
152 | STRDUP_REP(pfx->prefix_path_locale, pkg_locale); | ||
153 | WRN("Could not determine its installed prefix for '%s'\n" | ||
154 | " so am falling back on the compiled in default:\n" | ||
155 | " %s\n" | ||
156 | " implied by the following:\n" | ||
157 | " bindir = %s\n" | ||
158 | " libdir = %s\n" | ||
159 | " datadir = %s\n" | ||
160 | " localedir = %s\n" | ||
161 | " Try setting the following environment variables:\n" | ||
162 | " %s_PREFIX - points to the base prefix of install\n" | ||
163 | " or the next 4 variables\n" | ||
164 | " %s_BIN_DIR - provide a specific binary directory\n" | ||
165 | " %s_LIB_DIR - provide a specific library directory\n" | ||
166 | " %s_DATA_DIR - provide a specific data directory\n" | ||
167 | " %s_LOCALE_DIR - provide a specific locale directory", | ||
168 | envprefix, | ||
169 | pfx->prefix_path, pkg_bin, pkg_lib, pkg_data, pkg_locale, | ||
170 | envprefix, envprefix, envprefix, envprefix, envprefix); | ||
171 | pfx->fallback = 1; | ||
172 | return 1; | ||
173 | } | ||
174 | |||
175 | #ifndef _WIN32 | ||
176 | static int | ||
177 | _try_proc(Eina_Prefix *pfx, void *symbol) | ||
178 | { | ||
179 | FILE *f; | ||
180 | char buf[4096]; | ||
181 | |||
182 | DBG("Try /proc/self/maps"); | ||
183 | f = fopen("/proc/self/maps", "rb"); | ||
184 | if (!f) return 0; | ||
185 | DBG("Exists /proc/self/maps"); | ||
186 | while (fgets(buf, sizeof(buf), f)) | ||
187 | { | ||
188 | int len; | ||
189 | char *p, mode[5] = ""; | ||
190 | unsigned long ptr1 = 0, ptr2 = 0; | ||
191 | |||
192 | len = strlen(buf); | ||
193 | if (buf[len - 1] == '\n') | ||
194 | { | ||
195 | buf[len - 1] = 0; | ||
196 | len--; | ||
197 | } | ||
198 | if (sscanf(buf, "%lx-%lx %4s", &ptr1, &ptr2, mode) == 3) | ||
199 | { | ||
200 | if (!strcmp(mode, "r-xp")) | ||
201 | { | ||
202 | if (((void *)ptr1 <= symbol) && (symbol < (void *)ptr2)) | ||
203 | { | ||
204 | DBG("Found in /proc/self/maps: %s", buf); | ||
205 | p = strchr(buf, '/'); | ||
206 | if (p) | ||
207 | { | ||
208 | DBG("Found in /proc/self/maps: found last /"); | ||
209 | if (len > 10) | ||
210 | { | ||
211 | if (!strcmp(buf + len - 10, " (deleted)")) | ||
212 | buf[len - 10] = 0; | ||
213 | } | ||
214 | STRDUP_REP(pfx->exe_path, p); | ||
215 | INF("Found in /proc/self/maps: guess exe path is %s", pfx->exe_path); | ||
216 | fclose(f); | ||
217 | return 1; | ||
218 | } | ||
219 | else break; | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | fclose(f); | ||
225 | WRN("Failed in /proc/self/maps"); | ||
226 | return 0; | ||
227 | } | ||
228 | #endif | ||
229 | |||
230 | static int | ||
231 | _try_argv(Eina_Prefix *pfx, const char *argv0) | ||
232 | { | ||
233 | char *path, *p, *cp, *s; | ||
234 | int len, lenexe; | ||
235 | char buf[PATH_MAX], buf2[PATH_MAX], buf3[PATH_MAX]; | ||
236 | |||
237 | DBG("Try argv0 = %s", argv0); | ||
238 | /* 1. is argv0 abs path? */ | ||
239 | #ifdef _WIN32 | ||
240 | if (evil_path_is_absolute(argv0)) | ||
241 | #else | ||
242 | if (argv0[0] == DSEP_C) | ||
243 | #endif | ||
244 | { | ||
245 | DBG("Match arvg0 is full path: %s", argv0); | ||
246 | STRDUP_REP(pfx->exe_path, argv0); | ||
247 | if (access(pfx->exe_path, X_OK) == 0) | ||
248 | { | ||
249 | INF("Executable argv0 = %s", argv0); | ||
250 | return 1; | ||
251 | } | ||
252 | IF_FREE_NULL(pfx->exe_path); | ||
253 | DBG("Non existent argv0: %s", argv0); | ||
254 | return 0; | ||
255 | } | ||
256 | /* 2. relative path */ | ||
257 | if (strchr(argv0, DSEP_C)) | ||
258 | { | ||
259 | DBG("Relative path argv0: %s", argv0); | ||
260 | if (getcwd(buf3, sizeof(buf3))) | ||
261 | { | ||
262 | snprintf(buf2, sizeof(buf2), "%s" DSEP_S "%s", buf3, argv0); | ||
263 | DBG("Relative to CWD: %s", buf2); | ||
264 | if (realpath(buf2, buf)) | ||
265 | { | ||
266 | DBG("Realpath is: %s", buf); | ||
267 | STRDUP_REP(pfx->exe_path, buf); | ||
268 | if (access(pfx->exe_path, X_OK) == 0) | ||
269 | { | ||
270 | INF("Path %s is executable", pfx->exe_path); | ||
271 | return 1; | ||
272 | } | ||
273 | DBG("Fail check for executable: %s", pfx->exe_path); | ||
274 | IF_FREE_NULL(pfx->exe_path); | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | /* 3. argv0 no path - look in PATH */ | ||
279 | DBG("Look for argv0=%s in $PATH", argv0); | ||
280 | path = getenv("PATH"); | ||
281 | if (!path) return 0; | ||
282 | p = path; | ||
283 | cp = p; | ||
284 | lenexe = strlen(argv0); | ||
285 | while ((p = strchr(cp, PSEP_C))) | ||
286 | { | ||
287 | len = p - cp; | ||
288 | s = malloc(len + 1 + lenexe + 1); | ||
289 | if (s) | ||
290 | { | ||
291 | strncpy(s, cp, len); | ||
292 | s[len] = DSEP_C; | ||
293 | strcpy(s + len + 1, argv0); | ||
294 | DBG("Try path: %s", s); | ||
295 | if (realpath(s, buf)) | ||
296 | { | ||
297 | DBG("Realpath is: %s", buf); | ||
298 | if (access(buf, X_OK) == 0) | ||
299 | { | ||
300 | STRDUP_REP(pfx->exe_path, buf); | ||
301 | INF("Path %s is executable", pfx->exe_path); | ||
302 | free(s); | ||
303 | return 1; | ||
304 | } | ||
305 | } | ||
306 | free(s); | ||
307 | } | ||
308 | cp = p + 1; | ||
309 | } | ||
310 | /* 4. big problems. arg[0] != executable - weird execution */ | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int | ||
315 | _get_env_var(char **var, const char *env, const char *prefix, const char *dir) | ||
316 | { | ||
317 | char buf[PATH_MAX]; | ||
318 | const char *s = getenv(env); | ||
319 | |||
320 | DBG("Try env var %s", env); | ||
321 | if (s) | ||
322 | { | ||
323 | INF("Have env %s = %s", env, s); | ||
324 | STRDUP_REP(*var, s); | ||
325 | return 1; | ||
326 | } | ||
327 | else if (prefix) | ||
328 | { | ||
329 | snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", prefix, dir); | ||
330 | INF("Have prefix %s = %s", prefix, buf); | ||
331 | STRDUP_REP(*var, buf); | ||
332 | return 1; | ||
333 | } | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static int | ||
338 | _get_env_vars(Eina_Prefix *pfx, | ||
339 | const char *envprefix, | ||
340 | const char *bindir, | ||
341 | const char *libdir, | ||
342 | const char *datadir, | ||
343 | const char *localedir) | ||
344 | { | ||
345 | char env[1024]; | ||
346 | const char *s; | ||
347 | int ret = 0; | ||
348 | |||
349 | snprintf(env, sizeof(env), "%s_PREFIX", envprefix); | ||
350 | if ((s = getenv(env))) STRDUP_REP(pfx->prefix_path, s); | ||
351 | snprintf(env, sizeof(env), "%s_BIN_DIR", envprefix); | ||
352 | ret += _get_env_var(&pfx->prefix_path_bin, env, s, bindir); | ||
353 | snprintf(env, sizeof(env), "%s_LIB_DIR", envprefix); | ||
354 | ret += _get_env_var(&pfx->prefix_path_lib, env, s, libdir); | ||
355 | snprintf(env, sizeof(env), "%s_DATA_DIR", envprefix); | ||
356 | ret += _get_env_var(&pfx->prefix_path_data, env, s, datadir); | ||
357 | snprintf(env, sizeof(env), "%s_LOCALE_DIR", envprefix); | ||
358 | ret += _get_env_var(&pfx->prefix_path_locale, env, s, localedir); | ||
359 | return ret; | ||
360 | } | ||
361 | |||
362 | /** | ||
363 | * @endcond | ||
364 | */ | ||
365 | |||
366 | |||
367 | /*============================================================================* | ||
368 | * Global * | ||
369 | *============================================================================*/ | ||
370 | |||
371 | |||
372 | /*============================================================================* | ||
373 | * API * | ||
374 | *============================================================================*/ | ||
375 | |||
376 | |||
377 | EAPI Eina_Prefix * | ||
378 | eina_prefix_new(const char *argv0, void *symbol, const char *envprefix, | ||
379 | const char *sharedir, const char *magicsharefile, | ||
380 | const char *pkg_bin, const char *pkg_lib, | ||
381 | const char *pkg_data, const char *pkg_locale) | ||
382 | { | ||
383 | Eina_Prefix *pfx; | ||
384 | char *p, buf[4096], *tmp, *magic = NULL; | ||
385 | struct stat st; | ||
386 | const char *p1, *p2; | ||
387 | const char *pkg_bin_p = NULL; | ||
388 | const char *pkg_lib_p = NULL; | ||
389 | const char *pkg_data_p = NULL; | ||
390 | const char *pkg_locale_p = NULL; | ||
391 | const char *bindir = "bin"; | ||
392 | const char *libdir = "lib"; | ||
393 | const char *datadir = "share"; | ||
394 | const char *localedir = "share"; | ||
395 | |||
396 | DBG("EINA PREFIX: argv0=%s, symbol=%p, magicsharefile=%s, envprefix=%s", | ||
397 | argv0, symbol, magicsharefile, envprefix); | ||
398 | pfx = calloc(1, sizeof(Eina_Prefix)); | ||
399 | if (!pfx) return NULL; | ||
400 | |||
401 | /* if provided with a share dir use datadir/sharedir as the share dir */ | ||
402 | if (sharedir) | ||
403 | { | ||
404 | int len; | ||
405 | |||
406 | len = snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", datadir, sharedir); | ||
407 | if (len > 0) | ||
408 | { | ||
409 | #ifdef _WIN32 | ||
410 | /* on win32 convert / to \ for path here */ | ||
411 | for (p = buf + strlen(datadir) + strlen(DSEP_S); *p; p++) | ||
412 | { | ||
413 | if (*p == '/') *p = DSEP_C; | ||
414 | } | ||
415 | #endif | ||
416 | tmp = alloca(len + 1); | ||
417 | strcpy(tmp, buf); | ||
418 | datadir = tmp; | ||
419 | } | ||
420 | } | ||
421 | if (magicsharefile) | ||
422 | { | ||
423 | magic = alloca(strlen(magicsharefile)); | ||
424 | strcpy(magic, magicsharefile); | ||
425 | #ifdef _WIN32 | ||
426 | /* on win32 convert / to \ for path here */ | ||
427 | for (p = magic; *p; p++) | ||
428 | { | ||
429 | if (*p == '/') *p = DSEP_C; | ||
430 | } | ||
431 | #endif | ||
432 | } | ||
433 | |||
434 | /* look at compile-time package bin/lib/datadir etc. and figure out the | ||
435 | * bin, lib and data dirs from these, if possible. i.e. | ||
436 | * bin = /usr/local/bin | ||
437 | * lib = /usr/local/lib | ||
438 | * data = /usr/local/share/enlightenment | ||
439 | * thus they all have a common prefix string of /usr/local/ and | ||
440 | * bindir = bin | ||
441 | * libdir = lib | ||
442 | * datadir = share/enlightenment | ||
443 | * this addresses things like libdir is lib64 or lib32 or other such | ||
444 | * junk distributions like to do so then: | ||
445 | * bin = /usr/local/bin | ||
446 | * lib = /usr/local/lib64 | ||
447 | * data = /usr/local/share/enlightenment | ||
448 | * then | ||
449 | * bindir = bin | ||
450 | * libdir = lib64 | ||
451 | * datadir = share/enlightennment | ||
452 | * in theory this should also work with debians new multiarch style like | ||
453 | * bindir = bin | ||
454 | * libdir = lib/i386-linux-gnu | ||
455 | * or | ||
456 | * libdir = lib/x86_64-linux-gnu | ||
457 | * all with a common prefix that can be relocated | ||
458 | */ | ||
459 | /* 1. check last common char in bin and lib strings */ | ||
460 | for (p1 = pkg_bin, p2 = pkg_lib; *p1 && *p2; p1++, p2++) | ||
461 | { | ||
462 | if (*p1 != *p2) | ||
463 | { | ||
464 | pkg_bin_p = p1; | ||
465 | pkg_lib_p = p2; | ||
466 | break; | ||
467 | } | ||
468 | } | ||
469 | /* 1. check last common char in bin and data strings */ | ||
470 | for (p1 = pkg_bin, p2 = pkg_data; *p1 && *p2; p1++, p2++) | ||
471 | { | ||
472 | if (*p1 != *p2) | ||
473 | { | ||
474 | pkg_data_p = p2; | ||
475 | break; | ||
476 | } | ||
477 | } | ||
478 | /* 1. check last common char in bin and locale strings */ | ||
479 | for (p1 = pkg_bin, p2 = pkg_locale; *p1 && *p2; p1++, p2++) | ||
480 | { | ||
481 | if (*p1 != *p2) | ||
482 | { | ||
483 | pkg_locale_p = p2; | ||
484 | break; | ||
485 | } | ||
486 | } | ||
487 | /* 2. if all the common string offsets match we compiled with a common prefix */ | ||
488 | if (((pkg_bin_p - pkg_bin) == (pkg_lib_p - pkg_lib)) | ||
489 | && ((pkg_bin_p - pkg_bin) == (pkg_data_p - pkg_data)) | ||
490 | && ((pkg_bin_p - pkg_bin) == (pkg_locale_p - pkg_locale)) | ||
491 | ) | ||
492 | { | ||
493 | bindir = pkg_bin_p; | ||
494 | libdir = pkg_lib_p; | ||
495 | datadir = pkg_data_p; | ||
496 | localedir = pkg_locale_p; | ||
497 | DBG("Prefix relative bindir = %s", bindir); | ||
498 | DBG("Prefix relative libdir = %s", libdir); | ||
499 | DBG("Prefix relative datadir = %s", datadir); | ||
500 | DBG("Prefix relative localedir = %s", localedir); | ||
501 | } | ||
502 | /* 3. some galoot thought it awesome not to give us a common prefix at compile time | ||
503 | * so fall back to the compile time directories. we are no longer relocatable */ | ||
504 | else | ||
505 | { | ||
506 | STRDUP_REP(pfx->prefix_path_bin, pkg_bin); | ||
507 | STRDUP_REP(pfx->prefix_path_lib, pkg_lib); | ||
508 | STRDUP_REP(pfx->prefix_path_data, pkg_data); | ||
509 | STRDUP_REP(pfx->prefix_path_locale, pkg_locale); | ||
510 | pfx->no_common_prefix = 1; | ||
511 | DBG("Can't work out a common prefix - compiled in fallback"); | ||
512 | } | ||
513 | |||
514 | /* if user provides env vars - then use that or also more specific sub | ||
515 | * dirs for bin, lib, data and locale */ | ||
516 | if ((envprefix) && | ||
517 | (_get_env_vars(pfx, envprefix, bindir, libdir, datadir, localedir) > 0)) | ||
518 | { | ||
519 | pfx->env_used = 1; | ||
520 | return pfx; | ||
521 | } | ||
522 | |||
523 | #ifdef HAVE_DLADDR | ||
524 | DBG("Try dladdr on %p", symbol); | ||
525 | if (symbol) | ||
526 | { | ||
527 | Dl_info info_dl; | ||
528 | |||
529 | if (dladdr(symbol, &info_dl)) | ||
530 | { | ||
531 | DBG("Dlinfo worked"); | ||
532 | if (info_dl.dli_fname) | ||
533 | { | ||
534 | DBG("Dlinfo dli_fname = %s", info_dl.dli_fname); | ||
535 | # ifdef _WIN32 | ||
536 | if (evil_path_is_absolute(info_dl.dli_fname)) | ||
537 | # else | ||
538 | if (info_dl.dli_fname[0] == DSEP_C) | ||
539 | # endif | ||
540 | { | ||
541 | INF("Dlsym gave full path = %s", info_dl.dli_fname); | ||
542 | STRDUP_REP(pfx->exe_path, info_dl.dli_fname); | ||
543 | } | ||
544 | } | ||
545 | } | ||
546 | } | ||
547 | #endif | ||
548 | /* no env var - examine process and possible argv0 */ | ||
549 | if ((argv0) && (!pfx->exe_path) && (symbol)) | ||
550 | { | ||
551 | #ifndef _WIN32 | ||
552 | if (!_try_proc(pfx, symbol)) | ||
553 | { | ||
554 | #endif | ||
555 | if (!_try_argv(pfx, argv0)) | ||
556 | { | ||
557 | _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, | ||
558 | envprefix); | ||
559 | return pfx; | ||
560 | } | ||
561 | #ifndef _WIN32 | ||
562 | } | ||
563 | #endif | ||
564 | } | ||
565 | if (!pfx->exe_path) | ||
566 | { | ||
567 | WRN("Fallback - nothing found"); | ||
568 | _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix); | ||
569 | return pfx; | ||
570 | } | ||
571 | /* _exe_path is now a full absolute path TO this exe - figure out rest */ | ||
572 | /* if | ||
573 | * exe = /blah/whatever/bin/exe | ||
574 | * or | ||
575 | * exe = /blah/whatever/lib/libexe.so | ||
576 | * then | ||
577 | * prefix = /blah/whatever | ||
578 | * bin_dir = /blah/whatever/bin | ||
579 | * data_dir = /blah/whatever/share/enlightenment | ||
580 | * lib_dir = /blah/whatever/lib | ||
581 | */ | ||
582 | DBG("From exe %s figure out the rest", pfx->exe_path); | ||
583 | p = strrchr(pfx->exe_path, DSEP_C); | ||
584 | if (p) | ||
585 | { | ||
586 | p--; | ||
587 | while (p >= pfx->exe_path) | ||
588 | { | ||
589 | if (*p == DSEP_C) | ||
590 | { | ||
591 | pfx->prefix_path = malloc(p - pfx->exe_path + 1); | ||
592 | if (pfx->prefix_path) | ||
593 | { | ||
594 | strncpy(pfx->prefix_path, pfx->exe_path, | ||
595 | p - pfx->exe_path); | ||
596 | pfx->prefix_path[p - pfx->exe_path] = 0; | ||
597 | DBG("Have prefix = %s", pfx->prefix_path); | ||
598 | |||
599 | /* bin */ | ||
600 | snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", | ||
601 | pfx->prefix_path, bindir); | ||
602 | STRDUP_REP(pfx->prefix_path_bin, buf); | ||
603 | DBG("Have bin = %s", pfx->prefix_path_bin); | ||
604 | /* lib */ | ||
605 | snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", | ||
606 | pfx->prefix_path, libdir); | ||
607 | STRDUP_REP(pfx->prefix_path_lib, buf); | ||
608 | DBG("Have lib = %s", pfx->prefix_path_lib); | ||
609 | /* locale */ | ||
610 | snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", | ||
611 | pfx->prefix_path, localedir); | ||
612 | STRDUP_REP(pfx->prefix_path_locale, buf); | ||
613 | DBG("Have locale = %s", pfx->prefix_path_locale); | ||
614 | /* check if magic file is there - then our guess is right */ | ||
615 | if (magic) | ||
616 | { | ||
617 | DBG("Magic = %s", magic); | ||
618 | snprintf(buf, sizeof(buf), | ||
619 | "%s" DSEP_S "%s" DSEP_S "%s", | ||
620 | pfx->prefix_path, datadir, magic); | ||
621 | DBG("Check in %s", buf); | ||
622 | } | ||
623 | if ((!magic) || (stat(buf, &st) == 0)) | ||
624 | { | ||
625 | if (buf[0]) | ||
626 | DBG("Magic path %s stat passed", buf); | ||
627 | else | ||
628 | DBG("No magic file"); | ||
629 | snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", | ||
630 | pfx->prefix_path, datadir); | ||
631 | STRDUP_REP(pfx->prefix_path_data, buf); | ||
632 | } | ||
633 | /* magic file not there. time to start hunting! */ | ||
634 | else | ||
635 | { | ||
636 | WRN("Magic failed"); | ||
637 | _fallback(pfx, pkg_bin, pkg_lib, pkg_data, | ||
638 | pkg_locale, envprefix); | ||
639 | } | ||
640 | } | ||
641 | else | ||
642 | { | ||
643 | WRN("No Prefix path (alloc fail)"); | ||
644 | _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, | ||
645 | envprefix); | ||
646 | } | ||
647 | return pfx; | ||
648 | } | ||
649 | p--; | ||
650 | } | ||
651 | } | ||
652 | WRN("Final fallback"); | ||
653 | _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix); | ||
654 | return pfx; | ||
655 | } | ||
656 | |||
657 | EAPI void | ||
658 | eina_prefix_free(Eina_Prefix *pfx) | ||
659 | { | ||
660 | if (!pfx) return; | ||
661 | |||
662 | IF_FREE_NULL(pfx->exe_path); | ||
663 | IF_FREE_NULL(pfx->prefix_path); | ||
664 | IF_FREE_NULL(pfx->prefix_path_bin); | ||
665 | IF_FREE_NULL(pfx->prefix_path_data); | ||
666 | IF_FREE_NULL(pfx->prefix_path_lib); | ||
667 | IF_FREE_NULL(pfx->prefix_path_locale); | ||
668 | free(pfx); | ||
669 | } | ||
670 | |||
671 | EAPI const char * | ||
672 | eina_prefix_get(Eina_Prefix *pfx) | ||
673 | { | ||
674 | if (!pfx) return ""; | ||
675 | return pfx->prefix_path; | ||
676 | } | ||
677 | |||
678 | EAPI const char * | ||
679 | eina_prefix_bin_get(Eina_Prefix *pfx) | ||
680 | { | ||
681 | if (!pfx) return ""; | ||
682 | return pfx->prefix_path_bin; | ||
683 | } | ||
684 | |||
685 | EAPI const char * | ||
686 | eina_prefix_lib_get(Eina_Prefix *pfx) | ||
687 | { | ||
688 | if (!pfx) return ""; | ||
689 | return pfx->prefix_path_lib; | ||
690 | } | ||
691 | |||
692 | EAPI const char * | ||
693 | eina_prefix_data_get(Eina_Prefix *pfx) | ||
694 | { | ||
695 | if (!pfx) return ""; | ||
696 | return pfx->prefix_path_data; | ||
697 | } | ||
698 | |||
699 | EAPI const char * | ||
700 | eina_prefix_locale_get(Eina_Prefix *pfx) | ||
701 | { | ||
702 | if (!pfx) return ""; | ||
703 | return pfx->prefix_path_locale; | ||
704 | } | ||
705 | |||
706 | Eina_Bool | ||
707 | eina_prefix_init(void) | ||
708 | { | ||
709 | _eina_prefix_log_dom = eina_log_domain_register("eina_prefix", | ||
710 | EINA_LOG_COLOR_DEFAULT); | ||
711 | if (_eina_prefix_log_dom < 0) | ||
712 | { | ||
713 | EINA_LOG_ERR("Could not register log domain: eina_prefix"); | ||
714 | return EINA_FALSE; | ||
715 | } | ||
716 | |||
717 | return EINA_TRUE; | ||
718 | } | ||
719 | |||
720 | Eina_Bool | ||
721 | eina_prefix_shutdown(void) | ||
722 | { | ||
723 | eina_log_domain_unregister(_eina_prefix_log_dom); | ||
724 | _eina_prefix_log_dom = -1; | ||
725 | return EINA_TRUE; | ||
726 | } | ||