aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-08-11 01:04:30 -0700
committerPaul Eggert2017-08-11 01:07:31 -0700
commita56e6e79613779895975b1762c311bf8fe46f551 (patch)
treea5b61d84922996945ab52f2944b4d7538a626db0 /src
parent179499cde921a28c82400b1674520da245b93bb9 (diff)
downloademacs-a56e6e79613779895975b1762c311bf8fe46f551.tar.gz
emacs-a56e6e79613779895975b1762c311bf8fe46f551.zip
Improve performance for rename-file etc.
Although this does not fix Bug#27986, it is a step forward. I plan to propose a more-significant patch later. * lisp/files.el (directory-name-p): Move from here ... * src/fileio.c (Fdirectory_name_p): ... to here. (directory_like, cp_like_target): New static functions. (Fcopy_file, Frename_file, Fadd_name_to_file) (Fmake_symbolic_link): Use them, to avoid directory-testing syscalls on file names that must be directories if they exist. Omit unnecessary initializations and CHECK_STRING calls. (Frename_file): Don't call file_name_case_insensitive_p twice on the same file. Compare both file names expanded, instead of the old name expanded and the new one unexpanded.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c127
1 files changed, 66 insertions, 61 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 15845e39144..9aae7d997ee 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -267,9 +267,9 @@ Otherwise, return nil.
267A file name is handled if one of the regular expressions in 267A file name is handled if one of the regular expressions in
268`file-name-handler-alist' matches it. 268`file-name-handler-alist' matches it.
269 269
270If OPERATION equals `inhibit-file-name-operation', then we ignore 270If OPERATION equals `inhibit-file-name-operation', then ignore
271any handlers that are members of `inhibit-file-name-handlers', 271any handlers that are members of `inhibit-file-name-handlers',
272but we still do run any other handlers. This lets handlers 272but still do run any other handlers. This lets handlers
273use the standard functions without calling themselves recursively. */) 273use the standard functions without calling themselves recursively. */)
274 (Lisp_Object filename, Lisp_Object operation) 274 (Lisp_Object filename, Lisp_Object operation)
275{ 275{
@@ -583,6 +583,38 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
583 return srclen; 583 return srclen;
584} 584}
585 585
586DEFUN ("directory-name-p", Fdirectory_name_p, Sdirectory_name_p, 1, 1, 0,
587 doc: /* Return non-nil if NAME ends with a directory separator character. */)
588 (Lisp_Object name)
589{
590 CHECK_STRING (name);
591 ptrdiff_t namelen = SBYTES (name);
592 unsigned char c = namelen ? SREF (name, namelen - 1) : 0;
593 return IS_DIRECTORY_SEP (c) ? Qt : Qnil;
594}
595
596/* Return true if NAME must be that of a directory if it exists.
597 When NAME is a directory name, this avoids system calls compared to
598 just calling Ffile_directory_p. */
599
600static bool
601directory_like (Lisp_Object name)
602{
603 return !NILP (Fdirectory_name_p (name)) || !NILP (Ffile_directory_p (name));
604}
605
606/* Return the expansion of NEWNAME, except that if NEWNAME is like a
607 directory then return the expansion of FILE's basename under
608 NEWNAME. This is like how 'cp FILE NEWNAME' works. */
609
610static Lisp_Object
611expand_cp_target (Lisp_Object file, Lisp_Object newname)
612{
613 return (directory_like (newname)
614 ? Fexpand_file_name (Ffile_name_nondirectory (file), newname)
615 : Fexpand_file_name (newname, Qnil));
616}
617
586DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name, 618DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
587 1, 1, 0, 619 1, 1, 0,
588 doc: /* Returns the file name of the directory named DIRECTORY. 620 doc: /* Returns the file name of the directory named DIRECTORY.
@@ -1874,9 +1906,9 @@ This function always sets the file modes of the output file to match
1874the input file. 1906the input file.
1875 1907
1876The optional third argument OK-IF-ALREADY-EXISTS specifies what to do 1908The optional third argument OK-IF-ALREADY-EXISTS specifies what to do
1877if file NEWNAME already exists. If OK-IF-ALREADY-EXISTS is nil, we 1909if file NEWNAME already exists. If OK-IF-ALREADY-EXISTS is nil,
1878signal a `file-already-exists' error without overwriting. If 1910signal a `file-already-exists' error without overwriting. If
1879OK-IF-ALREADY-EXISTS is a number, we request confirmation from the user 1911OK-IF-ALREADY-EXISTS is an integer, request confirmation from the user
1880about overwriting; this is what happens in interactive use with M-x. 1912about overwriting; this is what happens in interactive use with M-x.
1881Any other value for OK-IF-ALREADY-EXISTS means to overwrite the 1913Any other value for OK-IF-ALREADY-EXISTS means to overwrite the
1882existing file. 1914existing file.
@@ -1886,8 +1918,8 @@ last-modified time as the old one. (This works on only some systems.)
1886 1918
1887A prefix arg makes KEEP-TIME non-nil. 1919A prefix arg makes KEEP-TIME non-nil.
1888 1920
1889If PRESERVE-UID-GID is non-nil, we try to transfer the 1921If PRESERVE-UID-GID is non-nil, try to transfer the uid and gid of
1890uid and gid of FILE to NEWNAME. 1922FILE to NEWNAME.
1891 1923
1892If PRESERVE-PERMISSIONS is non-nil, copy permissions of FILE to NEWNAME; 1924If PRESERVE-PERMISSIONS is non-nil, copy permissions of FILE to NEWNAME;
1893this includes the file modes, along with ACL entries and SELinux 1925this includes the file modes, along with ACL entries and SELinux
@@ -1914,16 +1946,8 @@ permissions. */)
1914 struct stat st; 1946 struct stat st;
1915#endif 1947#endif
1916 1948
1917 encoded_file = encoded_newname = Qnil;
1918 CHECK_STRING (file);
1919 CHECK_STRING (newname);
1920
1921 if (!NILP (Ffile_directory_p (newname)))
1922 newname = Fexpand_file_name (Ffile_name_nondirectory (file), newname);
1923 else
1924 newname = Fexpand_file_name (newname, Qnil);
1925
1926 file = Fexpand_file_name (file, Qnil); 1949 file = Fexpand_file_name (file, Qnil);
1950 newname = expand_cp_target (file, newname);
1927 1951
1928 /* If the input file name has special constructs in it, 1952 /* If the input file name has special constructs in it,
1929 call the corresponding file handler. */ 1953 call the corresponding file handler. */
@@ -2304,9 +2328,9 @@ DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
2304 "fRename file: \nGRename %s to file: \np", 2328 "fRename file: \nGRename %s to file: \np",
2305 doc: /* Rename FILE as NEWNAME. Both args must be strings. 2329 doc: /* Rename FILE as NEWNAME. Both args must be strings.
2306If file has names other than FILE, it continues to have those names. 2330If file has names other than FILE, it continues to have those names.
2307Signals a `file-already-exists' error if a file NEWNAME already exists 2331Signal a `file-already-exists' error if a file NEWNAME already exists
2308unless optional third argument OK-IF-ALREADY-EXISTS is non-nil. 2332unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
2309A number as third arg means request confirmation if NEWNAME already exists. 2333An integer third arg means request confirmation if NEWNAME already exists.
2310This is what happens in interactive use with M-x. */) 2334This is what happens in interactive use with M-x. */)
2311 (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists) 2335 (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists)
2312{ 2336{
@@ -2314,24 +2338,22 @@ This is what happens in interactive use with M-x. */)
2314 Lisp_Object encoded_file, encoded_newname, symlink_target; 2338 Lisp_Object encoded_file, encoded_newname, symlink_target;
2315 int dirp = -1; 2339 int dirp = -1;
2316 2340
2317 symlink_target = encoded_file = encoded_newname = Qnil;
2318 CHECK_STRING (file);
2319 CHECK_STRING (newname);
2320 file = Fexpand_file_name (file, Qnil); 2341 file = Fexpand_file_name (file, Qnil);
2321 2342
2322 if ((!NILP (Ffile_directory_p (newname))) 2343 /* If the filesystem is case-insensitive and the file names are
2323 /* If the filesystem is case-insensitive and the file names are 2344 identical but for case, treat it as a change-case request, and do
2324 identical but for the case, don't attempt to move directory 2345 not worry whether NEWNAME exists or whether it is a directory, as
2325 to itself. */ 2346 it is already another name for FILE. */
2326 && (NILP (Ffile_name_case_insensitive_p (file)) 2347 bool case_only_rename = false;
2327 || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))) 2348 if (!NILP (Ffile_name_case_insensitive_p (file)))
2328 { 2349 {
2329 dirp = !NILP (Ffile_directory_p (file)); 2350 newname = Fexpand_file_name (newname, Qnil);
2330 Lisp_Object fname = dirp ? Fdirectory_file_name (file) : file; 2351 case_only_rename = !NILP (Fstring_equal (Fdowncase (file),
2331 newname = Fexpand_file_name (Ffile_name_nondirectory (fname), newname); 2352 Fdowncase (newname)));
2332 } 2353 }
2333 else 2354
2334 newname = Fexpand_file_name (newname, Qnil); 2355 if (!case_only_rename)
2356 newname = expand_cp_target (Fdirectory_file_name (file), newname);
2335 2357
2336 /* If the file name has special constructs in it, 2358 /* If the file name has special constructs in it,
2337 call the corresponding file handler. */ 2359 call the corresponding file handler. */
@@ -2345,15 +2367,9 @@ This is what happens in interactive use with M-x. */)
2345 encoded_file = ENCODE_FILE (file); 2367 encoded_file = ENCODE_FILE (file);
2346 encoded_newname = ENCODE_FILE (newname); 2368 encoded_newname = ENCODE_FILE (newname);
2347 2369
2348 /* If the filesystem is case-insensitive and the file names are 2370 bool plain_rename = (case_only_rename
2349 identical but for the case, don't worry whether the destination 2371 || (!NILP (ok_if_already_exists)
2350 already exists: the caller simply wants to change the letter-case 2372 && !INTEGERP (ok_if_already_exists)));
2351 of the file name. */
2352 bool plain_rename
2353 = ((!NILP (ok_if_already_exists) && !INTEGERP (ok_if_already_exists))
2354 || (file_name_case_insensitive_p (SSDATA (encoded_file))
2355 && ! NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))));
2356
2357 int rename_errno; 2373 int rename_errno;
2358 if (!plain_rename) 2374 if (!plain_rename)
2359 { 2375 {
@@ -2395,7 +2411,7 @@ This is what happens in interactive use with M-x. */)
2395 else 2411 else
2396 { 2412 {
2397 if (dirp < 0) 2413 if (dirp < 0)
2398 dirp = !NILP (Ffile_directory_p (file)); 2414 dirp = directory_like (file);
2399 if (dirp) 2415 if (dirp)
2400 call4 (Qcopy_directory, file, newname, Qt, Qnil); 2416 call4 (Qcopy_directory, file, newname, Qt, Qnil);
2401 else 2417 else
@@ -2414,24 +2430,17 @@ This is what happens in interactive use with M-x. */)
2414DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3, 2430DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3,
2415 "fAdd name to file: \nGName to add to %s: \np", 2431 "fAdd name to file: \nGName to add to %s: \np",
2416 doc: /* Give FILE additional name NEWNAME. Both args must be strings. 2432 doc: /* Give FILE additional name NEWNAME. Both args must be strings.
2417Signals a `file-already-exists' error if a file NEWNAME already exists 2433Signal a `file-already-exists' error if a file NEWNAME already exists
2418unless optional third argument OK-IF-ALREADY-EXISTS is non-nil. 2434unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
2419A number as third arg means request confirmation if NEWNAME already exists. 2435An integer third arg means request confirmation if NEWNAME already exists.
2420This is what happens in interactive use with M-x. */) 2436This is what happens in interactive use with M-x. */)
2421 (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists) 2437 (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists)
2422{ 2438{
2423 Lisp_Object handler; 2439 Lisp_Object handler;
2424 Lisp_Object encoded_file, encoded_newname; 2440 Lisp_Object encoded_file, encoded_newname;
2425 2441
2426 encoded_file = encoded_newname = Qnil;
2427 CHECK_STRING (file);
2428 CHECK_STRING (newname);
2429 file = Fexpand_file_name (file, Qnil); 2442 file = Fexpand_file_name (file, Qnil);
2430 2443 newname = expand_cp_target (file, newname);
2431 if (!NILP (Ffile_directory_p (newname)))
2432 newname = Fexpand_file_name (Ffile_name_nondirectory (file), newname);
2433 else
2434 newname = Fexpand_file_name (newname, Qnil);
2435 2444
2436 /* If the file name has special constructs in it, 2445 /* If the file name has special constructs in it,
2437 call the corresponding file handler. */ 2446 call the corresponding file handler. */
@@ -2471,28 +2480,23 @@ DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
2471 "FMake symbolic link to file: \nGMake symbolic link to file %s: \np", 2480 "FMake symbolic link to file: \nGMake symbolic link to file %s: \np",
2472 doc: /* Make a symbolic link to TARGET, named LINKNAME. 2481 doc: /* Make a symbolic link to TARGET, named LINKNAME.
2473Both args must be strings. 2482Both args must be strings.
2474Signals a `file-already-exists' error if a file LINKNAME already exists 2483Signal a `file-already-exists' error if a file LINKNAME already exists
2475unless optional third argument OK-IF-ALREADY-EXISTS is non-nil. 2484unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
2476A number as third arg means request confirmation if LINKNAME already exists. 2485An integer third arg means request confirmation if LINKNAME already exists.
2477This happens for interactive use with M-x. */) 2486This happens for interactive use with M-x. */)
2478 (Lisp_Object target, Lisp_Object linkname, Lisp_Object ok_if_already_exists) 2487 (Lisp_Object target, Lisp_Object linkname, Lisp_Object ok_if_already_exists)
2479{ 2488{
2480 Lisp_Object handler; 2489 Lisp_Object handler;
2481 Lisp_Object encoded_target, encoded_linkname; 2490 Lisp_Object encoded_target, encoded_linkname;
2482 2491
2483 encoded_target = encoded_linkname = Qnil;
2484 CHECK_STRING (target); 2492 CHECK_STRING (target);
2485 CHECK_STRING (linkname);
2486 /* If the link target has a ~, we must expand it to get 2493 /* If the link target has a ~, we must expand it to get
2487 a truly valid file name. Otherwise, do not expand; 2494 a truly valid file name. Otherwise, do not expand;
2488 we want to permit links to relative file names. */ 2495 we want to permit links to relative file names. */
2489 if (SREF (target, 0) == '~') 2496 if (SREF (target, 0) == '~')
2490 target = Fexpand_file_name (target, Qnil); 2497 target = Fexpand_file_name (target, Qnil);
2491 2498
2492 if (!NILP (Ffile_directory_p (linkname))) 2499 linkname = expand_cp_target (target, linkname);
2493 linkname = Fexpand_file_name (Ffile_name_nondirectory (target), linkname);
2494 else
2495 linkname = Fexpand_file_name (linkname, Qnil);
2496 2500
2497 /* If the file name has special constructs in it, 2501 /* If the file name has special constructs in it,
2498 call the corresponding file handler. */ 2502 call the corresponding file handler. */
@@ -5577,7 +5581,7 @@ and are changed since last auto-saved.
5577Auto-saving writes the buffer into a file 5581Auto-saving writes the buffer into a file
5578so that your editing is not lost if the system crashes. 5582so that your editing is not lost if the system crashes.
5579This file is not the file you visited; that changes only when you save. 5583This file is not the file you visited; that changes only when you save.
5580Normally we run the normal hook `auto-save-hook' before saving. 5584Normally, run the normal hook `auto-save-hook' before saving.
5581 5585
5582A non-nil NO-MESSAGE argument means do not print any message if successful. 5586A non-nil NO-MESSAGE argument means do not print any message if successful.
5583A non-nil CURRENT-ONLY argument means save only current buffer. */) 5587A non-nil CURRENT-ONLY argument means save only current buffer. */)
@@ -6111,7 +6115,7 @@ This applies only to the operation `inhibit-file-name-operation'. */);
6111 Vinhibit_file_name_operation = Qnil; 6115 Vinhibit_file_name_operation = Qnil;
6112 6116
6113 DEFVAR_LISP ("auto-save-list-file-name", Vauto_save_list_file_name, 6117 DEFVAR_LISP ("auto-save-list-file-name", Vauto_save_list_file_name,
6114 doc: /* File name in which we write a list of all auto save file names. 6118 doc: /* File name in which to write a list of all auto save file names.
6115This variable is initialized automatically from `auto-save-list-file-prefix' 6119This variable is initialized automatically from `auto-save-list-file-prefix'
6116shortly after Emacs reads your init file, if you have not yet given it 6120shortly after Emacs reads your init file, if you have not yet given it
6117a non-nil value. */); 6121a non-nil value. */);
@@ -6166,6 +6170,7 @@ This includes interactive calls to `delete-file' and
6166 defsubr (&Sfile_name_nondirectory); 6170 defsubr (&Sfile_name_nondirectory);
6167 defsubr (&Sunhandled_file_name_directory); 6171 defsubr (&Sunhandled_file_name_directory);
6168 defsubr (&Sfile_name_as_directory); 6172 defsubr (&Sfile_name_as_directory);
6173 defsubr (&Sdirectory_name_p);
6169 defsubr (&Sdirectory_file_name); 6174 defsubr (&Sdirectory_file_name);
6170 defsubr (&Smake_temp_name); 6175 defsubr (&Smake_temp_name);
6171 defsubr (&Sexpand_file_name); 6176 defsubr (&Sexpand_file_name);