aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKen Brown2019-07-15 09:32:49 -0400
committerKen Brown2019-07-21 10:40:54 -0400
commit8b13ec1d7022b05ce71982c83f320d5272b92de7 (patch)
tree19e21f261d255ca52d9de7fe7e181579cde0c056 /src
parent0c48c0d0b241c1f3d089be033a7dea3a9b947ca5 (diff)
downloademacs-8b13ec1d7022b05ce71982c83f320d5272b92de7.tar.gz
emacs-8b13ec1d7022b05ce71982c83f320d5272b92de7.zip
Fix expand-file-name for names starting with '~'
* src/fileio.c: (file_name_absolute_no_tilde_p): New static function. (Fexpand_file_name): If the current buffer's default-directory starts with "~user" where "user" is not a valid user name, don't give the '~' a special meaning. Just treat the value of default-directory as a relative name. (Bug#36502) * test/src/fileio-tests.el (fileio-tests--relative-default-directory): Add a test.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c68
1 files changed, 44 insertions, 24 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 7f83267956c..4c7625cad4a 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -737,6 +737,13 @@ For that reason, you should normally use `make-temp-file' instead. */)
737 empty_unibyte_string, Qnil); 737 empty_unibyte_string, Qnil);
738} 738}
739 739
740/* NAME must be a string. */
741static bool
742file_name_absolute_no_tilde_p (Lisp_Object name)
743{
744 return IS_ABSOLUTE_FILE_NAME (SSDATA (name));
745}
746
740DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, 747DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
741 doc: /* Convert filename NAME to absolute, and canonicalize it. 748 doc: /* Convert filename NAME to absolute, and canonicalize it.
742Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative 749Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative
@@ -807,41 +814,54 @@ the root directory. */)
807 error ("Invalid handler in `file-name-handler-alist'"); 814 error ("Invalid handler in `file-name-handler-alist'");
808 } 815 }
809 816
817 /* As a last resort, we may have to use the root as
818 default_directory below. */
819 Lisp_Object root;
820#ifdef DOS_NT
821 /* "/" is not considered a root directory on DOS_NT, so using it
822 as default_directory causes an infinite recursion in, e.g.,
823 the following:
824
825 (let (default-directory)
826 (expand-file-name "a"))
827
828 To avoid this, we use the root of the current drive. */
829 root = build_string (emacs_root_dir ());
830#else
831 root = build_string ("/");
832#endif
810 833
811 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ 834 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */
812 if (NILP (default_directory)) 835 if (NILP (default_directory))
813 { 836 {
814 Lisp_Object dir = BVAR (current_buffer, directory); 837 Lisp_Object dir = BVAR (current_buffer, directory);
815 /* The buffer's default-directory should be absolute. If it 838 /* The buffer's default-directory should be absolute or should
816 isn't, try to expand it relative to invocation-directory. 839 start with `~'. If it isn't absolute, we replace it by its
817 But we have to be careful to avoid an infinite loop, because 840 expansion relative to a known absolute name ABSDIR, which is
818 the code in emacs.c that sets Vinvocation_directory might 841 the invocation-directory if the latter is absolute, or the
819 call Fexpand_file_name. */ 842 root otherwise.
843
844 In case default-directory starts with `~' or `~user', where
845 USER is a valid user name, this correctly expands it (and
846 ABSDIR plays no role). If USER is not a valid user name, the
847 leading `~' loses its special meaning and is retained as part
848 of the expanded name. */
820 if (STRINGP (dir)) 849 if (STRINGP (dir))
821 { 850 {
822 if (!NILP (Ffile_name_absolute_p (dir))) 851 if (file_name_absolute_no_tilde_p (dir))
823 default_directory = dir; 852 default_directory = dir;
824 else if (STRINGP (Vinvocation_directory) 853 else
825 && !NILP (Ffile_name_absolute_p (Vinvocation_directory))) 854 {
826 default_directory = Fexpand_file_name (dir, Vinvocation_directory); 855 Lisp_Object absdir
856 = STRINGP (Vinvocation_directory)
857 && file_name_absolute_no_tilde_p (Vinvocation_directory)
858 ? Vinvocation_directory : root;
859 default_directory = Fexpand_file_name (dir, absdir);
860 }
827 } 861 }
828 } 862 }
829 if (! STRINGP (default_directory)) 863 if (! STRINGP (default_directory))
830 { 864 default_directory = root;
831#ifdef DOS_NT
832 /* "/" is not considered a root directory on DOS_NT, so using "/"
833 here causes an infinite recursion in, e.g., the following:
834
835 (let (default-directory)
836 (expand-file-name "a"))
837
838 To avoid this, we set default_directory to the root of the
839 current drive. */
840 default_directory = build_string (emacs_root_dir ());
841#else
842 default_directory = build_string ("/");
843#endif
844 }
845 865
846 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); 866 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name);
847 if (!NILP (handler)) 867 if (!NILP (handler))