emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] master 2f5e0b1: Improve case-insensitive checks (Bug#24441


From: Paul Eggert
Subject: [Emacs-diffs] master 2f5e0b1: Improve case-insensitive checks (Bug#24441)
Date: Mon, 14 Nov 2016 17:09:52 +0000 (UTC)

branch: master
commit 2f5e0b1bf7b0ac4f450847db34d599a072020600
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    Improve case-insensitive checks (Bug#24441)
    
    * doc/lispref/files.texi (Truenames): Simplify documentation,
    to avoid giving too much platform-specific information that
    may not be accurate anyway.
    * src/fileio.c (file_name_case_insensitive_p): Use pathconf with
    _PC_CASE_SENSITIVE if _PC_CASE_INSENSITIVE is not available.
    Otherwise if one approach fails (e.g., with errno == EINVAL), fall
    back on an alternative rather than returning false.  Try skipping
    the Darwin code, as it (1) no longer seems to be needed and (2)
    does not seem to match the Apple documentation.  Leave in two
    alternatives conditionally compiled based on
    DARWIN_OS_CASE_SENSITIVE_FIXME in case (1) or (2) is incorrect.
---
 doc/lispref/files.texi |   14 ++------
 src/fileio.c           |   93 +++++++++++++++++++++++++++++++-----------------
 2 files changed, 64 insertions(+), 43 deletions(-)

diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 70c7177..ab0dcae 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1144,17 +1144,9 @@ return value is unspecified.
 Sometimes file names or their parts need to be compared as strings, in
 which case it's important to know whether the underlying filesystem is
 case-insensitive.  This function returns @code{t} if file
address@hidden is on a case-insensitive filesystem.  It always returns
address@hidden on MS-DOS and MS-Windows.  On Cygwin and Mac OS X,
-filesystems may or may not be case-insensitive, and the function tries
-to determine case-sensitivity by a runtime test.  If the test is
-inconclusive, the function returns @code{t} on Cygwin and @code{nil}
-on Mac OS X.
-
-Currently this function always returns @code{nil} on platforms other
-than MS-DOS, MS-Windows, Cygwin, and Mac OS X.  It does not detect
-case-insensitivity of mounted filesystems, such as Samba shares or
-NFS-mounted Windows volumes.
address@hidden is on a case-insensitive filesystem.  On platforms where
+this information is not available, this function guesses based on
+common practice.
 @end defun
 
 @defun file-in-directory-p file dir
diff --git a/src/fileio.c b/src/fileio.c
index f3f8f42..eec3591 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2236,13 +2236,10 @@ internal_delete_file (Lisp_Object filename)
   return NILP (tem);
 }
 
-/* Filesystems are case-sensitive on all supported systems except
-   MS-Windows, MS-DOS, Cygwin, and Mac OS X.  They are always
-   case-insensitive on the first two, but they may or may not be
-   case-insensitive on Cygwin and OS X.  The following function
-   attempts to provide a runtime test on those two systems.  If the
-   test is not conclusive, we assume case-insensitivity on Cygwin and
-   case-sensitivity on Mac OS X.
+/* Return true if FILENAME is on a case-insensitive file system.
+   Use a runtime test if available.  Otherwise, assume the file system
+   is case-insensitive on Microsoft-based platforms and case-sensitive
+   elsewhere.
 
    FIXME: Mounted filesystems on Posix hosts, like Samba shares or
    NFS-mounted Windows volumes, might be case-insensitive.  Can we
@@ -2251,33 +2248,65 @@ internal_delete_file (Lisp_Object filename)
 static bool
 file_name_case_insensitive_p (const char *filename)
 {
-#ifdef DOS_NT
-  return 1;
-#elif defined CYGWIN
-/* As of Cygwin-2.6.1, pathconf supports _PC_CASE_INSENSITIVE.  */
-# ifdef _PC_CASE_INSENSITIVE
+#ifdef _PC_CASE_INSENSITIVE
   int res = pathconf (filename, _PC_CASE_INSENSITIVE);
-  if (res < 0)
-    return 1;
-  return res > 0;
-# else
-  return 1;
+  if (0 < res)
+    return true;
+  if (res == 0 || errno != EINVAL)
+    return false;
+#elif defined _PC_CASE_SENSITIVE
+  int res = pathconf (filename, _PC_CASE_SENSITIVE);
+  if (res == 0)
+    return true;
+  if (0 < res || errno != EINVAL)
+    return false;
+#endif
+
+#ifdef DARWIN_OS
+  /* It is not clear whether this section is needed.  For now, rely on
+     pathconf and skip this section.  If pathconf does not work,
+     please recompile Emacs with -DDARWIN_OS_CASE_SENSITIVE_FIXME=1 or
+     -DDARWIN_OS_CASE_SENSITIVE_FIXME=2, and file a bug report saying
+     whether this fixed your problem.  */
+# ifndef DARWIN_OS_CASE_SENSITIVE_FIXME
+  int DARWIN_OS_CASE_SENSITIVE_FIXME = 0;
 # endif
-#elif defined DARWIN_OS
-  /* The following is based on
-     http://lists.apple.com/archives/darwin-dev/2007/Apr/msg00010.html.  */
-  struct attrlist alist;
-  unsigned char buffer[sizeof (vol_capabilities_attr_t) + sizeof (size_t)];
-
-  memset (&alist, 0, sizeof (alist));
-  alist.volattr = ATTR_VOL_CAPABILITIES;
-  if (getattrlist (filename, &alist, buffer, sizeof (buffer), 0)
-      || !(alist.volattr & ATTR_VOL_CAPABILITIES))
-    return 0;
-  vol_capabilities_attr_t *vcaps = buffer;
-  return !(vcaps->capabilities[0] & VOL_CAP_FMT_CASE_SENSITIVE);
+
+  if (DARWIN_OS_CASE_SENSITIVE_FIXME == 1)
+    {
+      /* This is based on developer.apple.com's getattrlist man page.  */
+      struct attrlist alist = {.volattr = ATTR_VOL_CAPABILITIES};
+      struct vol_capabilities_attr_t vcaps;
+      if (getattrlist (filename, &alist, &vcaps, sizeof vcaps, 0) == 0)
+       {
+         if (vcaps.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE)
+           return ! (vcaps.capabilities[VOL_CAPABILITIES_FORMAT]
+                     & VOL_CAP_FMT_CASE_SENSITIVE);
+       }
+      else if (errno != EINVAL)
+       return false;
+    }
+  else if (DARWIN_OS_CASE_SENSITIVE_FIXME == 2)
+    {
+      /* The following is based on
+        http://lists.apple.com/archives/darwin-dev/2007/Apr/msg00010.html.  */
+      struct attrlist alist;
+      unsigned char buffer[sizeof (vol_capabilities_attr_t) + sizeof (size_t)];
+
+      memset (&alist, 0, sizeof (alist));
+      alist.volattr = ATTR_VOL_CAPABILITIES;
+      if (getattrlist (filename, &alist, buffer, sizeof (buffer), 0)
+         || !(alist.volattr & ATTR_VOL_CAPABILITIES))
+       return 0;
+      vol_capabilities_attr_t *vcaps = buffer;
+      return !(vcaps->capabilities[0] & VOL_CAP_FMT_CASE_SENSITIVE);
+    }
+#endif
+
+#if defined CYGWIN || defined DOS_NT
+  return true;
 #else
-  return 0;
+  return false;
 #endif
 }
 
@@ -2349,7 +2378,7 @@ This is what happens in interactive use with M-x.  */)
   /* If the filesystem is case-insensitive and the file names are
      identical but for the case, don't ask for confirmation: they
      simply want to change the letter-case of the file name.  */
-  if ((!(file_name_case_insensitive_p (SSDATA (encoded_file)))
+  if ((! file_name_case_insensitive_p (SSDATA (encoded_file))
        || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))
       && ((NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists))))
     barf_or_query_if_file_exists (newname, false, "rename to it",



reply via email to

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