bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gettext patches for cygwin #3: relocation


From: Charles Wilson
Subject: gettext patches for cygwin #3: relocation
Date: Sat, 19 Nov 2005 23:51:06 -0500
User-agent: Mozilla Thunderbird 1.0.6 (Windows/20050716)

Mostly having to do with .exe extension.

2005-11-20  Charles Wilson  <address@hidden>

        * build-aux/install-reloc: handle EXEEXT.
        * gettext-runtime/intl/relocatable.c (DllMain): convert path
        to unix style on cygwin.
        (get_shared_library_fullname): rely on DLLMain to compute
        shared_library_fullname.
        * gettext-tools/lib/relocatable.c: ditto
        * gettext-tools/lib/progreloc.c (maybe_executable): use access()
        on cygwin even if WIN32 defined.
        (xreadlink_proc_exename): new function to read /proc/pid/exename
        (find_executable): don't use GetModuleFileName on cygwin.
        Instead, use /proc/self/exe or /proc/<pid>/exename.
        (set_program_name_and_installdir): take care for trailing .exe
        * gettext-tools/lib/relocwrapper.c (add_dotbin): foo.exe should
        become foo.bin.exe, not foo.exe.bin.

--
Chuck

diff -urN gettext-0.14.5-orig/gettext-runtime/intl/relocatable.c 
gettext-0.14.5/gettext-runtime/intl/relocatable.c
--- gettext-0.14.5-orig/gettext-runtime/intl/relocatable.c      2005-05-20 
16:09:45.000000000 -0400
+++ gettext-0.14.5/gettext-runtime/intl/relocatable.c   2005-11-11 
00:05:57.031250000 -0500
@@ -60,6 +60,12 @@
 # include <libintl.h>
 #endif
 
+/* cygwin doesn't get these defs by default, unlike other Win32 */
+#if defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
 /* Faked cheap 'bool'.  */
 #undef bool
 #undef false
@@ -240,6 +246,11 @@
                != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
              break;
 #else
+  /* technically, cygwin should be treated as above.  But, with 'managed'
+     mounts, cygwin can fake case-sensitivity.  So, we choose to use
+     case-sensitive comparison on cygwin, even though it may infrequently
+     break things if not using managed mounts
+  */
            if (*rpi != *cpi)
              break;
 #endif
@@ -280,7 +291,7 @@
 /* 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.  */
 
@@ -302,7 +313,16 @@
        /* Shouldn't happen.  */
        return FALSE;
 
+#if defined(__CYGWIN__)
+      {
+        static char cyglocation[MAX_PATH];
+        cygwin_conv_to_posix_path(location, cyglocation);
+        shared_library_fullname = strdup (cyglocation);
+      }
+#else
       shared_library_fullname = strdup (location);
+#endif
+    
     }
 
   return TRUE;
@@ -363,11 +383,11 @@
 
 /* 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)
     {
diff -urN gettext-0.14.5-orig/gettext-tools/lib/progreloc.c 
gettext-0.14.5/gettext-tools/lib/progreloc.c
--- gettext-0.14.5-orig/gettext-tools/lib/progreloc.c   2005-05-20 
16:25:41.000000000 -0400
+++ gettext-0.14.5/gettext-tools/lib/progreloc.c        2005-11-11 
00:53:26.546875000 -0500
@@ -91,11 +91,11 @@
 static bool
 maybe_executable (const char *filename)
 {
-#if !defined WIN32
+#if !defined (WIN32) || defined (__CYGWIN__)
   if (access (filename, X_OK) < 0)
     return false;
 
-#ifdef __linux__
+# ifdef __linux__
   if (executable_fd >= 0)
     {
       /* If we already have an executable_fd, check that filename points to
@@ -113,12 +113,105 @@
            return false;
        }
     }
-#endif
+# endif
 #endif
 
   return true;
 }
 
+/* Using /proc/<pid>/exename
+   Only on cygwin.
+
+   The first entry must be read manually as a text string, and then
+   xreadlink() can be used (in a loop) to find the final target exe.
+   (Or, better, use canonicalize_file_name instead).
+
+   returns NULL if target not found; otherwise returns the fullpath
+   of the executable in malloc'ed storage.
+*/
+static char *
+xreadlink_proc_exename(char * path)
+{
+  char* buf;
+  int fd = -1;
+  ssize_t count;
+  long int path_max;
+
+  if ((path == NULL) || (*path == '\0'))
+    return NULL;
+
+#ifdef PATH_MAX
+  path_max = PATH_MAX
+#else
+  path_max = pathconf (path, _PC_PATH_MAX);
+  if (path_max <= 0)
+    path_max = 1024;
+#endif
+
+  buf = xmalloc(path_max + 5);
+#if NO_XMALLOC
+  if (buf == NULL)
+    return NULL;
+#endif
+
+  if ((fd = open(path, O_RDONLY | O_BINARY)) == -1)
+  {
+    free(buf);
+    return NULL;
+  }
+  count = read(fd, buf, path_max + 4);
+  close(fd);
+
+  /* If count = -1, there was an error reading the file
+     If count = 0, the file was empty (!)
+     If we actually succeed in reading more than PATH_MAX characters,
+       then the contents do not represent a filename
+     In any of these cases, bail out
+  */
+  if ((count <= 0) || (count > path_max + 3))
+  {
+    free(buf);
+    return NULL;
+  }
+  buf[count] = '\0';
+
+  /* Because /proc/<pid>/exename may represent the name of a
+     symlink (to a symlink to a symlink ...) we would need 
+     to loop over readlink (xreadlink, if we need to worry
+     about allocated storage).  However, canonicalize_file_name()
+     handles all of that for us -- including allocated storage.
+     
+  */
+  {
+    char* tbuf;
+    struct stat st;
+
+    tbuf = canonicalize_file_name (buf);
+    free(buf);
+
+    /* canonicalize_file_name doesn't care if the final component
+       of its argument exists, nor if it is a symlink to a non-
+       existant file.  We do.  Bail if tbuf !exist, or if
+       tbuf is symlink 
+    */
+    if (tbuf == NULL)
+      return NULL;
+    if (lstat (tbuf, &st) < 0)
+    {
+      /* tbuf refers to a nonexistant file */
+      free(tbuf);
+      return NULL;
+    }
+    if (S_ISLNK (st.st_mode))
+    {
+      /* tbuf is a symlink to a nonexistant file */
+      free(tbuf);
+      return NULL;
+    } 
+    return tbuf;
+  }
+}
+
 /* Determine the full pathname of the current executable, freshly allocated.
    Return NULL if unknown.
    Guaranteed to work on Linux and Woe32.  Likely to work on the other
@@ -126,7 +219,7 @@
 static char *
 find_executable (const char *argv0)
 {
-#ifdef WIN32
+#if defined (WIN32) && !defined(__CYGWIN__)
   char buf[1024];
   int length = GetModuleFileName (NULL, buf, sizeof (buf));
   if (length < 0)
@@ -135,8 +228,45 @@
     /* Shouldn't happen.  */
     return NULL;
   return xstrdup (buf);
-#else /* Unix */
-#ifdef __linux__
+#else /* !Woe32 */
+# if defined (__CYGWIN__)
+  /* For cygwin, we could use GetModuleFileName and then translate
+     the windows-ish path to unix-ish, using cygwin's mount table.
+     Or, we can rely on cygwin-1.5.0's /proc/<pid>/ structure.  We 
+     choose the latter...but:
+
+     From cygwin-1.5.0 to 1.5.12, cygwin provides only /proc/<pid>/exename
+     not /proc/<pid>/exe, nor does it provide /proc/self/
+
+     As of cygwin-1.5.13 (01Mar2005), cygwin provides all of
+     /proc/<pid>/exe, /proc/<pic>/exename, and /proc/self/.
+     So, we try them in the most desirable order:
+       1. /proc/self/exe
+       2. /proc/self/exename
+       3. /proc/<pid>/exe
+       4. /proc/<pid>/exename
+     Except 2 and 3 are unnecessary, given the simultaneous introduction
+     of /proc/self support and /proc/<pid>/exe support.
+  */
+  {
+    char *link;
+
+    link = xreadlink("/proc/self/exe");
+    if (link != NULL)
+    {
+      return link;
+    }
+    else
+    {
+      char buf[6+10+9];
+      snprintf (buf, 24, "/proc/%d/exename", getpid ());
+      link = xreadlink_proc_exename (buf);
+      if (link != NULL)
+       return link;
+    }
+  }
+# else /* !cygwin */
+#  if defined (__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,
@@ -160,7 +290,8 @@
        executable_fd = open (buf, O_RDONLY, 0);
     }
   }
-#endif
+#  endif /* __linux__ */
+# endif /* __CYGWIN__ */
   /* Guess the executable's full path.  We assume the executable has been
      called via execlp() or execvp() with properly set up argv[0].  The
      login(1) convention to add a '-' prefix to argv[0] is not supported.  */
@@ -201,10 +332,10 @@
                /* We have a path item at p, of length p_len.
                   Now concatenate the path item and argv0.  */
                concat_name = (char *) xmalloc (p_len + strlen (argv0) + 2);
-#ifdef NO_XMALLOC
+# ifdef NO_XMALLOC
                if (concat_name == NULL)
                  return NULL;
-#endif
+# endif
                if (p_len == 0)
                  /* An empty PATH element designates the current directory.  */
                  strcpy (concat_name, argv0);
@@ -260,11 +391,12 @@
 {
   const char *argv0_stripped = argv0;
 
-  /* Relocatable programs are renamed to .bin by install-reloc.  Remove
-     this suffix here.  */
+  /* Relocatable programs are renamed to .bin (or .bin.exe) by 
+     install-reloc.  Remove this suffix here.  */
   {
     size_t argv0_len = strlen (argv0);
     if (argv0_len > 4 && memcmp (argv0 + argv0_len - 4, ".bin", 4) == 0)
+      /* foo.bin --> foo */
       {
        char *shorter = (char *) xmalloc (argv0_len - 4 + 1);
 #ifdef NO_XMALLOC
@@ -276,6 +408,20 @@
            argv0_stripped = shorter;
          }
       }
+    else if (argv0_len > 8 && memcmp (argv0 + argv0_len - 8, ".bin", 4) == 0)
+      /* foo.bin.exe --> foo.exe */
+      {
+       char *shorter = (char *) xmalloc (argv0_len - 4 + 1);
+#ifdef NO_XMALLOC
+       if (shorter != NULL)
+#endif
+         {
+           memcpy (shorter, argv0, argv0_len - 8);
+           memcpy (shorter + argv0_len - 8, ".exe", 4);
+           shorter[argv0_len - 4] = '\0';
+           argv0_stripped = shorter;
+         }
+      }
   }
 
   set_program_name (argv0_stripped);
diff -urN gettext-0.14.5-orig/gettext-tools/lib/relocatable.c 
gettext-0.14.5/gettext-tools/lib/relocatable.c
--- gettext-0.14.5-orig/gettext-tools/lib/relocatable.c 2005-05-20 
16:26:17.000000000 -0400
+++ gettext-0.14.5/gettext-tools/lib/relocatable.c      2005-11-11 
00:53:52.250000000 -0500
@@ -60,6 +60,12 @@
 # include <libintl.h>
 #endif
 
+/* cygwin doesn't get these defs by default, unlike other Win32 */
+#if defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
 /* Faked cheap 'bool'.  */
 #undef bool
 #undef false
@@ -240,6 +246,11 @@
                != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
              break;
 #else
+  /* technically, cygwin should be treated as above.  But, with 'managed'
+     mounts, cygwin can fake case-sensitivity.  So, we choose to use
+     case-sensitive comparison on cygwin, even though it may infrequently
+     break things if not using managed mounts
+  */
            if (*rpi != *cpi)
              break;
 #endif
@@ -280,7 +291,7 @@
 /* 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.  */
 
@@ -302,7 +313,16 @@
        /* Shouldn't happen.  */
        return FALSE;
 
+#if defined(__CYGWIN__)
+      {
+        static char cyglocation[MAX_PATH];
+        cygwin_conv_to_posix_path(location, cyglocation);
+        shared_library_fullname = strdup (cyglocation);
+      }
+#else
       shared_library_fullname = strdup (location);
+#endif
+    
     }
 
   return TRUE;
@@ -363,11 +383,11 @@
 
 /* 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)
     {
diff -urN gettext-0.14.5-orig/gettext-tools/lib/relocwrapper.c 
gettext-0.14.5/gettext-tools/lib/relocwrapper.c
--- gettext-0.14.5-orig/gettext-tools/lib/relocwrapper.c        2005-05-20 
16:26:25.000000000 -0400
+++ gettext-0.14.5/gettext-tools/lib/relocwrapper.c     2005-11-11 
00:55:46.359375000 -0500
@@ -58,17 +58,30 @@
 #include "relocatable.h"
 #include "setenv.h"
 
-/* Return a copy of the filename, with an extra ".bin" at the end.  */
+/* Return a copy of the filename, with an extra ".bin" at the end. 
+   If filename ends with .exe, then ".bin" is inserted between 
+   the .exe and the rest of the filename */
 static char *
 add_dotbin (const char *filename)
 {
   size_t filename_len = strlen (filename);
   char *result = (char *) malloc (filename_len + 4 + 1);
-
+  
   if (result != NULL)
     {
-      memcpy (result, filename, filename_len);
-      memcpy (result + filename_len, ".bin", 4 + 1);
+      if ((filename_len > 4) &&
+          ((strncmp(filename + filename_len - 4, ".exe", 4) == 0) ||
+           (strncmp(filename + filename_len - 4, ".EXE", 4) == 0)))
+        {
+          memcpy (result, filename, filename_len - 4);
+          memcpy (result + filename_len - 4, ".bin", 4);
+          memcpy (result + filename_len, filename + filename_len - 4, 4 + 1);
+        }
+      else
+        {
+          memcpy (result, filename, filename_len);
+          memcpy (result + filename_len, ".bin", 4 + 1);
+        }
       return result;
     }
   else
diff -urN -x .build -x .inst -x .sinst -x '*~' 
gettext-0.14.5-orig/build-aux/install-reloc 
gettext-0.14.5/build-aux/install-reloc
--- gettext-0.14.5-orig/build-aux/install-reloc 2005-05-20 16:03:20.000000000 
-0400
+++ gettext-0.14.5/build-aux/install-reloc      2005-11-11 18:05:17.906250000 
-0500
@@ -108,12 +108,19 @@
 # wrapper.
 test -n "$libdirs" || exit 0
 
+# deduce EXEEXT.  if $destprog endswith .exe, fine...
+EXEEXT=
+p1=`echo ${destprog}|sed -e 's/\.exe$//'`
+test "${p1}" == "${destprog}" || EXEEXT=.exe
+# otherwise, check for file existence
+test -f "${p1}.exe" && EXEEXT=.exe
+
 # Compile wrapper.
 installdir=`echo "$destprog" | sed -e 's,/[^/]*$,,'`
-func_verbose $compile_command -I"$builddir" -I"$srcdir" -I"$config_h_dir" 
-DHAVE_CONFIG_H -DNO_XMALLOC -D"INSTALLPREFIX=\"$prefix\"" 
-D"INSTALLDIR=\"$installdir\"" -D"LIBPATHVAR=\"$library_path_var\"" 
-D"LIBDIRS=$libdirs" "$srcdir"/relocwrapper.c "$srcdir"/progname.c 
"$srcdir"/progreloc.c "$srcdir"/xreadlink.c "$srcdir"/readlink.c 
"$srcdir"/canonicalize.c "$srcdir"/allocsa.c "$srcdir"/relocatable.c 
"$srcdir"/setenv.c "$srcdir"/strerror.c -o $destprog.wrapper || exit $?
+func_verbose $compile_command -I"$builddir" -I"$srcdir" -I"$config_h_dir" 
-DHAVE_CONFIG_H -DNO_XMALLOC -D"INSTALLPREFIX=\"$prefix\"" 
-D"INSTALLDIR=\"$installdir\"" -D"LIBPATHVAR=\"$library_path_var\"" 
-D"LIBDIRS=$libdirs" "$srcdir"/relocwrapper.c "$srcdir"/progname.c 
"$srcdir"/progreloc.c "$srcdir"/xreadlink.c "$srcdir"/readlink.c 
"$srcdir"/canonicalize.c "$srcdir"/allocsa.c "$srcdir"/relocatable.c 
"$srcdir"/setenv.c "$srcdir"/strerror.c -o ${p1}.wrapper${EXEEXT} || exit $?
 
 # Rename $destprog.wrapper -> $destprog -> $destprog.bin.
-ln -f $destprog $destprog.bin || exit 1
-mv $destprog.wrapper $destprog || exit 1
+ln -f ${p1}${EXEEXT} ${p1}.bin${EXEEXT} || exit 1
+mv ${p1}.wrapper${EXEEXT} ${p1}${EXEEXT} || exit 1
 
 exit 0

reply via email to

[Prev in Thread] Current Thread [Next in Thread]