Function: tramp-sh-handle-expand-file-name

tramp-sh-handle-expand-file-name is a byte-compiled function defined in tramp-sh.el.gz.

Signature

(tramp-sh-handle-expand-file-name NAME &optional DIR)

Documentation

Like expand-file-name for Tramp files.

If the localname part of the given file name starts with "/../" then the result will be a local, non-Tramp, file name.

Source Code

;; Defined in /usr/src/emacs/lisp/net/tramp-sh.el.gz
;; Canonicalization of file names.

(defun tramp-sh-handle-expand-file-name (name &optional dir)
  "Like `expand-file-name' for Tramp files.
If the localname part of the given file name starts with \"/../\" then
the result will be a local, non-Tramp, file name."
  ;; If DIR is not given, use `default-directory' or "/".
  (setq dir (or dir default-directory "/"))
  ;; Handle empty NAME.
  (when (zerop (length name)) (setq name "."))
  ;; On MS Windows, some special file names are not returned properly
  ;; by `file-name-absolute-p'.
  (if (and (eq system-type 'windows-nt)
	   (string-match-p
	    (concat "^\\([[:alpha:]]:\\|" null-device "$\\)") name))
      (tramp-run-real-handler #'expand-file-name (list name dir))
    ;; Unless NAME is absolute, concat DIR and NAME.
    (unless (file-name-absolute-p name)
      (setq name (tramp-compat-file-name-concat dir name)))
    ;; If connection is not established yet, run the real handler.
    (if (not (tramp-connectable-p name))
	(tramp-run-real-handler #'expand-file-name (list name nil))
      ;; Dissect NAME.
      (with-parsed-tramp-file-name name nil
	(unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
	  (setq localname (concat "~/" localname)))
	;; Tilde expansion if necessary.  This needs a shell which
	;; groks tilde expansion!  The function `tramp-find-shell' is
	;; supposed to find such a shell on the remote host.  Please
	;; tell me about it when this doesn't work on your system.
	(when (string-match "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
	  (let ((uname (match-string 1 localname))
		(fname (match-string 2 localname)))
	    ;; We cannot simply apply "~/", because under sudo "~/" is
	    ;; expanded to the local user home directory but to the
	    ;; root home directory.  On the other hand, using always
	    ;; the default user name for tilde expansion is not
	    ;; appropriate either, because ssh and companions might
	    ;; use a user name from the config file.
	    (when (and (string-equal uname "~")
		       (string-match-p "\\`su\\(do\\)?\\'" method))
	      (setq uname (concat uname user)))
	    (setq uname
		  (with-tramp-connection-property v uname
		    (tramp-send-command
		     v
		     (format "cd %s && pwd" (tramp-shell-quote-argument uname)))
		    (with-current-buffer (tramp-get-buffer v)
		      (goto-char (point-min))
		      (buffer-substring (point) (point-at-eol)))))
	    (setq localname (concat uname fname))))
	;; There might be a double slash, for example when "~/"
	;; expands to "/".  Remove this.
	(while (string-match "//" localname)
	  (setq localname (replace-match "/" t t localname)))
	;; Do not keep "/..".
	(when (string-match-p "^/\\.\\.?$" localname)
	  (setq localname "/"))
	;; No tilde characters in file name, do normal
	;; `expand-file-name' (this does "/./" and "/../").
	;; `default-directory' is bound, because on Windows there
	;; would be problems with UNC shares or Cygwin mounts.
	(let ((default-directory tramp-compat-temporary-file-directory))
	  (tramp-make-tramp-file-name
	   v (tramp-drop-volume-letter
	      (tramp-run-real-handler
	       #'expand-file-name (list localname)))))))))