aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-11-14 09:08:06 -0800
committerPaul Eggert2016-11-14 09:09:48 -0800
commit2f5e0b1bf7b0ac4f450847db34d599a072020600 (patch)
treef653be0ce0b66b4e8c507f4e57a6a0bbca3ae142 /src
parent3625e6ce9352942a4db980dd203b590cdaf821df (diff)
downloademacs-2f5e0b1bf7b0ac4f450847db34d599a072020600.tar.gz
emacs-2f5e0b1bf7b0ac4f450847db34d599a072020600.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c93
1 files changed, 61 insertions, 32 deletions
diff --git a/src/fileio.c b/src/fileio.c
index f3f8f421618..eec3591ff6e 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2236,13 +2236,10 @@ internal_delete_file (Lisp_Object filename)
2236 return NILP (tem); 2236 return NILP (tem);
2237} 2237}
2238 2238
2239/* Filesystems are case-sensitive on all supported systems except 2239/* Return true if FILENAME is on a case-insensitive file system.
2240 MS-Windows, MS-DOS, Cygwin, and Mac OS X. They are always 2240 Use a runtime test if available. Otherwise, assume the file system
2241 case-insensitive on the first two, but they may or may not be 2241 is case-insensitive on Microsoft-based platforms and case-sensitive
2242 case-insensitive on Cygwin and OS X. The following function 2242 elsewhere.
2243 attempts to provide a runtime test on those two systems. If the
2244 test is not conclusive, we assume case-insensitivity on Cygwin and
2245 case-sensitivity on Mac OS X.
2246 2243
2247 FIXME: Mounted filesystems on Posix hosts, like Samba shares or 2244 FIXME: Mounted filesystems on Posix hosts, like Samba shares or
2248 NFS-mounted Windows volumes, might be case-insensitive. Can we 2245 NFS-mounted Windows volumes, might be case-insensitive. Can we
@@ -2251,33 +2248,65 @@ internal_delete_file (Lisp_Object filename)
2251static bool 2248static bool
2252file_name_case_insensitive_p (const char *filename) 2249file_name_case_insensitive_p (const char *filename)
2253{ 2250{
2254#ifdef DOS_NT 2251#ifdef _PC_CASE_INSENSITIVE
2255 return 1;
2256#elif defined CYGWIN
2257/* As of Cygwin-2.6.1, pathconf supports _PC_CASE_INSENSITIVE. */
2258# ifdef _PC_CASE_INSENSITIVE
2259 int res = pathconf (filename, _PC_CASE_INSENSITIVE); 2252 int res = pathconf (filename, _PC_CASE_INSENSITIVE);
2260 if (res < 0) 2253 if (0 < res)
2261 return 1; 2254 return true;
2262 return res > 0; 2255 if (res == 0 || errno != EINVAL)
2263# else 2256 return false;
2264 return 1; 2257#elif defined _PC_CASE_SENSITIVE
2258 int res = pathconf (filename, _PC_CASE_SENSITIVE);
2259 if (res == 0)
2260 return true;
2261 if (0 < res || errno != EINVAL)
2262 return false;
2263#endif
2264
2265#ifdef DARWIN_OS
2266 /* It is not clear whether this section is needed. For now, rely on
2267 pathconf and skip this section. If pathconf does not work,
2268 please recompile Emacs with -DDARWIN_OS_CASE_SENSITIVE_FIXME=1 or
2269 -DDARWIN_OS_CASE_SENSITIVE_FIXME=2, and file a bug report saying
2270 whether this fixed your problem. */
2271# ifndef DARWIN_OS_CASE_SENSITIVE_FIXME
2272 int DARWIN_OS_CASE_SENSITIVE_FIXME = 0;
2265# endif 2273# endif
2266#elif defined DARWIN_OS 2274
2267 /* The following is based on 2275 if (DARWIN_OS_CASE_SENSITIVE_FIXME == 1)
2268 http://lists.apple.com/archives/darwin-dev/2007/Apr/msg00010.html. */ 2276 {
2269 struct attrlist alist; 2277 /* This is based on developer.apple.com's getattrlist man page. */
2270 unsigned char buffer[sizeof (vol_capabilities_attr_t) + sizeof (size_t)]; 2278 struct attrlist alist = {.volattr = ATTR_VOL_CAPABILITIES};
2271 2279 struct vol_capabilities_attr_t vcaps;
2272 memset (&alist, 0, sizeof (alist)); 2280 if (getattrlist (filename, &alist, &vcaps, sizeof vcaps, 0) == 0)
2273 alist.volattr = ATTR_VOL_CAPABILITIES; 2281 {
2274 if (getattrlist (filename, &alist, buffer, sizeof (buffer), 0) 2282 if (vcaps.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE)
2275 || !(alist.volattr & ATTR_VOL_CAPABILITIES)) 2283 return ! (vcaps.capabilities[VOL_CAPABILITIES_FORMAT]
2276 return 0; 2284 & VOL_CAP_FMT_CASE_SENSITIVE);
2277 vol_capabilities_attr_t *vcaps = buffer; 2285 }
2278 return !(vcaps->capabilities[0] & VOL_CAP_FMT_CASE_SENSITIVE); 2286 else if (errno != EINVAL)
2287 return false;
2288 }
2289 else if (DARWIN_OS_CASE_SENSITIVE_FIXME == 2)
2290 {
2291 /* The following is based on
2292 http://lists.apple.com/archives/darwin-dev/2007/Apr/msg00010.html. */
2293 struct attrlist alist;
2294 unsigned char buffer[sizeof (vol_capabilities_attr_t) + sizeof (size_t)];
2295
2296 memset (&alist, 0, sizeof (alist));
2297 alist.volattr = ATTR_VOL_CAPABILITIES;
2298 if (getattrlist (filename, &alist, buffer, sizeof (buffer), 0)
2299 || !(alist.volattr & ATTR_VOL_CAPABILITIES))
2300 return 0;
2301 vol_capabilities_attr_t *vcaps = buffer;
2302 return !(vcaps->capabilities[0] & VOL_CAP_FMT_CASE_SENSITIVE);
2303 }
2304#endif
2305
2306#if defined CYGWIN || defined DOS_NT
2307 return true;
2279#else 2308#else
2280 return 0; 2309 return false;
2281#endif 2310#endif
2282} 2311}
2283 2312
@@ -2349,7 +2378,7 @@ This is what happens in interactive use with M-x. */)
2349 /* If the filesystem is case-insensitive and the file names are 2378 /* If the filesystem is case-insensitive and the file names are
2350 identical but for the case, don't ask for confirmation: they 2379 identical but for the case, don't ask for confirmation: they
2351 simply want to change the letter-case of the file name. */ 2380 simply want to change the letter-case of the file name. */
2352 if ((!(file_name_case_insensitive_p (SSDATA (encoded_file))) 2381 if ((! file_name_case_insensitive_p (SSDATA (encoded_file))
2353 || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))) 2382 || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))
2354 && ((NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists)))) 2383 && ((NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists))))
2355 barf_or_query_if_file_exists (newname, false, "rename to it", 2384 barf_or_query_if_file_exists (newname, false, "rename to it",