aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKen Brown2016-11-12 19:00:35 -0500
committerKen Brown2016-11-12 21:54:45 -0500
commit2809012c8f9485d8dc54b186f989f289b2797892 (patch)
tree6958ef0540eaada506c32f1546147a9fd26b8a3b /src
parent462804da9ce5a2ffc8c6ad4887d97116cf868d13 (diff)
downloademacs-2809012c8f9485d8dc54b186f989f289b2797892.tar.gz
emacs-2809012c8f9485d8dc54b186f989f289b2797892.zip
Check case-sensitivity when renaming files
* src/fileio.c (file_name_case_insensitive_p) (Ffile_name_case_insensitive_p): New functions. (Frename_file): Allow renames that simply change case when the FILE argument is on a case-insensitive filesystem. (Bug#24441) * lisp/dired-aux.el (dired-do-create-files): Use 'file-name-case-insensitive-p' instead of 'system-type' to check for case-insensitivity. (Bug#24441) * doc/lispref/files.texi (Truenames): Document 'file-name-case-insensitive-p'.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c97
1 files changed, 83 insertions, 14 deletions
diff --git a/src/fileio.c b/src/fileio.c
index d3da0fb63d7..f3f8f421618 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -25,6 +25,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25#include <sys/stat.h> 25#include <sys/stat.h>
26#include <unistd.h> 26#include <unistd.h>
27 27
28#ifdef DARWIN_OS
29#include <sys/attr.h>
30#endif
31
28#ifdef HAVE_PWD_H 32#ifdef HAVE_PWD_H
29#include <pwd.h> 33#include <pwd.h>
30#endif 34#endif
@@ -2232,6 +2236,72 @@ internal_delete_file (Lisp_Object filename)
2232 return NILP (tem); 2236 return NILP (tem);
2233} 2237}
2234 2238
2239/* Filesystems are case-sensitive on all supported systems except
2240 MS-Windows, MS-DOS, Cygwin, and Mac OS X. They are always
2241 case-insensitive on the first two, but they may or may not be
2242 case-insensitive on Cygwin and OS X. The following function
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
2247 FIXME: Mounted filesystems on Posix hosts, like Samba shares or
2248 NFS-mounted Windows volumes, might be case-insensitive. Can we
2249 detect this? */
2250
2251static bool
2252file_name_case_insensitive_p (const char *filename)
2253{
2254#ifdef DOS_NT
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);
2260 if (res < 0)
2261 return 1;
2262 return res > 0;
2263# else
2264 return 1;
2265# endif
2266#elif defined DARWIN_OS
2267 /* The following is based on
2268 http://lists.apple.com/archives/darwin-dev/2007/Apr/msg00010.html. */
2269 struct attrlist alist;
2270 unsigned char buffer[sizeof (vol_capabilities_attr_t) + sizeof (size_t)];
2271
2272 memset (&alist, 0, sizeof (alist));
2273 alist.volattr = ATTR_VOL_CAPABILITIES;
2274 if (getattrlist (filename, &alist, buffer, sizeof (buffer), 0)
2275 || !(alist.volattr & ATTR_VOL_CAPABILITIES))
2276 return 0;
2277 vol_capabilities_attr_t *vcaps = buffer;
2278 return !(vcaps->capabilities[0] & VOL_CAP_FMT_CASE_SENSITIVE);
2279#else
2280 return 0;
2281#endif
2282}
2283
2284DEFUN ("file-name-case-insensitive-p", Ffile_name_case_insensitive_p,
2285 Sfile_name_case_insensitive_p, 1, 1, 0,
2286 doc: /* Return t if file FILENAME is on a case-insensitive filesystem.
2287The arg must be a string. */)
2288 (Lisp_Object filename)
2289{
2290 Lisp_Object handler;
2291
2292 CHECK_STRING (filename);
2293 filename = Fexpand_file_name (filename, Qnil);
2294
2295 /* If the file name has special constructs in it,
2296 call the corresponding file handler. */
2297 handler = Ffind_file_name_handler (filename, Qfile_name_case_insensitive_p);
2298 if (!NILP (handler))
2299 return call2 (handler, Qfile_name_case_insensitive_p, filename);
2300
2301 filename = ENCODE_FILE (filename);
2302 return file_name_case_insensitive_p (SSDATA (filename)) ? Qt : Qnil;
2303}
2304
2235DEFUN ("rename-file", Frename_file, Srename_file, 2, 3, 2305DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
2236 "fRename file: \nGRename %s to file: \np", 2306 "fRename file: \nGRename %s to file: \np",
2237 doc: /* Rename FILE as NEWNAME. Both args must be strings. 2307 doc: /* Rename FILE as NEWNAME. Both args must be strings.
@@ -2251,12 +2321,11 @@ This is what happens in interactive use with M-x. */)
2251 file = Fexpand_file_name (file, Qnil); 2321 file = Fexpand_file_name (file, Qnil);
2252 2322
2253 if ((!NILP (Ffile_directory_p (newname))) 2323 if ((!NILP (Ffile_directory_p (newname)))
2254#ifdef DOS_NT 2324 /* If the filesystem is case-insensitive and the file names are
2255 /* If the file names are identical but for the case, 2325 identical but for the case, don't attempt to move directory
2256 don't attempt to move directory to itself. */ 2326 to itself. */
2257 && (NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))) 2327 && (NILP (Ffile_name_case_insensitive_p (file))
2258#endif 2328 || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))))
2259 )
2260 { 2329 {
2261 Lisp_Object fname = (NILP (Ffile_directory_p (file)) 2330 Lisp_Object fname = (NILP (Ffile_directory_p (file))
2262 ? file : Fdirectory_file_name (file)); 2331 ? file : Fdirectory_file_name (file));
@@ -2277,14 +2346,12 @@ This is what happens in interactive use with M-x. */)
2277 encoded_file = ENCODE_FILE (file); 2346 encoded_file = ENCODE_FILE (file);
2278 encoded_newname = ENCODE_FILE (newname); 2347 encoded_newname = ENCODE_FILE (newname);
2279 2348
2280#ifdef DOS_NT 2349 /* If the filesystem is case-insensitive and the file names are
2281 /* If the file names are identical but for the case, don't ask for 2350 identical but for the case, don't ask for confirmation: they
2282 confirmation: they simply want to change the letter-case of the 2351 simply want to change the letter-case of the file name. */
2283 file name. */ 2352 if ((!(file_name_case_insensitive_p (SSDATA (encoded_file)))
2284 if (NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))) 2353 || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))
2285#endif 2354 && ((NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists))))
2286 if (NILP (ok_if_already_exists)
2287 || INTEGERP (ok_if_already_exists))
2288 barf_or_query_if_file_exists (newname, false, "rename to it", 2355 barf_or_query_if_file_exists (newname, false, "rename to it",
2289 INTEGERP (ok_if_already_exists), false); 2356 INTEGERP (ok_if_already_exists), false);
2290 if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0) 2357 if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0)
@@ -5836,6 +5903,7 @@ syms_of_fileio (void)
5836 DEFSYM (Qmake_directory_internal, "make-directory-internal"); 5903 DEFSYM (Qmake_directory_internal, "make-directory-internal");
5837 DEFSYM (Qmake_directory, "make-directory"); 5904 DEFSYM (Qmake_directory, "make-directory");
5838 DEFSYM (Qdelete_file, "delete-file"); 5905 DEFSYM (Qdelete_file, "delete-file");
5906 DEFSYM (Qfile_name_case_insensitive_p, "file-name-case-insensitive-p");
5839 DEFSYM (Qrename_file, "rename-file"); 5907 DEFSYM (Qrename_file, "rename-file");
5840 DEFSYM (Qadd_name_to_file, "add-name-to-file"); 5908 DEFSYM (Qadd_name_to_file, "add-name-to-file");
5841 DEFSYM (Qmake_symbolic_link, "make-symbolic-link"); 5909 DEFSYM (Qmake_symbolic_link, "make-symbolic-link");
@@ -6099,6 +6167,7 @@ This includes interactive calls to `delete-file' and
6099 defsubr (&Smake_directory_internal); 6167 defsubr (&Smake_directory_internal);
6100 defsubr (&Sdelete_directory_internal); 6168 defsubr (&Sdelete_directory_internal);
6101 defsubr (&Sdelete_file); 6169 defsubr (&Sdelete_file);
6170 defsubr (&Sfile_name_case_insensitive_p);
6102 defsubr (&Srename_file); 6171 defsubr (&Srename_file);
6103 defsubr (&Sadd_name_to_file); 6172 defsubr (&Sadd_name_to_file);
6104 defsubr (&Smake_symbolic_link); 6173 defsubr (&Smake_symbolic_link);