]> git.eshelyaron.com Git - emacs.git/commitdiff
file-truename now uses realpath for local files
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 6 Sep 2019 21:30:33 +0000 (14:30 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 6 Sep 2019 21:31:38 +0000 (14:31 -0700)
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.

lisp/files.el
src/fileio.c

index ce4dd99bd535906f6df0d77bb418a14c2814f5a5..d32c6acb82cbfcbf554c73571467c8aafe1f22bd 100644 (file)
@@ -1307,9 +1307,14 @@ containing it, until no links are left at any level.
       (let ((handler (find-file-name-handler filename 'file-truename)))
        ;; For file name that has a special handler, call handler.
        ;; This is so that ange-ftp can save time by doing a no-op.
-       (if handler
-           (setq filename (funcall handler 'file-truename filename)
-                 done t)
+       (or
+        (if handler
+            (setq filename (funcall handler 'file-truename filename)
+                  done t)
+          (condition-case nil
+              (setq filename (fileio--truename filename)
+                    done t)
+            (file-missing nil)))
          (let ((dir (or (file-name-directory filename) default-directory))
                target dirfile)
            ;; Get the truename of the directory.
index 968a55e595615599d4f85890568523ac866fcac9..adf2f3d9705f5065e47cc6cf6765ce4ff1df2dac 100644 (file)
@@ -20,6 +20,7 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <limits.h>
 #include <fcntl.h>
+#include <stdlib.h>
 #include "sysstdio.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -2693,6 +2694,46 @@ file_name_absolute_p (char const *filename)
              && (!filename[1] || IS_DIRECTORY_SEP (filename[1])
                  || user_homedir (&filename[1]))));
 }
+
+DEFUN ("fileio--truename", Ffileio__truename, Sfileio__truename, 1, 1, 0,
+       doc: /* Return the true name of FILENAME, without file name handlers.
+
+The returned string is an absolute file name that does not involve
+\".\", \"..\", or symbolic links.  Signal an error if FILENAME does
+not exist or if its true name cannot be determined.  */)
+     (Lisp_Object filename)
+{
+  CHECK_STRING (filename);
+  Lisp_Object absname = Fexpand_file_name (filename, Qnil);
+  Lisp_Object encoded_absname = ENCODE_FILE (absname);
+  ptrdiff_t encoded_len = SBYTES (encoded_absname);
+  char *encoded = SSDATA (encoded_absname);
+  bool append_slash = (1 < encoded_len
+                      && IS_DIRECTORY_SEP (encoded[encoded_len - 1])
+                      && !IS_DIRECTORY_SEP (encoded[encoded_len - 2]));
+  char *truename = realpath (encoded, NULL);
+  if (!truename)
+    report_file_error ("Deriving truename", filename);
+  ptrdiff_t truename_len = strlen (truename);
+  if (truename_len == encoded_len - append_slash
+      && memcmp (truename, encoded, truename_len) == 0)
+    {
+      /* ABSNAME is already the true name.  */
+      xfree (truename);
+      return absname;
+    }
+  else
+    {
+      if (append_slash)
+       {
+         truename = xrealloc (truename, truename_len + 2);
+         strcpy (truename + truename_len, "/");
+       }
+      Lisp_Object unibyte_truename = build_unibyte_string (truename);
+      xfree (truename);
+      return DECODE_FILE (unibyte_truename);
+    }
+}
 \f
 DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
        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
   defsubr (&Sadd_name_to_file);
   defsubr (&Smake_symbolic_link);
   defsubr (&Sfile_name_absolute_p);
+  defsubr (&Sfileio__truename);
   defsubr (&Sfile_exists_p);
   defsubr (&Sfile_executable_p);
   defsubr (&Sfile_readable_p);