~ubuntu-branches/ubuntu/karmic/mergeant/karmic

« back to all changes in this revision

Viewing changes to src/binreloc/binreloc.c

  • Committer: Bazaar Package Importer
  • Author(s): Gustavo R. Montesino
  • Date: 2007-11-29 08:44:48 UTC
  • mfrom: (2.1.4 hardy)
  • Revision ID: james.westby@ubuntu.com-20071129084448-6aon73d22bv6hzfw
Tags: 0.67-3
* Re-enable installation of the mime files in mergeant.install
* mergeant.dirs: create usr/share/mime/packages to make dh_installmime add
  the update-mime-database code snippets

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * BinReloc - a library for creating relocatable executables
 
3
 * Written by: Hongli Lai <h.lai@chello.nl>
 
4
 * http://autopackage.org/
 
5
 *
 
6
 * This source code is public domain. You can relicense this code
 
7
 * under whatever license you want.
 
8
 *
 
9
 * See http://autopackage.org/docs/binreloc/ for
 
10
 * more information and how to use this.
 
11
 */
 
12
 
 
13
#ifndef __BINRELOC_C__
 
14
#define __BINRELOC_C__
 
15
 
 
16
#ifdef ENABLE_BINRELOC
 
17
        #include <sys/types.h>
 
18
        #include <sys/stat.h>
 
19
        #include <unistd.h>
 
20
#endif /* ENABLE_BINRELOC */
 
21
#include <stdio.h>
 
22
#include <stdlib.h>
 
23
#include <limits.h>
 
24
#include <string.h>
 
25
#include "binreloc.h"
 
26
 
 
27
G_BEGIN_DECLS
 
28
 
 
29
 
 
30
/** @internal
 
31
 * Find the canonical filename of the executable. Returns the filename
 
32
 * (which must be freed) or NULL on error. If the parameter 'error' is
 
33
 * not NULL, the error code will be stored there, if an error occured.
 
34
 */
 
35
static char *
 
36
_br_find_exe (GbrInitError *error)
 
37
{
 
38
#ifndef ENABLE_BINRELOC
 
39
        if (error)
 
40
                *error = _MG_GBR_INIT_ERROR_DISABLED;
 
41
        return NULL;
 
42
#else
 
43
        char *path, *path2, *line, *result;
 
44
        size_t buf_size;
 
45
        ssize_t size;
 
46
        struct stat stat_buf;
 
47
        FILE *f;
 
48
 
 
49
        /* Read from /proc/self/exe (symlink) */
 
50
        if (sizeof (path) > SSIZE_MAX)
 
51
                buf_size = SSIZE_MAX - 1;
 
52
        else
 
53
                buf_size = PATH_MAX - 1;
 
54
        path = (char *) g_try_malloc (buf_size);
 
55
        if (path == NULL) {
 
56
                /* Cannot allocate memory. */
 
57
                if (error)
 
58
                        *error = _MG_GBR_INIT_ERROR_NOMEM;
 
59
                return NULL;
 
60
        }
 
61
        path2 = (char *) g_try_malloc (buf_size);
 
62
        if (path2 == NULL) {
 
63
                /* Cannot allocate memory. */
 
64
                if (error)
 
65
                        *error = _MG_GBR_INIT_ERROR_NOMEM;
 
66
                g_free (path);
 
67
                return NULL;
 
68
        }
 
69
 
 
70
        strncpy (path2, "/proc/self/exe", buf_size - 1);
 
71
 
 
72
        while (1) {
 
73
                int i;
 
74
 
 
75
                size = readlink (path2, path, buf_size - 1);
 
76
                if (size == -1) {
 
77
                        /* Error. */
 
78
                        g_free (path2);
 
79
                        break;
 
80
                }
 
81
 
 
82
                /* readlink() success. */
 
83
                path[size] = '\0';
 
84
 
 
85
                /* Check whether the symlink's target is also a symlink.
 
86
                 * We want to get the final target. */
 
87
                i = stat (path, &stat_buf);
 
88
                if (i == -1) {
 
89
                        /* Error. */
 
90
                        g_free (path2);
 
91
                        break;
 
92
                }
 
93
 
 
94
                /* stat() success. */
 
95
                if (!S_ISLNK (stat_buf.st_mode)) {
 
96
                        /* path is not a symlink. Done. */
 
97
                        g_free (path2);
 
98
                        return path;
 
99
                }
 
100
 
 
101
                /* path is a symlink. Continue loop and resolve this. */
 
102
                strncpy (path, path2, buf_size - 1);
 
103
        }
 
104
 
 
105
 
 
106
        /* readlink() or stat() failed; this can happen when the program is
 
107
         * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */
 
108
 
 
109
        buf_size = PATH_MAX + 128;
 
110
        line = (char *) g_try_realloc (path, buf_size);
 
111
        if (line == NULL) {
 
112
                /* Cannot allocate memory. */
 
113
                g_free (path);
 
114
                if (error)
 
115
                        *error = _MG_GBR_INIT_ERROR_NOMEM;
 
116
                return NULL;
 
117
        }
 
118
 
 
119
        f = fopen ("/proc/self/maps", "r");
 
120
        if (f == NULL) {
 
121
                g_free (line);
 
122
                if (error)
 
123
                        *error = _MG_GBR_INIT_ERROR_OPEN_MAPS;
 
124
                return NULL;
 
125
        }
 
126
 
 
127
        /* The first entry should be the executable name. */
 
128
        result = fgets (line, (int) buf_size, f);
 
129
        if (result == NULL) {
 
130
                fclose (f);
 
131
                g_free (line);
 
132
                if (error)
 
133
                        *error = _MG_GBR_INIT_ERROR_READ_MAPS;
 
134
                return NULL;
 
135
        }
 
136
 
 
137
        /* Get rid of newline character. */
 
138
        buf_size = strlen (line);
 
139
        if (buf_size <= 0) {
 
140
                /* Huh? An empty string? */
 
141
                fclose (f);
 
142
                g_free (line);
 
143
                if (error)
 
144
                        *error = _MG_GBR_INIT_ERROR_INVALID_MAPS;
 
145
                return NULL;
 
146
        }
 
147
        if (line[buf_size - 1] == 10)
 
148
                line[buf_size - 1] = 0;
 
149
 
 
150
        /* Extract the filename; it is always an absolute path. */
 
151
        path = strchr (line, '/');
 
152
 
 
153
        /* Sanity check. */
 
154
        if (strstr (line, " r-xp ") == NULL || path == NULL) {
 
155
                fclose (f);
 
156
                g_free (line);
 
157
                if (error)
 
158
                        *error = _MG_GBR_INIT_ERROR_INVALID_MAPS;
 
159
                return NULL;
 
160
        }
 
161
 
 
162
        path = g_strdup (path);
 
163
        g_free (line);
 
164
        fclose (f);
 
165
        return path;
 
166
#endif /* ENABLE_BINRELOC */
 
167
}
 
168
 
 
169
 
 
170
/** @internal
 
171
 * Find the canonical filename of the executable which owns symbol.
 
172
 * Returns a filename which must be freed, or NULL on error.
 
173
 */
 
174
static char *
 
175
_br_find_exe_for_symbol (const void *symbol, GbrInitError *error)
 
176
{
 
177
#ifndef ENABLE_BINRELOC
 
178
        if (error)
 
179
                *error = _MG_GBR_INIT_ERROR_DISABLED;
 
180
        return (char *) NULL;
 
181
#else
 
182
        #define SIZE PATH_MAX + 100
 
183
        FILE *f;
 
184
        size_t address_string_len;
 
185
        char *address_string, line[SIZE], *found;
 
186
 
 
187
        if (symbol == NULL)
 
188
                return (char *) NULL;
 
189
 
 
190
        f = fopen ("/proc/self/maps", "r");
 
191
        if (f == NULL)
 
192
                return (char *) NULL;
 
193
 
 
194
        address_string_len = 4;
 
195
        address_string = (char *) g_try_malloc (address_string_len);
 
196
        found = (char *) NULL;
 
197
 
 
198
        while (!feof (f)) {
 
199
                char *start_addr, *end_addr, *end_addr_end, *file;
 
200
                void *start_addr_p, *end_addr_p;
 
201
                size_t len;
 
202
 
 
203
                if (fgets (line, SIZE, f) == NULL)
 
204
                        break;
 
205
 
 
206
                /* Sanity check. */
 
207
                if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
 
208
                        continue;
 
209
 
 
210
                /* Parse line. */
 
211
                start_addr = line;
 
212
                end_addr = strchr (line, '-');
 
213
                file = strchr (line, '/');
 
214
 
 
215
                /* More sanity check. */
 
216
                if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
 
217
                        continue;
 
218
 
 
219
                end_addr[0] = '\0';
 
220
                end_addr++;
 
221
                end_addr_end = strchr (end_addr, ' ');
 
222
                if (end_addr_end == NULL)
 
223
                        continue;
 
224
 
 
225
                end_addr_end[0] = '\0';
 
226
                len = strlen (file);
 
227
                if (len == 0)
 
228
                        continue;
 
229
                if (file[len - 1] == '\n')
 
230
                        file[len - 1] = '\0';
 
231
 
 
232
                /* Get rid of "(deleted)" from the filename. */
 
233
                len = strlen (file);
 
234
                if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
 
235
                        file[len - 10] = '\0';
 
236
 
 
237
                /* I don't know whether this can happen but better safe than sorry. */
 
238
                len = strlen (start_addr);
 
239
                if (len != strlen (end_addr))
 
240
                        continue;
 
241
 
 
242
 
 
243
                /* Transform the addresses into a string in the form of 0xdeadbeef,
 
244
                 * then transform that into a pointer. */
 
245
                if (address_string_len < len + 3) {
 
246
                        address_string_len = len + 3;
 
247
                        address_string = (char *) g_try_realloc (address_string, address_string_len);
 
248
                }
 
249
 
 
250
                memcpy (address_string, "0x", 2);
 
251
                memcpy (address_string + 2, start_addr, len);
 
252
                address_string[2 + len] = '\0';
 
253
                sscanf (address_string, "%p", &start_addr_p);
 
254
 
 
255
                memcpy (address_string, "0x", 2);
 
256
                memcpy (address_string + 2, end_addr, len);
 
257
                address_string[2 + len] = '\0';
 
258
                sscanf (address_string, "%p", &end_addr_p);
 
259
 
 
260
 
 
261
                if (symbol >= start_addr_p && symbol < end_addr_p) {
 
262
                        found = file;
 
263
                        break;
 
264
                }
 
265
        }
 
266
 
 
267
        g_free (address_string);
 
268
        fclose (f);
 
269
 
 
270
        if (found == NULL)
 
271
                return (char *) NULL;
 
272
        else
 
273
                return g_strdup (found);
 
274
#endif /* ENABLE_BINRELOC */
 
275
}
 
276
 
 
277
 
 
278
static gchar *exe = NULL;
 
279
 
 
280
static void set_gerror (GError **error, GbrInitError errcode);
 
281
 
 
282
 
 
283
/** Initialize the BinReloc library (for applications).
 
284
 *
 
285
 * This function must be called before using any other BinReloc functions.
 
286
 * It attempts to locate the application's canonical filename.
 
287
 *
 
288
 * @note If you want to use BinReloc for a library, then you should call
 
289
 *       _mg_gbr_init_lib() instead.
 
290
 *
 
291
 * @param error  If BinReloc failed to initialize, then the error report will
 
292
 *               be stored in this variable. Set to NULL if you don't want an
 
293
 *               error report. See the #GbrInitError for a list of error
 
294
 *               codes.
 
295
 *
 
296
 * @returns TRUE on success, FALSE if BinReloc failed to initialize.
 
297
 */
 
298
gboolean
 
299
_mg_gbr_init (GError **error)
 
300
{
 
301
        GbrInitError errcode;
 
302
 
 
303
        /* Locate the application's filename. */
 
304
        exe = _br_find_exe (&errcode);
 
305
        if (exe != NULL)
 
306
                /* Success! */
 
307
                return TRUE;
 
308
        else {
 
309
                /* Failed :-( */
 
310
                set_gerror (error, errcode);
 
311
                return FALSE;
 
312
        }
 
313
}
 
314
 
 
315
 
 
316
/** Initialize the BinReloc library (for libraries).
 
317
 *
 
318
 * This function must be called before using any other BinReloc functions.
 
319
 * It attempts to locate the calling library's canonical filename.
 
320
 *
 
321
 * @note The BinReloc source code MUST be included in your library, or this
 
322
 *       function won't work correctly.
 
323
 *
 
324
 * @returns TRUE on success, FALSE if a filename cannot be found.
 
325
 */
 
326
gboolean
 
327
_mg_gbr_init_lib (GError **error)
 
328
{
 
329
        GbrInitError errcode;
 
330
 
 
331
        exe = _br_find_exe_for_symbol ((const void *) "", &errcode);
 
332
        if (exe != NULL)
 
333
                /* Success! */
 
334
                return TRUE;
 
335
        else {
 
336
                /* Failed :-( */
 
337
                set_gerror (error, errcode);
 
338
                return exe != NULL;
 
339
        }
 
340
}
 
341
 
 
342
 
 
343
static void
 
344
set_gerror (GError **error, GbrInitError errcode)
 
345
{
 
346
        gchar *error_message;
 
347
 
 
348
        if (error == NULL)
 
349
                return;
 
350
 
 
351
        switch (errcode) {
 
352
        case _MG_GBR_INIT_ERROR_NOMEM:
 
353
                error_message = "Cannot allocate memory.";
 
354
                break;
 
355
        case _MG_GBR_INIT_ERROR_OPEN_MAPS:
 
356
                error_message = "Unable to open /proc/self/maps for reading.";
 
357
                break;
 
358
        case _MG_GBR_INIT_ERROR_READ_MAPS:
 
359
                error_message = "Unable to read from /proc/self/maps.";
 
360
                break;
 
361
        case _MG_GBR_INIT_ERROR_INVALID_MAPS:
 
362
                error_message = "The file format of /proc/self/maps is invalid.";
 
363
                break;
 
364
        case _MG_GBR_INIT_ERROR_DISABLED:
 
365
                error_message = "Binary relocation support is disabled.";
 
366
                break;
 
367
        default:
 
368
                error_message = "Unknown error.";
 
369
                break;
 
370
        };
 
371
        g_set_error (error, g_quark_from_static_string ("GBinReloc"),
 
372
                     errcode, "%s", error_message);
 
373
}
 
374
 
 
375
 
 
376
/** Find the canonical filename of the current application.
 
377
 *
 
378
 * @param default_exe  A default filename which will be used as fallback.
 
379
 * @returns A string containing the application's canonical filename,
 
380
 *          which must be freed when no longer necessary. If BinReloc is
 
381
 *          not initialized, or if the initialization function failed,
 
382
 *          then a copy of default_exe will be returned. If default_exe
 
383
 *          is NULL, then NULL will be returned.
 
384
 */
 
385
gchar *
 
386
_mg_gbr_find_exe (const gchar *default_exe)
 
387
{
 
388
        if (exe == NULL) {
 
389
                /* BinReloc is not initialized. */
 
390
                if (default_exe != NULL)
 
391
                        return g_strdup (default_exe);
 
392
                else
 
393
                        return NULL;
 
394
        }
 
395
        return g_strdup (exe);
 
396
}
 
397
 
 
398
 
 
399
/** Locate the directory in which the current application is installed.
 
400
 *
 
401
 * The prefix is generated by the following pseudo-code evaluation:
 
402
 * \code
 
403
 * dirname(exename)
 
404
 * \endcode
 
405
 *
 
406
 * @param default_dir  A default directory which will used as fallback.
 
407
 * @return A string containing the directory, which must be freed when no
 
408
 *         longer necessary. If BinReloc is not initialized, or if the
 
409
 *         initialization function failed, then a copy of default_dir
 
410
 *         will be returned. If default_dir is NULL, then NULL will be
 
411
 *         returned.
 
412
 */
 
413
gchar *
 
414
_mg_gbr_find_exe_dir (const gchar *default_dir)
 
415
{
 
416
        if (exe == NULL) {
 
417
                /* BinReloc not initialized. */
 
418
                if (default_dir != NULL)
 
419
                        return g_strdup (default_dir);
 
420
                else
 
421
                        return NULL;
 
422
        }
 
423
 
 
424
        return g_path_get_dirname (exe);
 
425
}
 
426
 
 
427
 
 
428
/** Locate the prefix in which the current application is installed.
 
429
 *
 
430
 * The prefix is generated by the following pseudo-code evaluation:
 
431
 * \code
 
432
 * dirname(dirname(exename))
 
433
 * \endcode
 
434
 *
 
435
 * @param default_prefix  A default prefix which will used as fallback.
 
436
 * @return A string containing the prefix, which must be freed when no
 
437
 *         longer necessary. If BinReloc is not initialized, or if the
 
438
 *         initialization function failed, then a copy of default_prefix
 
439
 *         will be returned. If default_prefix is NULL, then NULL will be
 
440
 *         returned.
 
441
 */
 
442
gchar *
 
443
_mg_gbr_find_prefix (const gchar *default_prefix)
 
444
{
 
445
        gchar *dir1, *dir2;
 
446
 
 
447
        if (exe == NULL) {
 
448
                /* BinReloc not initialized. */
 
449
                if (default_prefix != NULL)
 
450
                        return g_strdup (default_prefix);
 
451
                else
 
452
                        return NULL;
 
453
        }
 
454
 
 
455
        dir1 = g_path_get_dirname (exe);
 
456
        dir2 = g_path_get_dirname (dir1);
 
457
        g_free (dir1);
 
458
        return dir2;
 
459
}
 
460
 
 
461
 
 
462
/** Locate the application's binary folder.
 
463
 *
 
464
 * The path is generated by the following pseudo-code evaluation:
 
465
 * \code
 
466
 * prefix + "/bin"
 
467
 * \endcode
 
468
 *
 
469
 * @param default_bin_dir  A default path which will used as fallback.
 
470
 * @return A string containing the bin folder's path, which must be freed when
 
471
 *         no longer necessary. If BinReloc is not initialized, or if the
 
472
 *         initialization function failed, then a copy of default_bin_dir will
 
473
 *         be returned. If default_bin_dir is NULL, then NULL will be returned.
 
474
 */
 
475
gchar *
 
476
_mg_gbr_find_bin_dir (const gchar *default_bin_dir)
 
477
{
 
478
        gchar *prefix, *dir;
 
479
 
 
480
        prefix = _mg_gbr_find_prefix (NULL);
 
481
        if (prefix == NULL) {
 
482
                /* BinReloc not initialized. */
 
483
                if (default_bin_dir != NULL)
 
484
                        return g_strdup (default_bin_dir);
 
485
                else
 
486
                        return NULL;
 
487
        }
 
488
 
 
489
        dir = g_build_filename (prefix, "bin", NULL);
 
490
        g_free (prefix);
 
491
        return dir;
 
492
}
 
493
 
 
494
 
 
495
/** Locate the application's superuser binary folder.
 
496
 *
 
497
 * The path is generated by the following pseudo-code evaluation:
 
498
 * \code
 
499
 * prefix + "/sbin"
 
500
 * \endcode
 
501
 *
 
502
 * @param default_sbin_dir  A default path which will used as fallback.
 
503
 * @return A string containing the sbin folder's path, which must be freed when
 
504
 *         no longer necessary. If BinReloc is not initialized, or if the
 
505
 *         initialization function failed, then a copy of default_sbin_dir will
 
506
 *         be returned. If default_bin_dir is NULL, then NULL will be returned.
 
507
 */
 
508
gchar *
 
509
_mg_gbr_find_sbin_dir (const gchar *default_sbin_dir)
 
510
{
 
511
        gchar *prefix, *dir;
 
512
 
 
513
        prefix = _mg_gbr_find_prefix (NULL);
 
514
        if (prefix == NULL) {
 
515
                /* BinReloc not initialized. */
 
516
                if (default_sbin_dir != NULL)
 
517
                        return g_strdup (default_sbin_dir);
 
518
                else
 
519
                        return NULL;
 
520
        }
 
521
 
 
522
        dir = g_build_filename (prefix, "sbin", NULL);
 
523
        g_free (prefix);
 
524
        return dir;
 
525
}
 
526
 
 
527
 
 
528
/** Locate the application's data folder.
 
529
 *
 
530
 * The path is generated by the following pseudo-code evaluation:
 
531
 * \code
 
532
 * prefix + "/share"
 
533
 * \endcode
 
534
 *
 
535
 * @param default_data_dir  A default path which will used as fallback.
 
536
 * @return A string containing the data folder's path, which must be freed when
 
537
 *         no longer necessary. If BinReloc is not initialized, or if the
 
538
 *         initialization function failed, then a copy of default_data_dir
 
539
 *         will be returned. If default_data_dir is NULL, then NULL will be
 
540
 *         returned.
 
541
 */
 
542
gchar *
 
543
_mg_gbr_find_data_dir (const gchar *default_data_dir)
 
544
{
 
545
        gchar *prefix, *dir;
 
546
 
 
547
        prefix = _mg_gbr_find_prefix (NULL);
 
548
        if (prefix == NULL) {
 
549
                /* BinReloc not initialized. */
 
550
                if (default_data_dir != NULL)
 
551
                        return g_strdup (default_data_dir);
 
552
                else
 
553
                        return NULL;
 
554
        }
 
555
 
 
556
        dir = g_build_filename (prefix, "share", NULL);
 
557
        g_free (prefix);
 
558
        return dir;
 
559
}
 
560
 
 
561
 
 
562
/** Locate the application's localization folder.
 
563
 *
 
564
 * The path is generated by the following pseudo-code evaluation:
 
565
 * \code
 
566
 * prefix + "/share/locale"
 
567
 * \endcode
 
568
 *
 
569
 * @param default_locale_dir  A default path which will used as fallback.
 
570
 * @return A string containing the localization folder's path, which must be freed when
 
571
 *         no longer necessary. If BinReloc is not initialized, or if the
 
572
 *         initialization function failed, then a copy of default_locale_dir will be returned.
 
573
 *         If default_locale_dir is NULL, then NULL will be returned.
 
574
 */
 
575
gchar *
 
576
_mg_gbr_find_locale_dir (const gchar *default_locale_dir)
 
577
{
 
578
        gchar *data_dir, *dir;
 
579
 
 
580
        data_dir = _mg_gbr_find_data_dir (NULL);
 
581
        if (data_dir == NULL) {
 
582
                /* BinReloc not initialized. */
 
583
                if (default_locale_dir != NULL)
 
584
                        return g_strdup (default_locale_dir);
 
585
                else
 
586
                        return NULL;
 
587
        }
 
588
 
 
589
        dir = g_build_filename (data_dir, "locale", NULL);
 
590
        g_free (data_dir);
 
591
        return dir;
 
592
}
 
593
 
 
594
 
 
595
/** Locate the application's library folder.
 
596
 *
 
597
 * The path is generated by the following pseudo-code evaluation:
 
598
 * \code
 
599
 * prefix + "/lib"
 
600
 * \endcode
 
601
 *
 
602
 * @param default_lib_dir  A default path which will used as fallback.
 
603
 * @return A string containing the library folder's path, which must be freed when
 
604
 *         no longer necessary. If BinReloc is not initialized, or if the
 
605
 *         initialization function failed, then a copy of default_lib_dir will be returned.
 
606
 *         If default_lib_dir is NULL, then NULL will be returned.
 
607
 */
 
608
gchar *
 
609
_mg_gbr_find_lib_dir (const gchar *default_lib_dir)
 
610
{
 
611
        gchar *prefix, *dir;
 
612
 
 
613
        prefix = _mg_gbr_find_prefix (NULL);
 
614
        if (prefix == NULL) {
 
615
                /* BinReloc not initialized. */
 
616
                if (default_lib_dir != NULL)
 
617
                        return g_strdup (default_lib_dir);
 
618
                else
 
619
                        return NULL;
 
620
        }
 
621
 
 
622
        dir = g_build_filename (prefix, "lib", NULL);
 
623
        g_free (prefix);
 
624
        return dir;
 
625
}
 
626
 
 
627
 
 
628
/** Locate the application's libexec folder.
 
629
 *
 
630
 * The path is generated by the following pseudo-code evaluation:
 
631
 * \code
 
632
 * prefix + "/libexec"
 
633
 * \endcode
 
634
 *
 
635
 * @param default_libexec_dir  A default path which will used as fallback.
 
636
 * @return A string containing the libexec folder's path, which must be freed when
 
637
 *         no longer necessary. If BinReloc is not initialized, or if the initialization
 
638
 *         function failed, then a copy of default_libexec_dir will be returned.
 
639
 *         If default_libexec_dir is NULL, then NULL will be returned.
 
640
 */
 
641
gchar *
 
642
_mg_gbr_find_libexec_dir (const gchar *default_libexec_dir)
 
643
{
 
644
        gchar *prefix, *dir;
 
645
 
 
646
        prefix = _mg_gbr_find_prefix (NULL);
 
647
        if (prefix == NULL) {
 
648
                /* BinReloc not initialized. */
 
649
                if (default_libexec_dir != NULL)
 
650
                        return g_strdup (default_libexec_dir);
 
651
                else
 
652
                        return NULL;
 
653
        }
 
654
 
 
655
        dir = g_build_filename (prefix, "libexec", NULL);
 
656
        g_free (prefix);
 
657
        return dir;
 
658
}
 
659
 
 
660
 
 
661
/** Locate the application's configuration files folder.
 
662
 *
 
663
 * The path is generated by the following pseudo-code evaluation:
 
664
 * \code
 
665
 * prefix + "/etc"
 
666
 * \endcode
 
667
 *
 
668
 * @param default_etc_dir  A default path which will used as fallback.
 
669
 * @return A string containing the etc folder's path, which must be freed when
 
670
 *         no longer necessary. If BinReloc is not initialized, or if the initialization
 
671
 *         function failed, then a copy of default_etc_dir will be returned.
 
672
 *         If default_etc_dir is NULL, then NULL will be returned.
 
673
 */
 
674
gchar *
 
675
_mg_gbr_find_etc_dir (const gchar *default_etc_dir)
 
676
{
 
677
        gchar *prefix, *dir;
 
678
 
 
679
        prefix = _mg_gbr_find_prefix (NULL);
 
680
        if (prefix == NULL) {
 
681
                /* BinReloc not initialized. */
 
682
                if (default_etc_dir != NULL)
 
683
                        return g_strdup (default_etc_dir);
 
684
                else
 
685
                        return NULL;
 
686
        }
 
687
 
 
688
        dir = g_build_filename (prefix, "etc", NULL);
 
689
        g_free (prefix);
 
690
        return dir;
 
691
}
 
692
 
 
693
 
 
694
G_END_DECLS
 
695
 
 
696
#endif /* __BINRELOC_C__ */