On the cygwin list, Corinna Vinschen, one of the main cygwin developers
and project lead, noticed a problem with libiconv's behavior on cygwin
1.7.x (which I'll follow up on the appropriate list, in a few days).

However, while she was investigating it, she ran across some very
obsolete code in the relocation support employed by libintl.  In keeping
with cygwin's mantra of "more like unix, less like windows", she
suggested the following changes.  These basically make cygwin's
relocation support use the linux machanisms (/proc/self/maps,
/proc/self/exe) rather than relying on win32 mechanisms like
GetModuleFileName, DllMain(), and the like.

An added benefit of using the linux mechanisms on cygwin, is that the
paths are therefore already in cygwin/unix format, and there is no need
to convert them from/to win32 format.

Speaking of which, the old conversion code used functions which (a) are
now deprecated, and (b) do not support paths longer than 254 characters.

As modified by this patch, extremely long path names are now supported,
as well as those containing non-ascii characters.

The only remaining vestige of win32ness in the patched code is that, for
characters in the A-Za-z range, filename comparison is performed
case-insensitively.  (There might be an issue here if the filename(s)
contain UTF-8 encoded multibyte characters, leading to false
equivalence.  But the odds of that seem pretty low...and the effects if
it DID happen pretty minor, it appears to me.  The alternative is to use
some locale-sensitive case conversion function, and then compare the
results...but that belongs in a different patch IMO.)

Concerns about backwards compatibility: the mechanisms exploited by the
"linux" code have been supported by cygwin since March 1 2005, with
cygwin-1.5.13.  That's almost six years.  Plus, the cygwin project no
longer supports ANY cygwin older than 1.7.x -- and 1.7.1 dates back more
than a year.  So, while the "new" code won't work on EXTREMELY old
cygwin, I think it's quite reasonable to require >= 1.5.13.  The only
likely complaints might come from the MSYS project, since they are based
on cygwin-1.3.4, but...since they deliberately operate in a closed
garden [*] they -- by which I mean "me" [**] -- will just have to deal
with it.

[*] They choose NOT to even allow config.guess to recognize their
triple, and don't ship their '#ifdef __MSYS__' patches upstream for ANY
projects. They are an "unofficial" port in every sense of the word.

[**] I am the maintainer of libiconv and gettext on MSYS, so...I'll just
deal with any problems this change might create on that platform.  No
need to force code on the "real" cygwin to use outdated, and deprecated,
interfaces just to keep msys happy.



2011-01-27  Corinna Vinschen  <...>
            Charles Wilson  <...>

        On Cygwin, use unix mechanisms instead of win32
        * progreloc.c: Prefer linux code throughout, rather than
        win32 implementations.
        (find_executable): Eliminate Cygwin path conversion logic
        from WIN32 code, as Cygwin now uses linux implementation.
        * relocatable.c: Prefer linux code throughout, rather than
        win32 implementations.
        (DllMain): Eliminate Cygwin path conversion logic from WIN32
        code, as Cygwin now uses linux implementation and does not
        require a custom DllMain.
        (find_shared_library_fullname): Use linux implementation for
        Cygwin.
        (get_shared_library_fullname): Allow on-demand initialization
        for Cygwin, as DllMain is no longer used to pre-initialize.


--
Chuck
diff --git a/lib/progreloc.c b/lib/progreloc.c
index 7a480c8..fa9a97c 100644
--- a/lib/progreloc.c
+++ b/lib/progreloc.c
@@ -38,7 +38,7 @@
 # define WIN32_NATIVE
 #endif
 
-#if defined WIN32_NATIVE || defined __CYGWIN__
+#if defined WIN32_NATIVE
 # define WIN32_LEAN_AND_MEAN
 # include <windows.h>
 #endif
@@ -72,8 +72,8 @@ extern char * canonicalize_file_name (const char *name);
    ISSLASH(C)           tests whether C is a directory separator character.
    IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
  */
-#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
-  /* Win32, Cygwin, OS/2, DOS */
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
 # define HAS_DEVICE(P) \
     ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
@@ -82,7 +82,7 @@ extern char * canonicalize_file_name (const char *name);
     (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
 # define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
 #else
-  /* Unix */
+  /* Unix, Cygwin */
 # define ISSLASH(C) ((C) == '/')
 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
 # define FILE_SYSTEM_PREFIX_LEN(P) 0
@@ -102,7 +102,7 @@ extern char * canonicalize_file_name (const char *name);
 
 #if ENABLE_RELOCATABLE
 
-#ifdef __linux__
+#if defined __linux__ || defined __CYGWIN__
 /* File descriptor of the executable.
    (Only used to verify that we find the correct executable.)  */
 static int executable_fd = -1;
@@ -112,12 +112,12 @@ static int executable_fd = -1;
 static bool
 maybe_executable (const char *filename)
 {
-  /* Woe32 lacks the access() function, but Cygwin doesn't.  */
-#if !(defined WIN32_NATIVE && !defined __CYGWIN__)
+  /* Woe32 lacks the access() function.  */
+#ifndef WIN32_NATIVE
   if (access (filename, X_OK) < 0)
     return false;
 
-#ifdef __linux__
+#if defined __linux__ || defined __CYGWIN__
   if (executable_fd >= 0)
     {
       /* If we already have an executable_fd, check that filename points to
@@ -148,7 +148,7 @@ maybe_executable (const char *filename)
 static char *
 find_executable (const char *argv0)
 {
-#if defined WIN32_NATIVE || defined __CYGWIN__
+#if defined WIN32_NATIVE
   char location[MAX_PATH];
   int length = GetModuleFileName (NULL, location, sizeof (location));
   if (length < 0)
@@ -156,36 +156,15 @@ find_executable (const char *argv0)
   if (!IS_PATH_WITH_DIR (location))
     /* Shouldn't happen.  */
     return NULL;
-  {
-#if defined __CYGWIN__
-    /* cygwin-1.5.13 (2005-03-01) or newer would also allow a Linux-like
-       implementation: readlink of "/proc/self/exe".  But using the
-       result of the Win32 system call is simpler and is consistent with the
-       code in relocatable.c.  */
-    /* 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 NULL;
-    /* Call canonicalize_file_name, because Cygwin supports symbolic links.  */
-    return canonicalize_file_name (location_as_posix_path);
-#else
-    return xstrdup (location);
-#endif
-  }
-#else /* Unix && !Cygwin */
-#ifdef __linux__
-  /* The executable is accessible as /proc/<pid>/exe.  In newer Linux
-     versions, also as /proc/self/exe.  Linux >= 2.1 provides a symlink
-     to the true pathname; older Linux versions give only device and ino,
-     enclosed in brackets, which we cannot use here.  */
+
+  return xstrdup (location);
+
+#else /* Unix or Cygwin */
+#if defined __linux__ || defined __CYGWIN__
+  /* The executable is accessible as /proc/<pid>/exe.  In Cygwin and in
+     newer Linux versions, also as /proc/self/exe.  Linux >= 2.1 provides
+     a symlink to the true pathname; older Linux versions give only device
+     and ino, enclosed in brackets, which we cannot use here.  */
   {
     char *link;
 
diff --git a/lib/relocatable.c b/lib/relocatable.c
index 3fc666b..add2ba1 100644
--- a/lib/relocatable.c
+++ b/lib/relocatable.c
@@ -43,7 +43,7 @@
 # include "xalloc.h"
 #endif
 
-#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
+#if defined _WIN32 || defined __WIN32__
 # define WIN32_LEAN_AND_MEAN
 # include <windows.h>
 #endif
@@ -70,8 +70,8 @@
    ISSLASH(C)           tests whether C is a directory separator character.
    IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
  */
-#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
-  /* Win32, Cygwin, OS/2, DOS */
+#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+  /* Win32, OS/2, DOS */
 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
 # define HAS_DEVICE(P) \
     ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
@@ -80,7 +80,7 @@
     (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
 # define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
 #else
-  /* Unix */
+  /* Unix, Cygwin */
 # define ISSLASH(C) ((C) == '/')
 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
 # define FILE_SYSTEM_PREFIX_LEN(P) 0
@@ -293,7 +293,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__ || defined __CYGWIN__
+#if defined _WIN32 || defined __WIN32__
 
 /* Determine the full pathname of the shared library when it is loaded.  */
 
@@ -315,38 +315,20 @@ DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
         /* Shouldn't happen.  */
         return FALSE;
 
-      {
-#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
-      }
+      shared_library_fullname = strdup (location);
     }
 
   return TRUE;
 }
 
-#else /* Unix except Cygwin */
+#else /* Unix or Cygwin */
 
 static void
 find_shared_library_fullname ()
 {
-#if defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)
+#if (defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__
   /* Linux has /proc/self/maps. glibc 2 and uClibc have the getline()
-     function.  */
+     function.  Cygwin as well.  */
   FILE *fp;
 
   /* Open the current process' maps file.  It describes one VMA per line.  */
@@ -391,7 +373,7 @@ find_shared_library_fullname ()
 #endif
 }
 
-#endif /* (WIN32 or Cygwin) / (Unix except Cygwin) */
+#endif /* WIN32 / (Unix or Cygwin) */
 
 /* Return the full pathname of the current shared library.
    Return NULL if unknown.
@@ -399,7 +381,7 @@ find_shared_library_fullname ()
 static char *
 get_shared_library_fullname ()
 {
-#if !(defined _WIN32 || defined __WIN32__ || defined __CYGWIN__)
+#if !(defined _WIN32 || defined __WIN32__)
   static bool tried_find_shared_library_fullname;
   if (!tried_find_shared_library_fullname)
     {

Reply via email to