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