Function: tramp-sh-handle-file-local-copy

tramp-sh-handle-file-local-copy is a byte-compiled function defined in tramp-sh.el.gz.

Signature

(tramp-sh-handle-file-local-copy FILENAME)

Documentation

Like file-local-copy for Tramp files.

Source Code

;; Defined in /usr/src/emacs/lisp/net/tramp-sh.el.gz
(defun tramp-sh-handle-file-local-copy (filename)
  "Like `file-local-copy' for Tramp files."
  (with-parsed-tramp-file-name filename nil
    (unless (file-exists-p (file-truename filename))
      (tramp-compat-file-missing v filename))

    (let* ((size (tramp-compat-file-attribute-size
		  (file-attributes (file-truename filename))))
	   (rem-enc (tramp-get-inline-coding v "remote-encoding" size))
	   (loc-dec (tramp-get-inline-coding v "local-decoding" size))
	   (tmpfile (tramp-compat-make-temp-file filename)))

      (condition-case err
	  (cond
	   ;; `copy-file' handles direct copy and out-of-band methods.
	   ((or (tramp-local-host-p v)
		(tramp-method-out-of-band-p v size))
	    (copy-file filename tmpfile 'ok-if-already-exists 'keep-time))

	   ;; Use inline encoding for file transfer.
	   (rem-enc
	    (with-tramp-progress-reporter
		v 3
		(format-message
		 "Encoding remote file `%s' with `%s'" filename rem-enc)
	      (tramp-barf-unless-okay
	       v (format rem-enc (tramp-shell-quote-argument localname))
	       "Encoding remote file failed"))

	    (with-tramp-progress-reporter
		v 3 (format-message
		     "Decoding local file `%s' with `%s'" tmpfile loc-dec)
	      (if (functionp loc-dec)
		  ;; If local decoding is a function, we call it.  We
		  ;; must disable multibyte, because
		  ;; `uudecode-decode-region' doesn't handle it
		  ;; correctly.  Unset `file-name-handler-alist'.
		  ;; Otherwise, epa-file gets confused.
		  (let (file-name-handler-alist
			(coding-system-for-write 'binary)
			(default-directory
			  tramp-compat-temporary-file-directory))
		    (with-temp-file tmpfile
		      (set-buffer-multibyte nil)
		      (insert-buffer-substring (tramp-get-buffer v))
		      (funcall loc-dec (point-min) (point-max))))

		;; If tramp-decoding-function is not defined for this
		;; method, we invoke tramp-decoding-command instead.
		(let ((tmpfile2 (tramp-compat-make-temp-file filename)))
		  ;; Unset `file-name-handler-alist'.  Otherwise,
		  ;; epa-file gets confused.
		  (let (file-name-handler-alist
			(coding-system-for-write 'binary))
		    (with-current-buffer (tramp-get-buffer v)
		      (write-region
		       (point-min) (point-max) tmpfile2 nil 'no-message)))
		  (unwind-protect
		      (tramp-call-local-coding-command
		       loc-dec tmpfile2 tmpfile)
		    (delete-file tmpfile2)))))

	    ;; Set proper permissions.
	    (set-file-modes tmpfile (tramp-default-file-modes filename))
	    ;; Set local user ownership.
	    (tramp-set-file-uid-gid tmpfile))

	   ;; Oops, I don't know what to do.
	   (t (tramp-error
	       v 'file-error "Wrong method specification for `%s'" method)))

	;; Error handling.
	((error quit)
	 (delete-file tmpfile)
	 (signal (car err) (cdr err))))

      (run-hooks 'tramp-handle-file-local-copy-hook)
      tmpfile)))