Diff for /embedaddon/libiconv/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:43
Line 1 Line 1
 /* Provide relocatable packages.  /* Provide relocatable packages.
   Copyright (C) 2003-2006 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 160  set_relocation_prefix (const char *orig_prefix_arg, co Line 161  set_relocation_prefix (const char *orig_prefix_arg, co
 /* Convenience function:  /* Convenience function:
    Computes the current installation prefix, based on the original     Computes the current installation prefix, based on the original
    installation prefix, the original installation directory of a particular     installation prefix, the original installation directory of a particular
   file, and the current pathname of this file.  Returns NULL upon failure.  */   file, and the current pathname of this file.
    Returns it, freshly allocated.  Returns NULL upon failure.  */
 #ifdef IN_LIBRARY  #ifdef IN_LIBRARY
 #define compute_curr_prefix local_compute_curr_prefix  #define compute_curr_prefix local_compute_curr_prefix
 static  static
 #endif  #endif
const 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)
 {  {
  const char *curr_installdir;  char *curr_installdir;
   const char *rel_installdir;    const char *rel_installdir;
   
   if (curr_pathname == NULL)    if (curr_pathname == NULL)
Line 193  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 218  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.  */      {
      return NULL;        /* Unexpected: The curr_installdir does not end with rel_installdir.  */
         free (curr_installdir);
         return NULL;
       }
   
     {      {
       size_t curr_prefix_len = cp - curr_installdir;        size_t curr_prefix_len = cp - curr_installdir;
Line 264  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)
        return NULL;        {
           free (curr_installdir);
           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';
   
         free (curr_installdir);
   
       return curr_prefix;        return curr_prefix;
     }      }
   }    }
Line 281  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 296  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 342  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 386  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 400  get_shared_library_fullname () Line 399  get_shared_library_fullname ()
 #endif /* PIC */  #endif /* PIC */
   
 /* Returns the pathname, relocated according to the current installation  /* Returns the pathname, relocated according to the current installation
   directory.  */   directory.
    The returned string is either PATHNAME unmodified or a freshly allocated
    string that you can free with free() after casting it to 'char *'.  */
 const char *  const char *
 relocate (const char *pathname)  relocate (const char *pathname)
 {  {
Line 411  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;
      const 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 ());
      if (curr_prefix_better == NULL) 
        curr_prefix_better = curr_prefix; 
   
      set_relocation_prefix (orig_installprefix, curr_prefix_better);      set_relocation_prefix (orig_installprefix,
                              curr_prefix_better != NULL
                              ? curr_prefix_better
                              : curr_prefix);
   
         if (curr_prefix_better != NULL)
           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.  */        {
        return curr_prefix;          /* pathname equals orig_prefix.  */
      if (ISSLASH (pathname[orig_prefix_len]))          char *result = (char *) xmalloc (strlen (curr_prefix) + 1);
        { 
          /* pathname starts with orig_prefix.  */ 
          const char *pathname_tail = &pathname[orig_prefix_len]; 
          char *result = 
            (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);              strcpy (result, curr_prefix);
              strcpy (result + curr_prefix_len, pathname_tail);              return result;
              return result;            }
            }        }
        }      else if (ISSLASH (pathname[orig_prefix_len]))
         {
           /* pathname starts with orig_prefix.  */
           const char *pathname_tail = &pathname[orig_prefix_len];
           char *result =
             (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
 
 #ifdef NO_XMALLOC
           if (result != NULL)
 #endif
             {
               memcpy (result, curr_prefix, curr_prefix_len);
               strcpy (result + curr_prefix_len, pathname_tail);
               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>