aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-09-15 22:15:04 -0700
committerPaul Eggert2019-09-15 22:15:28 -0700
commitbe828883475eddff0bb8cf6825f0d3383391c122 (patch)
treea187ddd00d189fea525498c07cf4c4e28768bb08 /src
parent5711c076dc63ecc0907f2b9cfe04035e0bd6a0b4 (diff)
downloademacs-be828883475eddff0bb8cf6825f0d3383391c122.tar.gz
emacs-be828883475eddff0bb8cf6825f0d3383391c122.zip
Fix some file-name-case-insensitive glitches
* src/fileio.c (file_name_directory): New static function, broken out of Ffile_name_directory. (file_name_case_insensitive_err, Ffile_writable_p, Fdo_auto_save): Use it. (file_name_case_insensitive_err): Rename from file_name_case_insensitive_p. Accept an unencoded Lisp_Object rather than an encoded char *, so that platforms other than Cygwin and macOS need not encode the file name. Return an int -1, 0, errno rather than a bool (setting errno if false), so that the caller can distinguish an error from false. All callers changed. (Ffile_name_case_insensitive_p): Don’t issue system calls on platforms other than Cygwin and macOS. Fix bug that broke the attempt to move up the filesystem tree (it moved up only one level).
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c86
1 files changed, 50 insertions, 36 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 34afbc23da7..c129f19872e 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -134,6 +134,7 @@ static dev_t timestamp_file_system;
134 is added here. */ 134 is added here. */
135static Lisp_Object Vwrite_region_annotation_buffers; 135static Lisp_Object Vwrite_region_annotation_buffers;
136 136
137static Lisp_Object file_name_directory (Lisp_Object);
137static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, 138static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
138 Lisp_Object *, struct coding_system *); 139 Lisp_Object *, struct coding_system *);
139static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, 140static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
@@ -356,6 +357,15 @@ Given a Unix syntax file name, returns a string ending in slash. */)
356 return STRINGP (handled_name) ? handled_name : Qnil; 357 return STRINGP (handled_name) ? handled_name : Qnil;
357 } 358 }
358 359
360 return file_name_directory (filename);
361}
362
363/* Return the directory component of FILENAME, or nil if FILENAME does
364 not contain a directory component. */
365
366static Lisp_Object
367file_name_directory (Lisp_Object filename)
368{
359 char *beg = SSDATA (filename); 369 char *beg = SSDATA (filename);
360 char const *p = beg + SBYTES (filename); 370 char const *p = beg + SBYTES (filename);
361 371
@@ -2369,41 +2379,48 @@ internal_delete_file (Lisp_Object filename)
2369 return NILP (tem); 2379 return NILP (tem);
2370} 2380}
2371 2381
2372/* Filesystems are case-sensitive on all supported systems except 2382/* Return -1 if FILE is a case-insensitive file name, 0 if not,
2373 MS-Windows, MS-DOS, Cygwin, and Mac OS X. They are always 2383 and a positive errno value if the result cannot be determined. */
2374 case-insensitive on the first two, but they may or may not be
2375 case-insensitive on Cygwin and OS X. The following function
2376 attempts to provide a runtime test on those two systems. If the
2377 test is not conclusive, we assume case-insensitivity on Cygwin and
2378 case-sensitivity on Mac OS X.
2379
2380 FIXME: Mounted filesystems on Posix hosts, like Samba shares or
2381 NFS-mounted Windows volumes, might be case-insensitive. Can we
2382 detect this? */
2383 2384
2384static bool 2385static int
2385file_name_case_insensitive_p (const char *filename) 2386file_name_case_insensitive_err (Lisp_Object file)
2386{ 2387{
2387 /* Use pathconf with _PC_CASE_INSENSITIVE or _PC_CASE_SENSITIVE if 2388 /* Filesystems are case-sensitive on all supported systems except
2388 those flags are available. As of this writing (2017-05-20), 2389 MS-Windows, MS-DOS, Cygwin, and macOS. They are always
2390 case-insensitive on the first two, but they may or may not be
2391 case-insensitive on Cygwin and macOS so do a runtime test on
2392 those two systems. If the test is not conclusive, assume
2393 case-insensitivity on Cygwin and case-sensitivity on macOS.
2394
2395 FIXME: Mounted filesystems on Posix hosts, like Samba shares or
2396 NFS-mounted Windows volumes, might be case-insensitive. Can we
2397 detect this?
2398
2399 Use pathconf with _PC_CASE_INSENSITIVE or _PC_CASE_SENSITIVE if
2400 those flags are available. As of this writing (2019-09-15),
2389 Cygwin is the only platform known to support the former (starting 2401 Cygwin is the only platform known to support the former (starting
2390 with Cygwin-2.6.1), and macOS is the only platform known to 2402 with Cygwin-2.6.1), and macOS is the only platform known to
2391 support the latter. */ 2403 support the latter. */
2392 2404
2393#ifdef _PC_CASE_INSENSITIVE 2405#if defined _PC_CASE_INSENSITIVE || defined _PC_CASE_SENSITIVE
2406 char *filename = SSDATA (ENCODE_FILE (file));
2407# ifdef _PC_CASE_INSENSITIVE
2394 long int res = pathconf (filename, _PC_CASE_INSENSITIVE); 2408 long int res = pathconf (filename, _PC_CASE_INSENSITIVE);
2395 if (res >= 0) 2409 if (res >= 0)
2396 return res > 0; 2410 return - (res > 0);
2397#elif defined _PC_CASE_SENSITIVE 2411# else
2398 long int res = pathconf (filename, _PC_CASE_SENSITIVE); 2412 long int res = pathconf (filename, _PC_CASE_SENSITIVE);
2399 if (res >= 0) 2413 if (res >= 0)
2400 return res == 0; 2414 return - (res == 0);
2415# endif
2416 if (errno != EINVAL)
2417 return errno;
2401#endif 2418#endif
2402 2419
2403#if defined CYGWIN || defined DOS_NT 2420#if defined CYGWIN || defined DOS_NT
2404 return true; 2421 return -1;
2405#else 2422#else
2406 return false; 2423 return 0;
2407#endif 2424#endif
2408} 2425}
2409 2426
@@ -2426,21 +2443,18 @@ The arg must be a string. */)
2426 2443
2427 /* If the file doesn't exist, move up the filesystem tree until we 2444 /* If the file doesn't exist, move up the filesystem tree until we
2428 reach an existing directory or the root. */ 2445 reach an existing directory or the root. */
2429 if (NILP (Ffile_exists_p (filename))) 2446 while (true)
2430 { 2447 {
2431 filename = Ffile_name_directory (filename); 2448 int err = file_name_case_insensitive_err (filename);
2432 while (NILP (Ffile_exists_p (filename))) 2449 if (! (err == ENOENT || err == ENOTDIR))
2433 { 2450 return err < 0 ? Qt : Qnil;
2434 Lisp_Object newname = expand_and_dir_to_file (filename); 2451 Lisp_Object parent = file_name_directory (filename);
2435 /* Avoid infinite loop if the root is reported as non-existing 2452 /* Avoid infinite loop if the root is reported as non-existing
2436 (impossible?). */ 2453 (impossible?). */
2437 if (!NILP (Fstring_equal (newname, filename))) 2454 if (!NILP (Fstring_equal (parent, filename)))
2438 break; 2455 return Qnil;
2439 filename = newname; 2456 filename = parent;
2440 }
2441 } 2457 }
2442 filename = ENCODE_FILE (filename);
2443 return file_name_case_insensitive_p (SSDATA (filename)) ? Qt : Qnil;
2444} 2458}
2445 2459
2446DEFUN ("rename-file", Frename_file, Srename_file, 2, 3, 2460DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
@@ -2790,7 +2804,7 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2790 if (errno != ENOENT) 2804 if (errno != ENOENT)
2791 return Qnil; 2805 return Qnil;
2792 2806
2793 dir = Ffile_name_directory (absname); 2807 dir = file_name_directory (absname);
2794 eassert (!NILP (dir)); 2808 eassert (!NILP (dir));
2795#ifdef MSDOS 2809#ifdef MSDOS
2796 dir = Fdirectory_file_name (dir); 2810 dir = Fdirectory_file_name (dir);
@@ -5822,7 +5836,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5822 if (!NILP (Vrun_hooks)) 5836 if (!NILP (Vrun_hooks))
5823 { 5837 {
5824 Lisp_Object dir; 5838 Lisp_Object dir;
5825 dir = Ffile_name_directory (listfile); 5839 dir = file_name_directory (listfile);
5826 if (NILP (Ffile_directory_p (dir))) 5840 if (NILP (Ffile_directory_p (dir)))
5827 internal_condition_case_1 (do_auto_save_make_dir, 5841 internal_condition_case_1 (do_auto_save_make_dir,
5828 dir, Qt, 5842 dir, Qt,