aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2019-09-06 14:30:33 -0700
committerPaul Eggert2019-09-06 14:31:38 -0700
commita59839d7556ef85058e09b005f0ff32e59b20ec3 (patch)
tree7e4eb3909246dde8efdcaecd77cfd41e75b93593
parent5b117511aa1b5c451773891b505a7098a67f9532 (diff)
downloademacs-a59839d7556ef85058e09b005f0ff32e59b20ec3.tar.gz
emacs-a59839d7556ef85058e09b005f0ff32e59b20ec3.zip
file-truename now uses realpath for local files
This uses fewer syscalls on GNU/Linux and other GNUish platforms. * lisp/files.el (file-truename): Try fileio--truename if there are no handlers. * src/fileio.c: Include stdlib.h, for realpath. (Ffileio__truename): New function.
-rw-r--r--lisp/files.el11
-rw-r--r--src/fileio.c42
2 files changed, 50 insertions, 3 deletions
diff --git a/lisp/files.el b/lisp/files.el
index ce4dd99bd53..d32c6acb82c 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1307,9 +1307,14 @@ containing it, until no links are left at any level.
1307 (let ((handler (find-file-name-handler filename 'file-truename))) 1307 (let ((handler (find-file-name-handler filename 'file-truename)))
1308 ;; For file name that has a special handler, call handler. 1308 ;; For file name that has a special handler, call handler.
1309 ;; This is so that ange-ftp can save time by doing a no-op. 1309 ;; This is so that ange-ftp can save time by doing a no-op.
1310 (if handler 1310 (or
1311 (setq filename (funcall handler 'file-truename filename) 1311 (if handler
1312 done t) 1312 (setq filename (funcall handler 'file-truename filename)
1313 done t)
1314 (condition-case nil
1315 (setq filename (fileio--truename filename)
1316 done t)
1317 (file-missing nil)))
1313 (let ((dir (or (file-name-directory filename) default-directory)) 1318 (let ((dir (or (file-name-directory filename) default-directory))
1314 target dirfile) 1319 target dirfile)
1315 ;; Get the truename of the directory. 1320 ;; Get the truename of the directory.
diff --git a/src/fileio.c b/src/fileio.c
index 968a55e5956..adf2f3d9705 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
20#include <config.h> 20#include <config.h>
21#include <limits.h> 21#include <limits.h>
22#include <fcntl.h> 22#include <fcntl.h>
23#include <stdlib.h>
23#include "sysstdio.h" 24#include "sysstdio.h"
24#include <sys/types.h> 25#include <sys/types.h>
25#include <sys/stat.h> 26#include <sys/stat.h>
@@ -2693,6 +2694,46 @@ file_name_absolute_p (char const *filename)
2693 && (!filename[1] || IS_DIRECTORY_SEP (filename[1]) 2694 && (!filename[1] || IS_DIRECTORY_SEP (filename[1])
2694 || user_homedir (&filename[1])))); 2695 || user_homedir (&filename[1]))));
2695} 2696}
2697
2698DEFUN ("fileio--truename", Ffileio__truename, Sfileio__truename, 1, 1, 0,
2699 doc: /* Return the true name of FILENAME, without file name handlers.
2700
2701The returned string is an absolute file name that does not involve
2702\".\", \"..\", or symbolic links. Signal an error if FILENAME does
2703not exist or if its true name cannot be determined. */)
2704 (Lisp_Object filename)
2705{
2706 CHECK_STRING (filename);
2707 Lisp_Object absname = Fexpand_file_name (filename, Qnil);
2708 Lisp_Object encoded_absname = ENCODE_FILE (absname);
2709 ptrdiff_t encoded_len = SBYTES (encoded_absname);
2710 char *encoded = SSDATA (encoded_absname);
2711 bool append_slash = (1 < encoded_len
2712 && IS_DIRECTORY_SEP (encoded[encoded_len - 1])
2713 && !IS_DIRECTORY_SEP (encoded[encoded_len - 2]));
2714 char *truename = realpath (encoded, NULL);
2715 if (!truename)
2716 report_file_error ("Deriving truename", filename);
2717 ptrdiff_t truename_len = strlen (truename);
2718 if (truename_len == encoded_len - append_slash
2719 && memcmp (truename, encoded, truename_len) == 0)
2720 {
2721 /* ABSNAME is already the true name. */
2722 xfree (truename);
2723 return absname;
2724 }
2725 else
2726 {
2727 if (append_slash)
2728 {
2729 truename = xrealloc (truename, truename_len + 2);
2730 strcpy (truename + truename_len, "/");
2731 }
2732 Lisp_Object unibyte_truename = build_unibyte_string (truename);
2733 xfree (truename);
2734 return DECODE_FILE (unibyte_truename);
2735 }
2736}
2696 2737
2697DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0, 2738DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
2698 doc: /* Return t if file FILENAME exists (whether or not you can read it). 2739 doc: /* Return t if file FILENAME exists (whether or not you can read it).
@@ -6428,6 +6469,7 @@ This includes interactive calls to `delete-file' and
6428 defsubr (&Sadd_name_to_file); 6469 defsubr (&Sadd_name_to_file);
6429 defsubr (&Smake_symbolic_link); 6470 defsubr (&Smake_symbolic_link);
6430 defsubr (&Sfile_name_absolute_p); 6471 defsubr (&Sfile_name_absolute_p);
6472 defsubr (&Sfileio__truename);
6431 defsubr (&Sfile_exists_p); 6473 defsubr (&Sfile_exists_p);
6432 defsubr (&Sfile_executable_p); 6474 defsubr (&Sfile_executable_p);
6433 defsubr (&Sfile_readable_p); 6475 defsubr (&Sfile_readable_p);