~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Externals/libiconv-1.14/lib/relocatable.c

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Provide relocatable packages.
 
2
   Copyright (C) 2003-2006, 2008-2011 Free Software Foundation, Inc.
 
3
   Written by Bruno Haible <bruno@clisp.org>, 2003.
 
4
 
 
5
   This program is free software; you can redistribute it and/or modify it
 
6
   under the terms of the GNU Library General Public License as published
 
7
   by the Free Software Foundation; either version 2, or (at your option)
 
8
   any later version.
 
9
 
 
10
   This program is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
   Library General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU Library General Public
 
16
   License along with this program; if not, write to the Free Software
 
17
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
18
   USA.  */
 
19
 
 
20
 
 
21
/* Tell glibc's <stdio.h> to provide a prototype for getline().
 
22
   This must come before <config.h> because <config.h> may include
 
23
   <features.h>, and once <features.h> has been included, it's too late.  */
 
24
#ifndef _GNU_SOURCE
 
25
# define _GNU_SOURCE 1
 
26
#endif
 
27
 
 
28
#define _GL_USE_STDLIB_ALLOC 1
 
29
#include "config.h"
 
30
 
 
31
/* Specification.  */
 
32
#include "relocatable.h"
 
33
 
 
34
#if ENABLE_RELOCATABLE
 
35
 
 
36
#include <stddef.h>
 
37
#include <stdio.h>
 
38
#include <stdlib.h>
 
39
#include <string.h>
 
40
 
 
41
#ifdef NO_XMALLOC
 
42
# define xmalloc malloc
 
43
#else
 
44
# include "xalloc.h"
 
45
#endif
 
46
 
 
47
#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
 
48
# define WIN32_LEAN_AND_MEAN
 
49
# include <windows.h>
 
50
#endif
 
51
 
 
52
#if DEPENDS_ON_LIBCHARSET
 
53
# include <libcharset.h>
 
54
#endif
 
55
#if DEPENDS_ON_LIBICONV && HAVE_ICONV
 
56
# include <iconv.h>
 
57
#endif
 
58
#if DEPENDS_ON_LIBINTL && ENABLE_NLS
 
59
# include <libintl.h>
 
60
#endif
 
61
 
 
62
/* Faked cheap 'bool'.  */
 
63
#undef bool
 
64
#undef false
 
65
#undef true
 
66
#define bool int
 
67
#define false 0
 
68
#define true 1
 
69
 
 
70
/* Pathname support.
 
71
   ISSLASH(C)           tests whether C is a directory separator character.
 
72
   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
 
73
 */
 
74
#if ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
 
75
  /* Win32, OS/2, DOS */
 
76
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
 
77
# define HAS_DEVICE(P) \
 
78
    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
 
79
     && (P)[1] == ':')
 
80
# define IS_PATH_WITH_DIR(P) \
 
81
    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
 
82
# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
 
83
#else
 
84
  /* Unix */
 
85
# define ISSLASH(C) ((C) == '/')
 
86
# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
 
87
# define FILE_SYSTEM_PREFIX_LEN(P) 0
 
88
#endif
 
89
 
 
90
/* Original installation prefix.  */
 
91
static char *orig_prefix;
 
92
static size_t orig_prefix_len;
 
93
/* Current installation prefix.  */
 
94
static char *curr_prefix;
 
95
static size_t curr_prefix_len;
 
96
/* These prefixes do not end in a slash.  Anything that will be concatenated
 
97
   to them must start with a slash.  */
 
98
 
 
99
/* Sets the original and the current installation prefix of this module.
 
100
   Relocation simply replaces a pathname starting with the original prefix
 
101
   by the corresponding pathname with the current prefix instead.  Both
 
102
   prefixes should be directory names without trailing slash (i.e. use ""
 
103
   instead of "/").  */
 
104
static void
 
105
set_this_relocation_prefix (const char *orig_prefix_arg,
 
106
                            const char *curr_prefix_arg)
 
107
{
 
108
  if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
 
109
      /* Optimization: if orig_prefix and curr_prefix are equal, the
 
110
         relocation is a nop.  */
 
111
      && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
 
112
    {
 
113
      /* Duplicate the argument strings.  */
 
114
      char *memory;
 
115
 
 
116
      orig_prefix_len = strlen (orig_prefix_arg);
 
117
      curr_prefix_len = strlen (curr_prefix_arg);
 
118
      memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
 
119
#ifdef NO_XMALLOC
 
120
      if (memory != NULL)
 
121
#endif
 
122
        {
 
123
          memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
 
124
          orig_prefix = memory;
 
125
          memory += orig_prefix_len + 1;
 
126
          memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
 
127
          curr_prefix = memory;
 
128
          return;
 
129
        }
 
130
    }
 
131
  orig_prefix = NULL;
 
132
  curr_prefix = NULL;
 
133
  /* Don't worry about wasted memory here - this function is usually only
 
134
     called once.  */
 
135
}
 
136
 
 
137
/* Sets the original and the current installation prefix of the package.
 
138
   Relocation simply replaces a pathname starting with the original prefix
 
139
   by the corresponding pathname with the current prefix instead.  Both
 
140
   prefixes should be directory names without trailing slash (i.e. use ""
 
141
   instead of "/").  */
 
142
void
 
143
set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
 
144
{
 
145
  set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
 
146
 
 
147
  /* Now notify all dependent libraries.  */
 
148
#if DEPENDS_ON_LIBCHARSET
 
149
  libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
 
150
#endif
 
151
#if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
 
152
  libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
 
153
#endif
 
154
#if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
 
155
  libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
 
156
#endif
 
157
}
 
158
 
 
159
#if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR)
 
160
 
 
161
/* Convenience function:
 
162
   Computes the current installation prefix, based on the original
 
163
   installation prefix, the original installation directory of a particular
 
164
   file, and the current pathname of this file.
 
165
   Returns it, freshly allocated.  Returns NULL upon failure.  */
 
166
#ifdef IN_LIBRARY
 
167
#define compute_curr_prefix local_compute_curr_prefix
 
168
static
 
169
#endif
 
170
char *
 
171
compute_curr_prefix (const char *orig_installprefix,
 
172
                     const char *orig_installdir,
 
173
                     const char *curr_pathname)
 
174
{
 
175
  char *curr_installdir;
 
176
  const char *rel_installdir;
 
177
 
 
178
  if (curr_pathname == NULL)
 
179
    return NULL;
 
180
 
 
181
  /* Determine the relative installation directory, relative to the prefix.
 
182
     This is simply the difference between orig_installprefix and
 
183
     orig_installdir.  */
 
184
  if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
 
185
      != 0)
 
186
    /* Shouldn't happen - nothing should be installed outside $(prefix).  */
 
187
    return NULL;
 
188
  rel_installdir = orig_installdir + strlen (orig_installprefix);
 
189
 
 
190
  /* Determine the current installation directory.  */
 
191
  {
 
192
    const char *p_base = curr_pathname + FILE_SYSTEM_PREFIX_LEN (curr_pathname);
 
193
    const char *p = curr_pathname + strlen (curr_pathname);
 
194
    char *q;
 
195
 
 
196
    while (p > p_base)
 
197
      {
 
198
        p--;
 
199
        if (ISSLASH (*p))
 
200
          break;
 
201
      }
 
202
 
 
203
    q = (char *) xmalloc (p - curr_pathname + 1);
 
204
#ifdef NO_XMALLOC
 
205
    if (q == NULL)
 
206
      return NULL;
 
207
#endif
 
208
    memcpy (q, curr_pathname, p - curr_pathname);
 
209
    q[p - curr_pathname] = '\0';
 
210
    curr_installdir = q;
 
211
  }
 
212
 
 
213
  /* Compute the current installation prefix by removing the trailing
 
214
     rel_installdir from it.  */
 
215
  {
 
216
    const char *rp = rel_installdir + strlen (rel_installdir);
 
217
    const char *cp = curr_installdir + strlen (curr_installdir);
 
218
    const char *cp_base =
 
219
      curr_installdir + FILE_SYSTEM_PREFIX_LEN (curr_installdir);
 
220
 
 
221
    while (rp > rel_installdir && cp > cp_base)
 
222
      {
 
223
        bool same = false;
 
224
        const char *rpi = rp;
 
225
        const char *cpi = cp;
 
226
 
 
227
        while (rpi > rel_installdir && cpi > cp_base)
 
228
          {
 
229
            rpi--;
 
230
            cpi--;
 
231
            if (ISSLASH (*rpi) || ISSLASH (*cpi))
 
232
              {
 
233
                if (ISSLASH (*rpi) && ISSLASH (*cpi))
 
234
                  same = true;
 
235
                break;
 
236
              }
 
237
            /* Do case-insensitive comparison if the file system is always or
 
238
               often case-insensitive.  It's better to accept the comparison
 
239
               if the difference is only in case, rather than to fail.  */
 
240
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
 
241
            /* Win32, Cygwin, OS/2, DOS - case insignificant file system */
 
242
            if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
 
243
                != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
 
244
              break;
 
245
#else
 
246
            if (*rpi != *cpi)
 
247
              break;
 
248
#endif
 
249
          }
 
250
        if (!same)
 
251
          break;
 
252
        /* The last pathname component was the same.  opi and cpi now point
 
253
           to the slash before it.  */
 
254
        rp = rpi;
 
255
        cp = cpi;
 
256
      }
 
257
 
 
258
    if (rp > rel_installdir)
 
259
      {
 
260
        /* Unexpected: The curr_installdir does not end with rel_installdir.  */
 
261
        free (curr_installdir);
 
262
        return NULL;
 
263
      }
 
264
 
 
265
    {
 
266
      size_t curr_prefix_len = cp - curr_installdir;
 
267
      char *curr_prefix;
 
268
 
 
269
      curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
 
270
#ifdef NO_XMALLOC
 
271
      if (curr_prefix == NULL)
 
272
        {
 
273
          free (curr_installdir);
 
274
          return NULL;
 
275
        }
 
276
#endif
 
277
      memcpy (curr_prefix, curr_installdir, curr_prefix_len);
 
278
      curr_prefix[curr_prefix_len] = '\0';
 
279
 
 
280
      free (curr_installdir);
 
281
 
 
282
      return curr_prefix;
 
283
    }
 
284
  }
 
285
}
 
286
 
 
287
#endif /* !IN_LIBRARY || PIC */
 
288
 
 
289
#if defined PIC && defined INSTALLDIR
 
290
 
 
291
/* Full pathname of shared library, or NULL.  */
 
292
static char *shared_library_fullname;
 
293
 
 
294
#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
 
295
/* Native Win32 only.
 
296
   On Cygwin, it is better to use the Cygwin provided /proc interface, than
 
297
   to use native Win32 API and cygwin_conv_to_posix_path, because it supports
 
298
   longer file names
 
299
   (see <http://cygwin.com/ml/cygwin/2011-01/msg00410.html>).  */
 
300
 
 
301
/* Determine the full pathname of the shared library when it is loaded.  */
 
302
 
 
303
BOOL WINAPI
 
304
DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
 
305
{
 
306
  (void) reserved;
 
307
 
 
308
  if (event == DLL_PROCESS_ATTACH)
 
309
    {
 
310
      /* The DLL is being loaded into an application's address range.  */
 
311
      static char location[MAX_PATH];
 
312
 
 
313
      if (!GetModuleFileName (module_handle, location, sizeof (location)))
 
314
        /* Shouldn't happen.  */
 
315
        return FALSE;
 
316
 
 
317
      if (!IS_PATH_WITH_DIR (location))
 
318
        /* Shouldn't happen.  */
 
319
        return FALSE;
 
320
 
 
321
      shared_library_fullname = strdup (location);
 
322
    }
 
323
 
 
324
  return TRUE;
 
325
}
 
326
 
 
327
#else /* Unix */
 
328
 
 
329
static void
 
330
find_shared_library_fullname ()
 
331
{
 
332
#if (defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__
 
333
  /* Linux has /proc/self/maps. glibc 2 and uClibc have the getline()
 
334
     function.
 
335
     Cygwin >= 1.5 has /proc/self/maps and the getline() function too.  */
 
336
  FILE *fp;
 
337
 
 
338
  /* Open the current process' maps file.  It describes one VMA per line.  */
 
339
  fp = fopen ("/proc/self/maps", "r");
 
340
  if (fp)
 
341
    {
 
342
      unsigned long address = (unsigned long) &find_shared_library_fullname;
 
343
      for (;;)
 
344
        {
 
345
          unsigned long start, end;
 
346
          int c;
 
347
 
 
348
          if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
 
349
            break;
 
350
          if (address >= start && address <= end - 1)
 
351
            {
 
352
              /* Found it.  Now see if this line contains a filename.  */
 
353
              while (c = getc (fp), c != EOF && c != '\n' && c != '/')
 
354
                continue;
 
355
              if (c == '/')
 
356
                {
 
357
                  size_t size;
 
358
                  int len;
 
359
 
 
360
                  ungetc (c, fp);
 
361
                  shared_library_fullname = NULL; size = 0;
 
362
                  len = getline (&shared_library_fullname, &size, fp);
 
363
                  if (len >= 0)
 
364
                    {
 
365
                      /* Success: filled shared_library_fullname.  */
 
366
                      if (len > 0 && shared_library_fullname[len - 1] == '\n')
 
367
                        shared_library_fullname[len - 1] = '\0';
 
368
                    }
 
369
                }
 
370
              break;
 
371
            }
 
372
          while (c = getc (fp), c != EOF && c != '\n')
 
373
            continue;
 
374
        }
 
375
      fclose (fp);
 
376
    }
 
377
#endif
 
378
}
 
379
 
 
380
#endif /* WIN32 / Unix */
 
381
 
 
382
/* Return the full pathname of the current shared library.
 
383
   Return NULL if unknown.
 
384
   Guaranteed to work only on Linux, Cygwin and Woe32.  */
 
385
static char *
 
386
get_shared_library_fullname ()
 
387
{
 
388
#if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
 
389
  static bool tried_find_shared_library_fullname;
 
390
  if (!tried_find_shared_library_fullname)
 
391
    {
 
392
      find_shared_library_fullname ();
 
393
      tried_find_shared_library_fullname = true;
 
394
    }
 
395
#endif
 
396
  return shared_library_fullname;
 
397
}
 
398
 
 
399
#endif /* PIC */
 
400
 
 
401
/* Returns the pathname, relocated according to the current installation
 
402
   directory.
 
403
   The returned string is either PATHNAME unmodified or a freshly allocated
 
404
   string that you can free with free() after casting it to 'char *'.  */
 
405
const char *
 
406
relocate (const char *pathname)
 
407
{
 
408
#if defined PIC && defined INSTALLDIR
 
409
  static int initialized;
 
410
 
 
411
  /* Initialization code for a shared library.  */
 
412
  if (!initialized)
 
413
    {
 
414
      /* At this point, orig_prefix and curr_prefix likely have already been
 
415
         set through the main program's set_program_name_and_installdir
 
416
         function.  This is sufficient in the case that the library has
 
417
         initially been installed in the same orig_prefix.  But we can do
 
418
         better, to also cover the cases that 1. it has been installed
 
419
         in a different prefix before being moved to orig_prefix and (later)
 
420
         to curr_prefix, 2. unlike the program, it has not moved away from
 
421
         orig_prefix.  */
 
422
      const char *orig_installprefix = INSTALLPREFIX;
 
423
      const char *orig_installdir = INSTALLDIR;
 
424
      char *curr_prefix_better;
 
425
 
 
426
      curr_prefix_better =
 
427
        compute_curr_prefix (orig_installprefix, orig_installdir,
 
428
                             get_shared_library_fullname ());
 
429
 
 
430
      set_relocation_prefix (orig_installprefix,
 
431
                             curr_prefix_better != NULL
 
432
                             ? curr_prefix_better
 
433
                             : curr_prefix);
 
434
 
 
435
      if (curr_prefix_better != NULL)
 
436
        free (curr_prefix_better);
 
437
 
 
438
      initialized = 1;
 
439
    }
 
440
#endif
 
441
 
 
442
  /* Note: It is not necessary to perform case insensitive comparison here,
 
443
     even for DOS-like file systems, because the pathname argument was
 
444
     typically created from the same Makefile variable as orig_prefix came
 
445
     from.  */
 
446
  if (orig_prefix != NULL && curr_prefix != NULL
 
447
      && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
 
448
    {
 
449
      if (pathname[orig_prefix_len] == '\0')
 
450
        {
 
451
          /* pathname equals orig_prefix.  */
 
452
          char *result = (char *) xmalloc (strlen (curr_prefix) + 1);
 
453
 
 
454
#ifdef NO_XMALLOC
 
455
          if (result != NULL)
 
456
#endif
 
457
            {
 
458
              strcpy (result, curr_prefix);
 
459
              return result;
 
460
            }
 
461
        }
 
462
      else if (ISSLASH (pathname[orig_prefix_len]))
 
463
        {
 
464
          /* pathname starts with orig_prefix.  */
 
465
          const char *pathname_tail = &pathname[orig_prefix_len];
 
466
          char *result =
 
467
            (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
 
468
 
 
469
#ifdef NO_XMALLOC
 
470
          if (result != NULL)
 
471
#endif
 
472
            {
 
473
              memcpy (result, curr_prefix, curr_prefix_len);
 
474
              strcpy (result + curr_prefix_len, pathname_tail);
 
475
              return result;
 
476
            }
 
477
        }
 
478
    }
 
479
  /* Nothing to relocate.  */
 
480
  return pathname;
 
481
}
 
482
 
 
483
#endif