]> git.deb.at Git - pkg/abook.git/blobdiff - intl/relocatable.c
autotools update: 1/2: main files
[pkg/abook.git] / intl / relocatable.c
index 2683ace717893d917662384493372ae79016b87d..f1bed781b3d93e05e29dde0f453879d27d3d1bdb 100644 (file)
@@ -1,5 +1,5 @@
 /* Provide relocatable packages.
-   Copyright (C) 2003-2004 Free Software Foundation, Inc.
+   Copyright (C) 2003-2006, 2008-2009 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2003.
 
    This program is free software; you can redistribute it and/or modify it
@@ -14,7 +14,7 @@
 
    You should have received a copy of the GNU Library General Public
    License along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
    USA.  */
 
 
    This must come before <config.h> because <config.h> may include
    <features.h>, and once <features.h> has been included, it's too late.  */
 #ifndef _GNU_SOURCE
-# define _GNU_SOURCE   1
+# define _GNU_SOURCE 1
 #endif
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include <config.h>
 
 /* Specification.  */
 #include "relocatable.h"
@@ -45,7 +43,7 @@
 # include "xalloc.h"
 #endif
 
-#if defined _WIN32 || defined __WIN32__
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
 # define WIN32_LEAN_AND_MEAN
 # include <windows.h>
 #endif
@@ -104,11 +102,11 @@ static size_t curr_prefix_len;
    instead of "/").  */
 static void
 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
       /* 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)
     {
       /* Duplicate the argument strings.  */
@@ -120,14 +118,14 @@ set_this_relocation_prefix (const char *orig_prefix_arg,
 #ifdef NO_XMALLOC
       if (memory != NULL)
 #endif
-       {
-         memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
-         orig_prefix = memory;
-         memory += orig_prefix_len + 1;
-         memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
-         curr_prefix = memory;
-         return;
-       }
+        {
+          memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
+          orig_prefix = memory;
+          memory += orig_prefix_len + 1;
+          memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
+          curr_prefix = memory;
+          return;
+        }
     }
   orig_prefix = NULL;
   curr_prefix = NULL;
@@ -162,17 +160,18 @@ set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
 /* Convenience function:
    Computes the current installation prefix, based on the original
    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
 #define compute_curr_prefix local_compute_curr_prefix
 static
 #endif
-const char *
+char *
 compute_curr_prefix (const char *orig_installprefix,
-                    const char *orig_installdir,
-                    const char *curr_pathname)
+                     const char *orig_installdir,
+                     const char *curr_pathname)
 {
-  const char *curr_installdir;
+  char *curr_installdir;
   const char *rel_installdir;
 
   if (curr_pathname == NULL)
@@ -195,9 +194,9 @@ compute_curr_prefix (const char *orig_installprefix,
 
     while (p > p_base)
       {
-       p--;
-       if (ISSLASH (*p))
-         break;
+        p--;
+        if (ISSLASH (*p))
+          break;
       }
 
     q = (char *) xmalloc (p - curr_pathname + 1);
@@ -220,41 +219,47 @@ compute_curr_prefix (const char *orig_installprefix,
 
     while (rp > rel_installdir && cp > cp_base)
       {
-       bool same = false;
-       const char *rpi = rp;
-       const char *cpi = cp;
-
-       while (rpi > rel_installdir && cpi > cp_base)
-         {
-           rpi--;
-           cpi--;
-           if (ISSLASH (*rpi) || ISSLASH (*cpi))
-             {
-               if (ISSLASH (*rpi) && ISSLASH (*cpi))
-                 same = true;
-               break;
-             }
+        bool same = false;
+        const char *rpi = rp;
+        const char *cpi = cp;
+
+        while (rpi > rel_installdir && cpi > cp_base)
+          {
+            rpi--;
+            cpi--;
+            if (ISSLASH (*rpi) || ISSLASH (*cpi))
+              {
+                if (ISSLASH (*rpi) && ISSLASH (*cpi))
+                  same = true;
+                break;
+              }
+            /* Do case-insensitive comparison if the file system is always or
+               often case-insensitive.  It's better to accept the comparison
+               if the difference is only in case, rather than to fail.  */
 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
-           /* Win32, Cygwin, OS/2, DOS - case insignificant filesystem */
-           if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
-               != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
-             break;
+            /* Win32, Cygwin, OS/2, DOS - case insignificant file system */
+            if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
+                != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
+              break;
 #else
-           if (*rpi != *cpi)
-             break;
+            if (*rpi != *cpi)
+              break;
 #endif
-         }
-       if (!same)
-         break;
-       /* The last pathname component was the same.  opi and cpi now point
-          to the slash before it.  */
-       rp = rpi;
-       cp = cpi;
+          }
+        if (!same)
+          break;
+        /* The last pathname component was the same.  opi and cpi now point
+           to the slash before it.  */
+        rp = rpi;
+        cp = cpi;
       }
 
     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;
@@ -263,11 +268,16 @@ compute_curr_prefix (const char *orig_installprefix,
       curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
 #ifdef NO_XMALLOC
       if (curr_prefix == NULL)
-       return NULL;
+        {
+          free (curr_installdir);
+          return NULL;
+        }
 #endif
       memcpy (curr_prefix, curr_installdir, curr_prefix_len);
       curr_prefix[curr_prefix_len] = '\0';
 
+      free (curr_installdir);
+
       return curr_prefix;
     }
   }
@@ -280,7 +290,7 @@ compute_curr_prefix (const char *orig_installprefix,
 /* Full pathname of shared library, or NULL.  */
 static char *shared_library_fullname;
 
-#if defined _WIN32 || defined __WIN32__
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
 
 /* Determine the full pathname of the shared library when it is loaded.  */
 
@@ -295,20 +305,38 @@ DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
       static char location[MAX_PATH];
 
       if (!GetModuleFileName (module_handle, location, sizeof (location)))
-       /* Shouldn't happen.  */
-       return FALSE;
+        /* Shouldn't happen.  */
+        return FALSE;
 
       if (!IS_PATH_WITH_DIR (location))
-       /* Shouldn't happen.  */
-       return FALSE;
+        /* Shouldn't happen.  */
+        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;
 }
 
-#else /* Unix */
+#else /* Unix except Cygwin */
 
 static void
 find_shared_library_fullname ()
@@ -323,51 +351,51 @@ find_shared_library_fullname ()
     {
       unsigned long address = (unsigned long) &find_shared_library_fullname;
       for (;;)
-       {
-         unsigned long start, end;
-         int c;
-
-         if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
-           break;
-         if (address >= start && address <= end - 1)
-           {
-             /* Found it.  Now see if this line contains a filename.  */
-             while (c = getc (fp), c != EOF && c != '\n' && c != '/')
-               continue;
-             if (c == '/')
-               {
-                 size_t size;
-                 int len;
-
-                 ungetc (c, fp);
-                 shared_library_fullname = NULL; size = 0;
-                 len = getline (&shared_library_fullname, &size, fp);
-                 if (len >= 0)
-                   {
-                     /* Success: filled shared_library_fullname.  */
-                     if (len > 0 && shared_library_fullname[len - 1] == '\n')
-                       shared_library_fullname[len - 1] = '\0';
-                   }
-               }
-             break;
-           }
-         while (c = getc (fp), c != EOF && c != '\n')
-           continue;
-       }
+        {
+          unsigned long start, end;
+          int c;
+
+          if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
+            break;
+          if (address >= start && address <= end - 1)
+            {
+              /* Found it.  Now see if this line contains a filename.  */
+              while (c = getc (fp), c != EOF && c != '\n' && c != '/')
+                continue;
+              if (c == '/')
+                {
+                  size_t size;
+                  int len;
+
+                  ungetc (c, fp);
+                  shared_library_fullname = NULL; size = 0;
+                  len = getline (&shared_library_fullname, &size, fp);
+                  if (len >= 0)
+                    {
+                      /* Success: filled shared_library_fullname.  */
+                      if (len > 0 && shared_library_fullname[len - 1] == '\n')
+                        shared_library_fullname[len - 1] = '\0';
+                    }
+                }
+              break;
+            }
+          while (c = getc (fp), c != EOF && c != '\n')
+            continue;
+        }
       fclose (fp);
     }
 #endif
 }
 
-#endif /* WIN32 / Unix */
+#endif /* (WIN32 or Cygwin) / (Unix except Cygwin) */
 
 /* Return the full pathname of the current shared library.
    Return NULL if unknown.
-   Guaranteed to work only on Linux and Woe32.  */
+   Guaranteed to work only on Linux, Cygwin and Woe32.  */
 static char *
 get_shared_library_fullname ()
 {
-#if !(defined _WIN32 || defined __WIN32__)
+#if !(defined _WIN32 || defined __WIN32__ || defined __CYGWIN__)
   static bool tried_find_shared_library_fullname;
   if (!tried_find_shared_library_fullname)
     {
@@ -381,7 +409,9 @@ get_shared_library_fullname ()
 #endif /* PIC */
 
 /* 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 *
 relocate (const char *pathname)
 {
@@ -392,55 +422,69 @@ relocate (const char *pathname)
   if (!initialized)
     {
       /* At this point, orig_prefix and curr_prefix likely have already been
-        set through the main program's set_program_name_and_installdir
-        function.  This is sufficient in the case that the library has
-        initially been installed in the same orig_prefix.  But we can do
-        better, to also cover the cases that 1. it has been installed
-        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
-        orig_prefix.  */
+         set through the main program's set_program_name_and_installdir
+         function.  This is sufficient in the case that the library has
+         initially been installed in the same orig_prefix.  But we can do
+         better, to also cover the cases that 1. it has been installed
+         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
+         orig_prefix.  */
       const char *orig_installprefix = INSTALLPREFIX;
       const char *orig_installdir = INSTALLDIR;
-      const char *curr_prefix_better;
+      char *curr_prefix_better;
 
       curr_prefix_better =
-       compute_curr_prefix (orig_installprefix, orig_installdir,
-                            get_shared_library_fullname ());
-      if (curr_prefix_better == NULL)
-       curr_prefix_better = curr_prefix;
+        compute_curr_prefix (orig_installprefix, orig_installdir,
+                             get_shared_library_fullname ());
+
+      set_relocation_prefix (orig_installprefix,
+                             curr_prefix_better != NULL
+                             ? curr_prefix_better
+                             : curr_prefix);
 
-      set_relocation_prefix (orig_installprefix, curr_prefix_better);
+      if (curr_prefix_better != NULL)
+        free (curr_prefix_better);
 
       initialized = 1;
     }
 #endif
 
   /* 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
      from.  */
   if (orig_prefix != NULL && curr_prefix != NULL
       && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
     {
       if (pathname[orig_prefix_len] == '\0')
-       /* pathname equals orig_prefix.  */
-       return curr_prefix;
-      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);
+        {
+          /* pathname equals orig_prefix.  */
+          char *result = (char *) xmalloc (strlen (curr_prefix) + 1);
+
+#ifdef NO_XMALLOC
+          if (result != NULL)
+#endif
+            {
+              strcpy (result, curr_prefix);
+              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)
+          if (result != NULL)
 #endif
-           {
-             memcpy (result, curr_prefix, curr_prefix_len);
-             strcpy (result + curr_prefix_len, pathname_tail);
-             return result;
-           }
-       }
+            {
+              memcpy (result, curr_prefix, curr_prefix_len);
+              strcpy (result + curr_prefix_len, pathname_tail);
+              return result;
+            }
+        }
     }
   /* Nothing to relocate.  */
   return pathname;