changeset 4721:19d70297d866

Make readlink_or_correct_case function correctly on Darwin. src/ChangeLog addition: 2009-10-26 Aidan Kehoe <kehoea@parhasard.net> * config.h.in (REALPATH_CORRECTS_CASE): New #define, available on Darwin. * realpath.c (readlink_or_correct_case): On Darwin, use realpath(3)'s case correction to get the canonical case for a file; thank you Robert Delius Royar!
author Aidan Kehoe <kehoea@parhasard.net>
date Mon, 26 Oct 2009 09:42:20 +0000
parents 3c92890f3750
children dfc9fe46c294
files src/ChangeLog src/config.h.in src/realpath.c
diffstat 3 files changed, 63 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sat Oct 24 15:33:23 2009 +0100
+++ b/src/ChangeLog	Mon Oct 26 09:42:20 2009 +0000
@@ -1,3 +1,11 @@
+2009-10-26  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* config.h.in (REALPATH_CORRECTS_CASE): 
+	New #define, available on Darwin. 
+	* realpath.c (readlink_or_correct_case): 
+	On Darwin, use realpath(3)'s case correction to get the canonical
+	case for a file; thank you Robert Delius Royar!
+
 2009-10-11  Michael Sperber  <mike@xemacs.org>
 
 	* event-stream.c (post_command_hook): Run `post-command-hook'
--- a/src/config.h.in	Sat Oct 24 15:33:23 2009 +0100
+++ b/src/config.h.in	Mon Oct 26 09:42:20 2009 +0000
@@ -340,6 +340,11 @@
 #undef DLSYM_NEEDS_UNDERSCORE
 #undef HAVE_SHLIB
 
+/* Darwin; realpath corrects for case: */
+#ifdef HAVE_DYLD
+#define REALPATH_CORRECTS_CASE 1
+#endif
+
 #undef HAVE_LIBINTL
 #undef HAVE_LIBDNET
 #undef HAVE_LIBRESOLV
--- a/src/realpath.c	Sat Oct 24 15:33:23 2009 +0100
+++ b/src/realpath.c	Mon Oct 26 09:42:20 2009 +0000
@@ -78,6 +78,11 @@
    DOES NOT ZERO TERMINATE!!!!!
 */
 
+#ifdef REALPATH_CORRECTS_CASE /* Darwin */
+#include <sys/param.h>
+#include <stdlib.h>
+#endif
+
 static int
 readlink_or_correct_case (const Ibyte *name, Ibyte *buf, Bytecount size,
 #ifndef WIN32_ANY
@@ -88,8 +93,52 @@
 			  )
 {
 #ifndef WIN32_ANY
+#ifdef REALPATH_CORRECTS_CASE
+  /* Darwin's realpath corrects file name case, so we want to use that
+     here, as well as our own, non-case-correcting, implementation
+     further down in this file.
+
+     It might be reasonable to incorporate case correction in our own
+     realpath implementation, which would help things with
+     case-insensitive file systems on Linux; one way to do this would
+     be to make sure that init_initial_directory and
+     get_initial_directory always give the correct case.  */
+  int n = qxe_readlink (name, buf, (size_t) size);
+  Extbyte realpath_buf[PATH_MAX], *tmp;
+  DECLARE_EISTRING (realpathing);
+
+  if (n >= 0 || errno != EINVAL)
+    return n;
+
+  eicpy_rawz (realpathing, name);
+  eito_external (realpathing, Qfile_name);
+  tmp = realpath (eiextdata (realpathing), realpath_buf);
+
+  if (!tmp)
+    return -1;
+
+  if (0 == memcmp (eiextdata (realpathing), realpath_buf,
+                   eiextlen (realpathing)))
+    {
+      /* No case change needed; tell the caller that. */
+      errno = EINVAL;
+      return -1;
+    }
+
+  eireset (realpathing);
+  eicpy_ext (realpathing, realpath_buf, Qfile_name);
+  if (eilen (realpathing) > size)
+    {
+      errno = ERANGE;
+      return -1;
+    }
+
+  memcpy (buf, eidata (realpathing), eilen (realpathing));
+  return eilen (realpathing);
+#else /* !REALPATH_CORRECTS_CASE */
   return qxe_readlink (name, buf, (size_t) size);
-#else
+#endif /* REALPATH_CORRECTS_CASE */
+#else /* defined (WIN32_ANY) */
 # ifdef CYGWIN
   Ibyte *tmp;
   int n = qxe_readlink (name, buf, (size_t) size);