Diff for /embedaddon/libiconv/libcharset/lib/relocatable.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 22:57:48 version 1.1.1.2, 2012/05/29 09:29:42
Line 1 Line 1
 /* Provide relocatable packages.  /* Provide relocatable packages.
   Copyright (C) 2003-2006, 2008 Free Software Foundation, Inc.   Copyright (C) 2003-2006, 2008-2011 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2003.     Written by Bruno Haible <bruno@clisp.org>, 2003.
   
    This program is free software; you can redistribute it and/or modify it     This program is free software; you can redistribute it and/or modify it
Line 22 Line 22
    This must come before <config.h> because <config.h> may include     This must come before <config.h> because <config.h> may include
    <features.h>, and once <features.h> has been included, it's too late.  */     <features.h>, and once <features.h> has been included, it's too late.  */
 #ifndef _GNU_SOURCE  #ifndef _GNU_SOURCE
# define _GNU_SOURCE    1# define _GNU_SOURCE 1
 #endif  #endif
   
   #define _GL_USE_STDLIB_ALLOC 1
 #include <config.h>  #include <config.h>
   
 /* Specification.  */  /* Specification.  */
Line 43 Line 44
 # include "xalloc.h"  # include "xalloc.h"
 #endif  #endif
   
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
 # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
 # include <windows.h>  # include <windows.h>
 #endif  #endif
Line 70 Line 71
    ISSLASH(C)           tests whether C is a directory separator character.     ISSLASH(C)           tests whether C is a directory separator character.
    IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.     IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
  */   */
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__#if ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
  /* Win32, Cygwin, OS/2, DOS */  /* Win32, OS/2, DOS */
 # define ISSLASH(C) ((C) == '/' || (C) == '\\')  # define ISSLASH(C) ((C) == '/' || (C) == '\\')
 # define HAS_DEVICE(P) \  # define HAS_DEVICE(P) \
     ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \      ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
Line 102  static size_t curr_prefix_len; Line 103  static size_t curr_prefix_len;
    instead of "/").  */     instead of "/").  */
 static void  static void
 set_this_relocation_prefix (const char *orig_prefix_arg,  set_this_relocation_prefix (const char *orig_prefix_arg,
                            const char *curr_prefix_arg)                            const char *curr_prefix_arg)
 {  {
   if (orig_prefix_arg != NULL && curr_prefix_arg != NULL    if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
       /* Optimization: if orig_prefix and curr_prefix are equal, the        /* Optimization: if orig_prefix and curr_prefix are equal, the
         relocation is a nop.  */         relocation is a nop.  */
       && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)        && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
     {      {
       /* Duplicate the argument strings.  */        /* Duplicate the argument strings.  */
Line 118  set_this_relocation_prefix (const char *orig_prefix_ar Line 119  set_this_relocation_prefix (const char *orig_prefix_ar
 #ifdef NO_XMALLOC  #ifdef NO_XMALLOC
       if (memory != NULL)        if (memory != NULL)
 #endif  #endif
        {        {
          memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);          memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
          orig_prefix = memory;          orig_prefix = memory;
          memory += orig_prefix_len + 1;          memory += orig_prefix_len + 1;
          memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);          memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
          curr_prefix = memory;          curr_prefix = memory;
          return;          return;
        }        }
     }      }
   orig_prefix = NULL;    orig_prefix = NULL;
   curr_prefix = NULL;    curr_prefix = NULL;
Line 168  static Line 169  static
 #endif  #endif
 char *  char *
 compute_curr_prefix (const char *orig_installprefix,  compute_curr_prefix (const char *orig_installprefix,
                     const char *orig_installdir,                     const char *orig_installdir,
                     const char *curr_pathname)                     const char *curr_pathname)
 {  {
   char *curr_installdir;    char *curr_installdir;
   const char *rel_installdir;    const char *rel_installdir;
Line 194  compute_curr_prefix (const char *orig_installprefix, Line 195  compute_curr_prefix (const char *orig_installprefix,
   
     while (p > p_base)      while (p > p_base)
       {        {
        p--;        p--;
        if (ISSLASH (*p))        if (ISSLASH (*p))
          break;          break;
       }        }
   
     q = (char *) xmalloc (p - curr_pathname + 1);      q = (char *) xmalloc (p - curr_pathname + 1);
Line 219  compute_curr_prefix (const char *orig_installprefix, Line 220  compute_curr_prefix (const char *orig_installprefix,
   
     while (rp > rel_installdir && cp > cp_base)      while (rp > rel_installdir && cp > cp_base)
       {        {
        bool same = false;        bool same = false;
        const char *rpi = rp;        const char *rpi = rp;
        const char *cpi = cp;        const char *cpi = cp;
   
        while (rpi > rel_installdir && cpi > cp_base)        while (rpi > rel_installdir && cpi > cp_base)
          {          {
            rpi--;            rpi--;
            cpi--;            cpi--;
            if (ISSLASH (*rpi) || ISSLASH (*cpi))            if (ISSLASH (*rpi) || ISSLASH (*cpi))
              {              {
                if (ISSLASH (*rpi) && ISSLASH (*cpi))                if (ISSLASH (*rpi) && ISSLASH (*cpi))
                  same = true;                  same = true;
                break;                break;
              }              }
            /* Do case-insensitive comparison if the filesystem is always or            /* Do case-insensitive comparison if the file system is always or
               often case-insensitive.  It's better to accept the comparison               often case-insensitive.  It's better to accept the comparison
               if the difference is only in case, rather than to fail.  */               if the difference is only in case, rather than to fail.  */
 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__  #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
            /* Win32, Cygwin, OS/2, DOS - case insignificant filesystem */            /* Win32, Cygwin, OS/2, DOS - case insignificant file system */
            if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)            if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
                != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))                != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
              break;              break;
 #else  #else
            if (*rpi != *cpi)            if (*rpi != *cpi)
              break;              break;
 #endif  #endif
          }          }
        if (!same)        if (!same)
          break;          break;
        /* The last pathname component was the same.  opi and cpi now point        /* The last pathname component was the same.  opi and cpi now point
           to the slash before it.  */           to the slash before it.  */
        rp = rpi;        rp = rpi;
        cp = cpi;        cp = cpi;
       }        }
   
     if (rp > rel_installdir)      if (rp > rel_installdir)
       {        {
        /* Unexpected: The curr_installdir does not end with rel_installdir.  */        /* Unexpected: The curr_installdir does not end with rel_installdir.  */
        free (curr_installdir);        free (curr_installdir);
        return NULL;        return NULL;
       }        }
   
     {      {
Line 268  compute_curr_prefix (const char *orig_installprefix, Line 269  compute_curr_prefix (const char *orig_installprefix,
       curr_prefix = (char *) xmalloc (curr_prefix_len + 1);        curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
 #ifdef NO_XMALLOC  #ifdef NO_XMALLOC
       if (curr_prefix == NULL)        if (curr_prefix == NULL)
        {        {
          free (curr_installdir);          free (curr_installdir);
          return NULL;          return NULL;
        }        }
 #endif  #endif
       memcpy (curr_prefix, curr_installdir, curr_prefix_len);        memcpy (curr_prefix, curr_installdir, curr_prefix_len);
       curr_prefix[curr_prefix_len] = '\0';        curr_prefix[curr_prefix_len] = '\0';
Line 290  compute_curr_prefix (const char *orig_installprefix, Line 291  compute_curr_prefix (const char *orig_installprefix,
 /* Full pathname of shared library, or NULL.  */  /* Full pathname of shared library, or NULL.  */
 static char *shared_library_fullname;  static char *shared_library_fullname;
   
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
 /* Native Win32 only.
    On Cygwin, it is better to use the Cygwin provided /proc interface, than
    to use native Win32 API and cygwin_conv_to_posix_path, because it supports
    longer file names
    (see <http://cygwin.com/ml/cygwin/2011-01/msg00410.html>).  */
   
 /* Determine the full pathname of the shared library when it is loaded.  */  /* Determine the full pathname of the shared library when it is loaded.  */
   
Line 305  DllMain (HINSTANCE module_handle, DWORD event, LPVOID  Line 311  DllMain (HINSTANCE module_handle, DWORD event, LPVOID 
       static char location[MAX_PATH];        static char location[MAX_PATH];
   
       if (!GetModuleFileName (module_handle, location, sizeof (location)))        if (!GetModuleFileName (module_handle, location, sizeof (location)))
        /* Shouldn't happen.  */        /* Shouldn't happen.  */
        return FALSE;        return FALSE;
   
       if (!IS_PATH_WITH_DIR (location))        if (!IS_PATH_WITH_DIR (location))
        /* Shouldn't happen.  */        /* Shouldn't happen.  */
        return FALSE;        return FALSE;
   
      {      shared_library_fullname = strdup (location);
#if defined __CYGWIN__ 
        /* On Cygwin, we need to convert paths coming from Win32 system calls 
           to the Unix-like slashified notation.  */ 
        static char location_as_posix_path[2 * MAX_PATH]; 
        /* There's no error return defined for cygwin_conv_to_posix_path. 
           See cygwin-api/func-cygwin-conv-to-posix-path.html. 
           Does it overflow the buffer of expected size MAX_PATH or does it 
           truncate the path?  I don't know.  Let's catch both.  */ 
        cygwin_conv_to_posix_path (location, location_as_posix_path); 
        location_as_posix_path[MAX_PATH - 1] = '\0'; 
        if (strlen (location_as_posix_path) >= MAX_PATH - 1) 
          /* A sign of buffer overflow or path truncation.  */ 
          return FALSE; 
        shared_library_fullname = strdup (location_as_posix_path); 
#else 
        shared_library_fullname = strdup (location); 
#endif 
      } 
     }      }
   
   return TRUE;    return TRUE;
 }  }
   
#else /* Unix except Cygwin */#else /* Unix */
   
 static void  static void
 find_shared_library_fullname ()  find_shared_library_fullname ()
 {  {
#if defined __linux__ && __GLIBC__ >= 2#if (defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__
  /* Linux has /proc/self/maps. glibc 2 has the getline() function.  */  /* Linux has /proc/self/maps. glibc 2 and uClibc have the getline()
      function.
      Cygwin >= 1.5 has /proc/self/maps and the getline() function too.  */
   FILE *fp;    FILE *fp;
   
   /* Open the current process' maps file.  It describes one VMA per line.  */    /* Open the current process' maps file.  It describes one VMA per line.  */
Line 351  find_shared_library_fullname () Line 341  find_shared_library_fullname ()
     {      {
       unsigned long address = (unsigned long) &find_shared_library_fullname;        unsigned long address = (unsigned long) &find_shared_library_fullname;
       for (;;)        for (;;)
        {        {
          unsigned long start, end;          unsigned long start, end;
          int c;          int c;
   
          if (fscanf (fp, "%lx-%lx", &start, &end) != 2)          if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
            break;            break;
          if (address >= start && address <= end - 1)          if (address >= start && address <= end - 1)
            {            {
              /* Found it.  Now see if this line contains a filename.  */              /* Found it.  Now see if this line contains a filename.  */
              while (c = getc (fp), c != EOF && c != '\n' && c != '/')              while (c = getc (fp), c != EOF && c != '\n' && c != '/')
                continue;                continue;
              if (c == '/')              if (c == '/')
                {                {
                  size_t size;                  size_t size;
                  int len;                  int len;
   
                  ungetc (c, fp);                  ungetc (c, fp);
                  shared_library_fullname = NULL; size = 0;                  shared_library_fullname = NULL; size = 0;
                  len = getline (&shared_library_fullname, &size, fp);                  len = getline (&shared_library_fullname, &size, fp);
                  if (len >= 0)                  if (len >= 0)
                    {                    {
                      /* Success: filled shared_library_fullname.  */                      /* Success: filled shared_library_fullname.  */
                      if (len > 0 && shared_library_fullname[len - 1] == '\n')                      if (len > 0 && shared_library_fullname[len - 1] == '\n')
                        shared_library_fullname[len - 1] = '\0';                        shared_library_fullname[len - 1] = '\0';
                    }                    }
                }                }
              break;              break;
            }            }
          while (c = getc (fp), c != EOF && c != '\n')          while (c = getc (fp), c != EOF && c != '\n')
            continue;            continue;
        }        }
       fclose (fp);        fclose (fp);
     }      }
 #endif  #endif
 }  }
   
#endif /* (WIN32 or Cygwin) / (Unix except Cygwin) */#endif /* WIN32 / Unix */
   
 /* Return the full pathname of the current shared library.  /* Return the full pathname of the current shared library.
    Return NULL if unknown.     Return NULL if unknown.
Line 395  find_shared_library_fullname () Line 385  find_shared_library_fullname ()
 static char *  static char *
 get_shared_library_fullname ()  get_shared_library_fullname ()
 {  {
#if !(defined _WIN32 || defined __WIN32__ || defined __CYGWIN__)#if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
   static bool tried_find_shared_library_fullname;    static bool tried_find_shared_library_fullname;
   if (!tried_find_shared_library_fullname)    if (!tried_find_shared_library_fullname)
     {      {
Line 422  relocate (const char *pathname) Line 412  relocate (const char *pathname)
   if (!initialized)    if (!initialized)
     {      {
       /* At this point, orig_prefix and curr_prefix likely have already been        /* At this point, orig_prefix and curr_prefix likely have already been
         set through the main program's set_program_name_and_installdir         set through the main program's set_program_name_and_installdir
         function.  This is sufficient in the case that the library has         function.  This is sufficient in the case that the library has
         initially been installed in the same orig_prefix.  But we can do         initially been installed in the same orig_prefix.  But we can do
         better, to also cover the cases that 1. it has been installed         better, to also cover the cases that 1. it has been installed
         in a different prefix before being moved to orig_prefix and (later)         in a different prefix before being moved to orig_prefix and (later)
         to curr_prefix, 2. unlike the program, it has not moved away from         to curr_prefix, 2. unlike the program, it has not moved away from
         orig_prefix.  */         orig_prefix.  */
       const char *orig_installprefix = INSTALLPREFIX;        const char *orig_installprefix = INSTALLPREFIX;
       const char *orig_installdir = INSTALLDIR;        const char *orig_installdir = INSTALLDIR;
       char *curr_prefix_better;        char *curr_prefix_better;
   
       curr_prefix_better =        curr_prefix_better =
        compute_curr_prefix (orig_installprefix, orig_installdir,        compute_curr_prefix (orig_installprefix, orig_installdir,
                             get_shared_library_fullname ());                             get_shared_library_fullname ());
   
       set_relocation_prefix (orig_installprefix,        set_relocation_prefix (orig_installprefix,
                             curr_prefix_better != NULL                             curr_prefix_better != NULL
                             ? curr_prefix_better                             ? curr_prefix_better
                             : curr_prefix);                             : curr_prefix);
   
       if (curr_prefix_better != NULL)        if (curr_prefix_better != NULL)
        free (curr_prefix_better);        free (curr_prefix_better);
   
       initialized = 1;        initialized = 1;
     }      }
 #endif  #endif
   
   /* Note: It is not necessary to perform case insensitive comparison here,    /* Note: It is not necessary to perform case insensitive comparison here,
     even for DOS-like filesystems, because the pathname argument was     even for DOS-like file systems, because the pathname argument was
      typically created from the same Makefile variable as orig_prefix came       typically created from the same Makefile variable as orig_prefix came
      from.  */       from.  */
   if (orig_prefix != NULL && curr_prefix != NULL    if (orig_prefix != NULL && curr_prefix != NULL
       && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)        && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
     {      {
       if (pathname[orig_prefix_len] == '\0')        if (pathname[orig_prefix_len] == '\0')
        {        {
          /* pathname equals orig_prefix.  */          /* pathname equals orig_prefix.  */
          char *result = (char *) xmalloc (strlen (curr_prefix) + 1);          char *result = (char *) xmalloc (strlen (curr_prefix) + 1);
   
 #ifdef NO_XMALLOC  #ifdef NO_XMALLOC
          if (result != NULL)          if (result != NULL)
 #endif  #endif
            {            {
              strcpy (result, curr_prefix);              strcpy (result, curr_prefix);
              return result;              return result;
            }            }
        }        }
       else if (ISSLASH (pathname[orig_prefix_len]))        else if (ISSLASH (pathname[orig_prefix_len]))
        {        {
          /* pathname starts with orig_prefix.  */          /* pathname starts with orig_prefix.  */
          const char *pathname_tail = &pathname[orig_prefix_len];          const char *pathname_tail = &pathname[orig_prefix_len];
          char *result =          char *result =
            (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);            (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
   
 #ifdef NO_XMALLOC  #ifdef NO_XMALLOC
          if (result != NULL)          if (result != NULL)
 #endif  #endif
            {            {
              memcpy (result, curr_prefix, curr_prefix_len);              memcpy (result, curr_prefix, curr_prefix_len);
              strcpy (result + curr_prefix_len, pathname_tail);              strcpy (result + curr_prefix_len, pathname_tail);
              return result;              return result;
            }            }
        }        }
     }      }
   /* Nothing to relocate.  */    /* Nothing to relocate.  */
   return pathname;    return pathname;

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>