Function: tramp-ftp-file-name-handler

tramp-ftp-file-name-handler is an autoloaded and byte-compiled function defined in tramp-ftp.el.gz.

Signature

(tramp-ftp-file-name-handler OPERATION &rest ARGS)

Documentation

Invoke the Ange-FTP handler for OPERATION and ARGS.

First arg specifies the OPERATION, second arg is a list of arguments to pass to the OPERATION.

Source Code

;; Defined in /usr/src/emacs/lisp/net/tramp-ftp.el.gz
;;;###tramp-autoload
(defun tramp-ftp-file-name-handler (operation &rest args)
  "Invoke the Ange-FTP handler for OPERATION and ARGS.
First arg specifies the OPERATION, second arg is a list of arguments to
pass to the OPERATION."
  (save-match-data
    (or (boundp 'ange-ftp-name-format)
	(let (file-name-handler-alist) (require 'ange-ftp)))
    (let ((ange-ftp-name-format
	   (list (nth 0 tramp-file-name-structure)
		 (nth 3 tramp-file-name-structure)
		 (nth 2 tramp-file-name-structure)
		 (nth 4 tramp-file-name-structure)))
	  ;; ange-ftp uses `ange-ftp-ftp-name-arg' and `ange-ftp-ftp-name-res'
	  ;; for optimization in `ange-ftp-ftp-name'.  If Tramp wasn't active,
	  ;; there could be incorrect values from previous calls in case the
	  ;; "ftp" method is used in the Tramp file name.  So we unset
	  ;; those values.
	  (ange-ftp-ftp-name-arg "")
	  ange-ftp-ftp-name-res)
      (cond
       ;; If argument is a symlink, `file-directory-p' and
       ;; `file-exists-p' call the traversed file recursively.  So we
       ;; cannot disable the file-name-handler this case.  We set the
       ;; connection property "started" in order to put the remote
       ;; location into the cache, which is helpful for further
       ;; completion.  We don't use `with-parsed-tramp-file-name',
       ;; because this returns another user but the one declared in
       ;; "~/.netrc".
       ;; For file names which look like Tramp archive files like
       ;; "/ftp:anonymous@ftp.gnu.org:/gnu/tramp/tramp-2.0.39.tar.gz",
       ;; we must disable tramp-archive.el, because in
       ;; `ange-ftp-get-files' this is "normalized" by
       ;; `file-name-as-directory' with unwelcome side side-effects.
       ;; This disables the file archive functionality, perhaps we
       ;; could fix this otherwise.  (Bug#56078)
       ((memq operation '(file-directory-p file-exists-p))
	(cl-letf (((symbol-function #'tramp-archive-file-name-handler)
		   (lambda (operation &rest args)
		     (tramp-archive-run-real-handler operation args))))
	  (prog1 (apply #'ange-ftp-hook-function operation args)
	    (let ((v (tramp-dissect-file-name (car args) t)))
	      (setf (tramp-file-name-method v) tramp-ftp-method)
	      (tramp-set-connection-property v "started" t)))))

       ;; If the second argument of `copy-file' or `rename-file' is a
       ;; remote file name but via FTP, ange-ftp doesn't check this.
       ;; We must copy it locally first, because there is no place in
       ;; ange-ftp for correct handling.
       ((and (memq operation '(copy-file rename-file))
	     (tramp-tramp-file-p (cadr args))
	     (not (tramp-ftp-file-name-p (cadr args))))
	(let* ((filename (car args))
	       (newname (cadr args))
	       (tmpfile (tramp-compat-make-temp-file filename))
	       (args (cddr args)))
	  ;; We must set `ok-if-already-exists' to t in the first
	  ;; step, because the temp file has been created already.
	  (if (eq operation 'copy-file)
	      (apply operation filename tmpfile t (cdr args))
	    (apply operation filename tmpfile t))
	  (unwind-protect
	      (rename-file tmpfile newname (car args))
	    ;; Cleanup.
	    (ignore-errors (delete-file tmpfile)))))

       ;; Normally, the handlers must be discarded.
       (t (let* ((inhibit-file-name-handlers
		  (list 'tramp-file-name-handler
			'tramp-completion-file-name-handler
			(and (eq inhibit-file-name-operation operation)
			     inhibit-file-name-handlers)))
		 (inhibit-file-name-operation operation))
	    (apply #'ange-ftp-hook-function operation args)))))))