aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
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",