;;; tramp-sh.el --- Tramp access functions for (s)sh-like connections
-;; Copyright (C) 1998-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2013 Free Software Foundation, Inc.
;; (copyright statements below in code to be updated with the above notice)
(tramp-copy-keep-date t)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
- '("scp"
- (tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p") ("-e" "none") ("%h")))
- (tramp-async-args (("-q")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-copy-program "scp")
- (tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q") ("-r")))
- (tramp-copy-keep-date t)
- (tramp-copy-recursive t)
- (tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
- ("-o" "UserKnownHostsFile=/dev/null")
- ("-o" "StrictHostKeyChecking=no")))
- (tramp-default-port 22)))
-;;;###tramp-autoload
-(add-to-list 'tramp-methods
- '("scp1"
+ '("scp"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-1") ("-e" "none") ("%h")))
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
+ ("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "scp")
- (tramp-copy-args (("-1") ("-P" "%p") ("-p" "%k") ("-q") ("-r")))
+ (tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q") ("-r") ("%c")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
(tramp-default-port 22)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
- '("scp2"
+ '("scp1"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-2") ("-e" "none") ("%h")))
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
+ ("-1") ("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "scp")
- (tramp-copy-args (("-2") ("-P" "%p") ("-p" "%k") ("-q") ("-r")))
+ (tramp-copy-args (("-1") ("-P" "%p") ("-p" "%k")
+ ("-q") ("-r") ("%c")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
(tramp-default-port 22)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
- '("scpc"
+ '("scp2"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-o" "ControlPath=%t.%%r@%%h:%%p")
- ("-o" "ControlMaster=yes")
- ("-e" "none") ("%h")))
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
+ ("-2") ("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "scp")
- (tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q") ("-r")
- ("-o" "ControlPath=%t.%%r@%%h:%%p")
- ("-o" "ControlMaster=auto")))
+ (tramp-copy-args (("-2") ("-P" "%p") ("-p" "%k")
+ ("-q") ("-r") ("%c")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
(add-to-list 'tramp-methods
'("scpx"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-e" "none") ("-t" "-t")
- ("%h") ("/bin/sh")))
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
+ ("-e" "none") ("-t" "-t") ("%h") ("/bin/sh")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "scp")
- (tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q") ("-r")))
+ (tramp-copy-args (("-P" "%p") ("-p" "%k")
+ ("-q") ("-r") ("%c")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
(add-to-list 'tramp-methods
'("sftp"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p") ("-e" "none") ("%h")))
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
+ ("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
- (tramp-copy-program "sftp")))
-;;;###tramp-autoload
+ (tramp-copy-program "sftp")
+ (tramp-copy-args ("%c"))))
+ ;;;###tramp-autoload
(add-to-list 'tramp-methods
'("rsync"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p") ("-e" "none") ("%h")))
- (tramp-async-args (("-q")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-copy-program "rsync")
- (tramp-copy-args (("-e" "ssh") ("-t" "%k") ("-r")))
- (tramp-copy-keep-date t)
- (tramp-copy-keep-tmpfile t)
- (tramp-copy-recursive t)))
-;;;###tramp-autoload
-(add-to-list 'tramp-methods
- `("rsyncc"
- (tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-o" "ControlPath=%t.%%r@%%h:%%p")
- ("-o" "ControlMaster=yes")
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "rsync")
(tramp-copy-args (("-t" "%k") ("-r")))
- (tramp-copy-env (("RSYNC_RSH")
- (,(concat
- "ssh"
- " -o ControlPath=%t.%%r@%%h:%%p"
- " -o ControlMaster=auto"))))
+ (tramp-copy-env (("RSYNC_RSH") ("ssh" "%c")))
(tramp-copy-keep-date t)
(tramp-copy-keep-tmpfile t)
(tramp-copy-recursive t)))
(add-to-list 'tramp-methods
'("ssh"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p") ("-e" "none") ("%h")))
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
+ ("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(add-to-list 'tramp-methods
'("ssh1"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
("-1") ("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(add-to-list 'tramp-methods
'("ssh2"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
("-2") ("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(add-to-list 'tramp-methods
'("sshx"
(tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-e" "none") ("-t" "-t")
- ("%h") ("/bin/sh")))
+ (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
+ ("-e" "none") ("-t" "-t") ("%h") ("/bin/sh")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-set-completion-function "scp" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "scp1" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "scp2" tramp-completion-function-alist-ssh)
- (tramp-set-completion-function "scpc" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "scpx" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "sftp" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "rsync" tramp-completion-function-alist-ssh)
- (tramp-set-completion-function
- "rsyncc" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "rsh" tramp-completion-function-alist-rsh)
(tramp-set-completion-function "remsh" tramp-completion-function-alist-rsh)
(tramp-set-completion-function "ssh" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "ssh1" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "ssh2" tramp-completion-function-alist-ssh)
- (tramp-set-completion-function
- "ssh1_old" tramp-completion-function-alist-ssh)
- (tramp-set-completion-function
- "ssh2_old" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "sshx" tramp-completion-function-alist-ssh)
(tramp-set-completion-function
"telnet" tramp-completion-function-alist-telnet)
;; IRIX64: /usr/bin
;;;###tramp-autoload
(defcustom tramp-remote-path
- '(tramp-default-remote-path "/bin" "/usr/bin" "/usr/sbin"
- "/usr/local/bin" "/local/bin" "/local/freeware/bin" "/local/gnu/bin"
- "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin"
+ '(tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin"
+ "/usr/local/bin" "/usr/local/sbin" "/local/bin" "/local/freeware/bin"
+ "/local/gnu/bin" "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin"
"/opt/bin" "/opt/sbin" "/opt/local/bin")
"List of directories to search for executables on remote host.
For every remote host, this variable will be set buffer local,
(const :tag "Private Directories" tramp-own-remote-path)
(string :tag "Directory"))))
+;;;###tramp-autoload
(defcustom tramp-remote-process-environment
`("HISTFILE=$HOME/.tramp_history" "HISTSIZE=1" "LC_ALL=C"
,(format "TERM=%s" tramp-terminal-type)
(defconst tramp-perl-encode
"%s -e '
# This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002-2012 Free Software Foundation, Inc.
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
use strict;
my %%trans = do {
map {(substr(unpack(q(B8), chr $i++), 2, 6), $_)}
split //, q(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/);
};
-
-binmode(\\*STDIN);
+my $data;
# We read in chunks of 54 bytes, to generate output lines
# of 72 chars (plus end of line)
-$/ = \\54;
-
-while (my $data = <STDIN>) {
+while (read STDIN, $data, 54) {
my $pad = q();
# Only for the last chunk, and only if did not fill the last three-byte packet
(defconst tramp-perl-decode
"%s -e '
# This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002-2012 Free Software Foundation, Inc.
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
use strict;
my %%trans = do {
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
(file-truename . tramp-sh-handle-file-truename)
(file-exists-p . tramp-sh-handle-file-exists-p)
+ (file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
(file-directory-p . tramp-sh-handle-file-directory-p)
(file-executable-p . tramp-sh-handle-file-executable-p)
(file-readable-p . tramp-sh-handle-file-readable-p)
(verify-visited-file-modtime . tramp-sh-handle-verify-visited-file-modtime)
(file-selinux-context . tramp-sh-handle-file-selinux-context)
(set-file-selinux-context . tramp-sh-handle-set-file-selinux-context)
+ (file-acl . tramp-sh-handle-file-acl)
+ (set-file-acl . tramp-sh-handle-set-file-acl)
(vc-registered . tramp-sh-handle-vc-registered))
"Alist of handler functions.
Operations not mentioned here will be handled by the normal Emacs functions.")
"Like `file-truename' for Tramp files."
(with-parsed-tramp-file-name (expand-file-name filename) nil
(tramp-make-tramp-file-name method user host
- (with-file-property v localname "file-truename"
+ (with-tramp-file-property v localname "file-truename"
(let ((result nil)) ; result steps in reverse order
(tramp-message v 4 "Finding true name for `%s'" filename)
(cond
(defun tramp-sh-handle-file-exists-p (filename)
"Like `file-exists-p' for Tramp files."
(with-parsed-tramp-file-name filename nil
- (with-file-property v localname "file-exists-p"
+ (with-tramp-file-property v localname "file-exists-p"
(or (not (null (tramp-get-file-property
v localname "file-attributes-integer" nil)))
(not (null (tramp-get-file-property
;; Don't modify `last-coding-system-used' by accident.
(let ((last-coding-system-used last-coding-system-used))
(with-parsed-tramp-file-name (expand-file-name filename) nil
- (with-file-property v localname (format "file-attributes-%s" id-format)
+ (with-tramp-file-property
+ v localname (format "file-attributes-%s" id-format)
(save-excursion
(tramp-convert-file-attributes
v
res-uid
;; 3. File gid.
res-gid
- ;; 4. Last access time, as a list of two integers. First
- ;; integer has high-order 16 bits of time, second has low 16
- ;; bits.
+ ;; 4. Last access time, as a list of integers. Normally this
+ ;; would be in the same format as `current-time', but the
+ ;; subseconds part is not currently implemented, and (0 0)
+ ;; denotes an unknown time.
;; 5. Last modification time, likewise.
;; 6. Last status change time, likewise.
'(0 0) '(0 0) '(0 0) ;CCC how to find out?
(let ((f (buffer-file-name))
coding-system-used)
(with-parsed-tramp-file-name f nil
- (let* ((attr (file-attributes f))
+ (let* ((remote-file-name-inhibit-cache t)
+ (attr (file-attributes f))
;; '(-1 65535) means file doesn't exists yet.
(modtime (or (nth 5 attr) '(-1 65535))))
(when (boundp 'last-coding-system-used)
(utc (not (featurep 'xemacs))))
(tramp-send-command-and-check
v (format "%s touch -t %s %s"
- (if utc "TZ=UTC; export TZ;" "")
+ (if utc "env TZ=UTC" "")
(if utc
(format-time-string "%Y%m%d%H%M.%S" time t)
(format-time-string "%Y%m%d%H%M.%S" time))
(defun tramp-set-file-uid-gid (filename &optional uid gid)
"Set the ownership for FILENAME.
If UID and GID are provided, these values are used; otherwise uid
-and gid of the corresponding user is taken. Both parameters must be integers."
+and gid of the corresponding user is taken. Both parameters must
+be non-negative integers."
;; Modern Unices allow chown only for root. So we might need
;; another implementation, see `dired-do-chown'. OTOH, it is mostly
;; working with su(do)? when it is needed, so it shall succeed in
(if (and (zerop (user-uid)) (tramp-local-host-p v))
;; If we are root on the local host, we can do it directly.
(tramp-set-file-uid-gid localname uid gid)
- (let ((uid (or (and (integerp uid) uid)
+ (let ((uid (or (and (natnump uid) uid)
(tramp-get-remote-uid v 'integer)))
- (gid (or (and (integerp gid) gid)
+ (gid (or (and (natnump gid) gid)
(tramp-get-remote-gid v 'integer))))
(tramp-send-command
v (format
;; We handle also the local part, because there doesn't exist
;; `set-file-uid-gid'. On W32 "chown" might not work.
- (let ((uid (or (and (integerp uid) uid) (tramp-get-local-uid 'integer)))
- (gid (or (and (integerp gid) gid) (tramp-get-local-gid 'integer))))
+ (let ((uid (or (and (natnump uid) uid) (tramp-get-local-uid 'integer)))
+ (gid (or (and (natnump gid) gid) (tramp-get-local-gid 'integer))))
(tramp-compat-call-process
"chown" nil nil nil
(format "%d:%d" uid gid) (tramp-shell-quote-argument filename))))))
(defun tramp-remote-selinux-p (vec)
"Check, whether SELINUX is enabled on the remote host."
- (with-connection-property (tramp-get-connection-process vec) "selinux-p"
+ (with-tramp-connection-property
+ (tramp-get-connection-process vec) "selinux-p"
(let ((result (tramp-find-executable
vec "getenforce" (tramp-get-remote-path vec) t t)))
(and result
(defun tramp-sh-handle-file-selinux-context (filename)
"Like `file-selinux-context' for Tramp files."
(with-parsed-tramp-file-name filename nil
- (with-file-property v localname "file-selinux-context"
+ (with-tramp-file-property v localname "file-selinux-context"
(let ((context '(nil nil nil nil))
(regexp (concat "\\([a-z0-9_]+\\):" "\\([a-z0-9_]+\\):"
"\\([a-z0-9_]+\\):" "\\([a-z0-9_]+\\)")))
(if (stringp (nth 3 context))
(format "--range=%s" (nth 3 context)) "")
(tramp-shell-quote-argument localname))))
- (tramp-set-file-property v localname "file-selinux-context" context)
- (tramp-set-file-property v localname "file-selinux-context" 'undef)))
- ;; We always return nil.
- nil)
+ (progn
+ (tramp-set-file-property v localname "file-selinux-context" context)
+ t)
+ (tramp-set-file-property v localname "file-selinux-context" 'undef)
+ nil)))
+
+(defun tramp-remote-acl-p (vec)
+ "Check, whether ACL is enabled on the remote host."
+ (with-tramp-connection-property (tramp-get-connection-process vec) "acl-p"
+ (tramp-send-command-and-check vec "getfacl /")))
+
+(defun tramp-sh-handle-file-acl (filename)
+ "Like `file-acl' for Tramp files."
+ (with-parsed-tramp-file-name filename nil
+ (with-tramp-file-property v localname "file-acl"
+ (when (and (tramp-remote-acl-p v)
+ (tramp-send-command-and-check
+ v (format
+ "getfacl -ac %s 2>/dev/null"
+ (tramp-shell-quote-argument localname))))
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (goto-char (point-max))
+ (delete-blank-lines)
+ (when (> (point-max) (point-min))
+ (tramp-compat-funcall
+ 'substring-no-properties (buffer-string))))))))
+
+(defun tramp-sh-handle-set-file-acl (filename acl-string)
+ "Like `set-file-acl' for Tramp files."
+ (with-parsed-tramp-file-name (expand-file-name filename) nil
+ (if (and (stringp acl-string) (tramp-remote-acl-p v)
+ (progn
+ (tramp-send-command
+ v (format "setfacl --set-file=- %s <<'EOF'\n%s\nEOF\n"
+ (tramp-shell-quote-argument localname) acl-string))
+ (tramp-send-command-and-check v nil)))
+ ;; Success.
+ (progn
+ (tramp-set-file-property v localname "file-acl" acl-string)
+ t)
+ ;; In case of errors, we return `nil'.
+ (tramp-set-file-property v localname "file-acl-string" 'undef)
+ nil)))
;; Simple functions using the `test' command.
(defun tramp-sh-handle-file-executable-p (filename)
"Like `file-executable-p' for Tramp files."
(with-parsed-tramp-file-name filename nil
- (with-file-property v localname "file-executable-p"
+ (with-tramp-file-property v localname "file-executable-p"
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
(or (tramp-check-cached-permissions v ?x)
(defun tramp-sh-handle-file-readable-p (filename)
"Like `file-readable-p' for Tramp files."
(with-parsed-tramp-file-name filename nil
- (with-file-property v localname "file-readable-p"
+ (with-tramp-file-property v localname "file-readable-p"
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
(or (tramp-check-cached-permissions v ?r)
;; desirable to return t immediately for "/method:foo:". It can
;; be expected that this is always a directory.
(or (zerop (length localname))
- (with-file-property v localname "file-directory-p"
+ (with-tramp-file-property v localname "file-directory-p"
(tramp-run-test "-d" filename)))))
(defun tramp-sh-handle-file-writable-p (filename)
"Like `file-writable-p' for Tramp files."
(with-parsed-tramp-file-name filename nil
- (with-file-property v localname "file-writable-p"
+ (with-tramp-file-property v localname "file-writable-p"
(if (file-exists-p filename)
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
(and (tramp-run-test "-d" (file-name-directory filename))
(tramp-run-test "-w" (file-name-directory filename)))))))
-(defun tramp-sh-handle-file-ownership-preserved-p (filename)
+(defun tramp-sh-handle-file-ownership-preserved-p (filename &optional group)
"Like `file-ownership-preserved-p' for Tramp files."
(with-parsed-tramp-file-name filename nil
- (with-file-property v localname "file-ownership-preserved-p"
+ (with-tramp-file-property v localname "file-ownership-preserved-p"
(let ((attributes (file-attributes filename)))
;; Return t if the file doesn't exist, since it's true that no
;; information would be lost by an (attempted) delete and create.
(or (null attributes)
- (= (nth 2 attributes) (tramp-get-remote-uid v 'integer)))))))
+ (and
+ (= (nth 2 attributes) (tramp-get-remote-uid v 'integer))
+ (or (not group)
+ (= (nth 3 attributes) (tramp-get-remote-gid v 'integer)))))))))
;; Directory listings.
(let* ((temp
(copy-tree
(with-parsed-tramp-file-name directory nil
- (with-file-property
+ (with-tramp-file-property
v localname
(format "directory-files-and-attributes-%s" id-format)
(save-excursion
(defun tramp-sh-handle-copy-file
(filename newname &optional ok-if-already-exists keep-date
- preserve-uid-gid preserve-selinux-context)
+ preserve-uid-gid preserve-extended-attributes)
"Like `copy-file' for Tramp files."
(setq filename (expand-file-name filename))
(setq newname (expand-file-name newname))
(tramp-tramp-file-p newname))
(tramp-do-copy-or-rename-file
'copy filename newname ok-if-already-exists keep-date
- preserve-uid-gid preserve-selinux-context))
+ preserve-uid-gid preserve-extended-attributes))
;; Compat section.
- (preserve-selinux-context
+ (preserve-extended-attributes
(tramp-run-real-handler
'copy-file
(list filename newname ok-if-already-exists keep-date
- preserve-uid-gid preserve-selinux-context)))
+ preserve-uid-gid preserve-extended-attributes)))
(preserve-uid-gid
(tramp-run-real-handler
'copy-file
(defun tramp-do-copy-or-rename-file
(op filename newname &optional ok-if-already-exists keep-date
- preserve-uid-gid preserve-selinux-context)
+ preserve-uid-gid preserve-extended-attributes)
"Copy or rename a remote file.
OP must be `copy' or `rename' and indicates the operation to perform.
FILENAME specifies the file to copy or rename, NEWNAME is the name of
KEEP-DATE means to make sure that NEWNAME has the same timestamp
as FILENAME. PRESERVE-UID-GID, when non-nil, instructs to keep
the uid and gid if both files are on the same host.
-PRESERVE-SELINUX-CONTEXT activates selinux commands.
+PRESERVE-EXTENDED-ATTRIBUTES activates selinux and acl commands.
This function is invoked by `tramp-sh-handle-copy-file' and
`tramp-sh-handle-rename-file'. It is an error if OP is neither
(error "Unknown operation `%s', must be `copy' or `rename'" op))
(let ((t1 (tramp-tramp-file-p filename))
(t2 (tramp-tramp-file-p newname))
- (context (and preserve-selinux-context
- (apply 'file-selinux-context (list filename))))
+ (length (nth 7 (file-attributes (file-truename filename))))
+ (attributes (and preserve-extended-attributes
+ (apply 'file-extended-attributes (list filename))))
pr tm)
(with-parsed-tramp-file-name (if t1 filename newname) nil
(tramp-error
v 'file-already-exists "File %s already exists" newname))
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
v 0 (format "%s %s to %s"
(if (eq op 'copy) "Copying" "Renaming")
filename newname)
ok-if-already-exists keep-date preserve-uid-gid))
;; Try out-of-band operation.
- ((tramp-method-out-of-band-p
- v1 (nth 7 (file-attributes (file-truename filename))))
+ ((and
+ (tramp-method-out-of-band-p v1 length)
+ (tramp-method-out-of-band-p v2 length))
(tramp-do-copy-or-rename-file-out-of-band
op filename newname keep-date))
;; If the Tramp file has an out-of-band method, the
;; corresponding copy-program can be invoked.
- ((tramp-method-out-of-band-p
- v (nth 7 (file-attributes (file-truename filename))))
+ ((tramp-method-out-of-band-p v length)
(tramp-do-copy-or-rename-file-out-of-band
op filename newname keep-date))
;; One of them must be a Tramp file.
(error "Tramp implementation says this cannot happen")))
- ;; Handle `preserve-selinux-context'.
- (when context (apply 'set-file-selinux-context (list newname context)))
+ ;; Handle `preserve-extended-attributes'. We ignore possible
+ ;; errors, because ACL strings could be incompatible.
+ (when attributes
+ (ignore-errors
+ (apply 'set-file-extended-attributes (list newname attributes))))
;; In case of `rename', we must flush the cache of the source file.
(when (and t1 (eq op 'rename))
(t2 (tramp-tramp-file-p newname))
(orig-vec (tramp-dissect-file-name (if t1 filename newname)))
copy-program copy-args copy-env copy-keep-date port spec
- source target)
+ options source target)
(with-parsed-tramp-file-name (if t1 filename newname) nil
(if (and t1 t2)
user (or user "")
port (or port "")
spec (format-spec-make
- ?h host ?u user ?p port
?t (tramp-get-connection-property
- (tramp-get-connection-process v) "temp-file" "")
+ (tramp-get-connection-process v) "temp-file" ""))
+ options (format-spec tramp-ssh-controlmaster-options spec)
+ spec (format-spec-make
+ ?h host ?u user ?p port ?c options
?k (if keep-date " " ""))
copy-program (tramp-get-method-parameter
method 'tramp-copy-program)
v "process-buffer" (current-buffer))
(while copy-env
(tramp-message
- orig-vec 5 "%s=\"%s\"" (car copy-env) (cadr copy-env))
+ orig-vec 6 "%s=\"%s\"" (car copy-env) (cadr copy-env))
(setenv (pop copy-env) (pop copy-env)))
;; Use an asynchronous process. By this, password can
;; last longer than 60 secs.
(let ((p (let ((default-directory
(tramp-compat-temporary-file-directory)))
- (apply 'start-process
+ (apply 'start-process-shell-command
(tramp-get-connection-name v)
(tramp-get-connection-buffer v)
copy-program
- (append copy-args (list source target))))))
+ (append
+ copy-args
+ (list
+ (shell-quote-argument source)
+ (shell-quote-argument target)
+ "&&" "echo" "tramp_exit_status" "0"
+ "||" "echo" "tramp_exit_status" "1"))))))
(tramp-message
orig-vec 6 "%s"
(mapconcat 'identity (process-command p) " "))
(tramp-compat-set-process-query-on-exit-flag p nil)
(tramp-process-actions
- p v nil tramp-actions-copy-out-of-band)))
+ p v nil tramp-actions-copy-out-of-band)
+
+ ;; Check the return code.
+ (goto-char (point-max))
+ (unless
+ (re-search-backward "tramp_exit_status [0-9]+" nil t)
+ (tramp-error
+ orig-vec 'file-error
+ "Couldn't find exit status of `%s'" (process-command p)))
+ (skip-chars-forward "^ ")
+ (unless (zerop (read (current-buffer)))
+ (forward-line -1)
+ (tramp-error
+ orig-vec 'file-error
+ "Error copying: `%s'"
+ (buffer-substring (point-min) (point-at-eol))))))
;; Reset the transfer process properties.
(tramp-message orig-vec 6 "\n%s" (buffer-string))
nil)
((and suffix (nth 2 suffix))
;; We found an uncompression rule.
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
v 0 (format "Uncompressing %s" file)
(when (tramp-send-command-and-check
v (concat (nth 2 suffix) " "
(t
;; We don't recognize the file as compressed, so compress it.
;; Try gzip.
- (tramp-with-progress-reporter v 0 (format "Compressing %s" file)
+ (with-tramp-progress-reporter v 0 (format "Compressing %s" file)
(when (tramp-send-command-and-check
v (concat "gzip -f "
(tramp-shell-quote-argument localname)))
(if full-directory-p "yes" "no"))
;; If `full-directory-p', we just say `ls -l FILENAME'.
;; Else we chdir to the parent directory, then say `ls -ld BASENAME'.
+ ;; "--dired" returns byte positions. Therefore, the file names
+ ;; must be encoded, which is guaranteed by "LC_ALL=en_US.utf8
+ ;; LC_CTYPE=''".
(if full-directory-p
(tramp-send-command
v
- (format "%s %s %s 2>/dev/null"
+ (format "env LC_ALL=en_US.utf8 LC_CTYPE='' %s %s %s 2>/dev/null"
(tramp-get-ls-command v)
switches
(if wildcard
(tramp-run-real-handler 'file-name-directory (list localname))))
(tramp-send-command
v
- (format "%s %s %s"
+ (format "env LC_ALL=en_US.utf8 LC_CTYPE='' %s %s %s 2>/dev/null"
(tramp-get-ls-command v)
switches
(if (or wildcard
(while (re-search-forward tramp-color-escape-sequence-regexp nil t)
(replace-match "")))
+ ;; Decode the output, it could be multibyte.
+ (decode-coding-region
+ beg (point-max)
+ (or file-name-coding-system default-file-name-coding-system))
+
;; The inserted file could be from somewhere else.
(when (and (not wildcard) (not full-directory-p))
(goto-char (point-max))
(string-match "\\`su\\(do\\)?\\'" method))
(setq uname (concat uname user)))
(setq uname
- (with-connection-property v 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)
(or (null program) tramp-process-connection-type))
(bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
(name1 name)
- (i 0))
+ (i 0)
+ ;; We do not want to raise an error when
+ ;; `start-file-process' has been started several time in
+ ;; `eshell' and friends.
+ (tramp-current-connection nil))
(unless buffer
;; BUFFER can be nil. We use a temporary buffer.
(with-current-buffer (tramp-get-connection-buffer v)
(unwind-protect
+ ;; We catch this event. Otherwise, `start-process' could
+ ;; be called on the local host.
(save-excursion
(save-restriction
;; Activate narrowing in order to save BUFFER
(narrow-to-region (point-max) (point-max))
;; We call `tramp-maybe-open-connection', in order
;; to cleanup the prompt afterwards.
- (tramp-maybe-open-connection v)
- (widen)
- (delete-region mark (point))
- (narrow-to-region (point-max) (point-max))
- ;; Now do it.
- (if command
- ;; Send the command.
- (tramp-send-command v command nil t) ; nooutput
- ;; Check, whether a pty is associated.
- (unless (tramp-compat-process-get
- (tramp-get-connection-process v) 'remote-tty)
- (tramp-error
- v 'file-error
- "pty association is not supported for `%s'" name))))
- (let ((p (tramp-get-connection-process v)))
- ;; Set query flag for this process. We ignore errors,
- ;; because the process could have finished already.
- (ignore-errors
- (tramp-compat-set-process-query-on-exit-flag p t))
- ;; Return process.
- p)))
+ (catch 'suppress
+ (tramp-maybe-open-connection v)
+ (widen)
+ (delete-region mark (point))
+ (narrow-to-region (point-max) (point-max))
+ ;; Now do it.
+ (if command
+ ;; Send the command.
+ (tramp-send-command v command nil t) ; nooutput
+ ;; Check, whether a pty is associated.
+ (unless (tramp-compat-process-get
+ (tramp-get-connection-process v) 'remote-tty)
+ (tramp-error
+ v 'file-error
+ "pty association is not supported for `%s'" name))))
+ (let ((p (tramp-get-connection-process v)))
+ ;; Set query flag and process marker for this
+ ;; process. We ignore errors, because the process
+ ;; could have finished already.
+ (ignore-errors
+ (tramp-compat-set-process-query-on-exit-flag p t)
+ (set-marker (process-mark p) (point)))
+ ;; Return process.
+ p))))
;; Save exit.
(if (string-match tramp-temp-buffer-name (buffer-name))
- (progn
+ (ignore-errors
(set-process-buffer (tramp-get-connection-process v) nil)
(kill-buffer (current-buffer)))
(set-buffer-modified-p bmp))
(keyboard-quit)
ret))))
-(defun tramp-sh-handle-call-process-region
- (start end program &optional delete buffer display &rest args)
- "Like `call-process-region' for Tramp files."
- (let ((tmpfile (tramp-compat-make-temp-file "")))
- (write-region start end tmpfile)
- (when delete (delete-region start end))
- (unwind-protect
- (apply 'call-process program tmpfile buffer display args)
- (delete-file tmpfile))))
-
(defun tramp-sh-handle-file-local-copy (filename)
"Like `file-local-copy' for Tramp files."
(with-parsed-tramp-file-name filename nil
;; Use inline encoding for file transfer.
(rem-enc
(save-excursion
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
v 3 (format "Encoding remote file %s" filename)
(tramp-barf-unless-okay
v (format rem-enc (tramp-shell-quote-argument localname))
(with-temp-buffer
(set-buffer-multibyte nil)
(insert-buffer-substring (tramp-get-buffer v))
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
v 3 (format "Decoding remote file %s with function %s"
filename loc-dec)
(funcall loc-dec (point-min) (point-max))
(let (file-name-handler-alist
(coding-system-for-write 'binary))
(write-region (point-min) (point-max) tmpfile2))
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
v 3 (format "Decoding remote file %s with command %s"
filename loc-dec)
(unwind-protect
(set-buffer-multibyte nil)
;; Use encoding function or command.
(if (functionp loc-enc)
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
v 3 (format "Encoding region using function `%s'"
loc-enc)
(let ((coding-system-for-read 'binary))
(tramp-compat-temporary-file-directory)))
(funcall loc-enc (point-min) (point-max))))
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
v 3 (format "Encoding region using command `%s'"
loc-enc)
(unless (zerop (tramp-call-local-coding-command
;; Send buffer into remote decoding command which
;; writes to remote file. Because this happens on
;; the remote host, we cannot use the function.
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
v 3
(format "Decoding region into remote file %s" filename)
(goto-char (point-max))
"Like `vc-registered' for Tramp files."
(tramp-compat-with-temp-message ""
(with-parsed-tramp-file-name file nil
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
v 3 (format "Checking `vc-registered' for %s" file)
;; There could be new files, created by the vc backend. We
(let ((scripts (tramp-get-connection-property
(tramp-get-connection-process vec) "scripts" nil)))
(unless (member name scripts)
- (tramp-with-progress-reporter vec 5 (format "Sending script `%s'" name)
+ (with-tramp-progress-reporter vec 5 (format "Sending script `%s'" name)
;; The script could contain a call of Perl. This is masked with `%s'.
(tramp-barf-unless-okay
vec
(defun tramp-open-shell (vec shell)
"Opens shell SHELL."
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
vec 5 (format "Opening remote shell `%s'" shell)
;; Find arguments for this shell.
(let ((tramp-end-of-output tramp-initial-end-of-output)
(tramp-file-name-method vec) 'tramp-remote-shell)))
shell)
(setq shell
- (with-connection-property vec "remote-shell"
+ (with-tramp-connection-property vec "remote-shell"
;; CCC: "root" does not exist always, see QNAP 459.
;; Which check could we apply instead?
(tramp-send-command vec "echo ~root" t)
(tramp-open-shell vec shell))
;; Busyboxes tend to behave strange. We check for the existence.
- (with-connection-property vec "busybox"
+ (with-tramp-connection-property vec "busybox"
(tramp-send-command vec (format "%s --version" shell) t)
(let ((case-fold-search t))
(and (string-match "busybox" (buffer-string)) t))))))
;; successfully, sending 625 bytes failed. Emacs makes a hack when
;; this host type is detected locally. It cannot handle remote
;; hosts, though.
- (with-connection-property proc "chunksize"
+ (with-tramp-connection-property proc "chunksize"
(cond
((and (integerp tramp-chunksize) (> tramp-chunksize 0))
tramp-chunksize)
(tramp-message
vec 2 "Couldn't find an inline transfer compress command")))))
+(defvar tramp-gw-tunnel-method)
+(defvar tramp-gw-socks-method)
+
(defun tramp-compute-multi-hops (vec)
"Expands VEC according to `tramp-default-proxies-alist'.
Gateway hops are already opened."
(setq choices tramp-default-proxies-alist)))))
;; Handle gateways.
- (when (string-match
- (format
- "^\\(%s\\|%s\\)$" tramp-gw-tunnel-method tramp-gw-socks-method)
- (tramp-file-name-method (car target-alist)))
+ (when (and (boundp 'tramp-gw-tunnel-method) (boundp 'tramp-gw-socks-method)
+ (string-match
+ (format
+ "^\\(%s\\|%s\\)$" tramp-gw-tunnel-method tramp-gw-socks-method)
+ (tramp-file-name-method (car target-alist))))
(let ((gw (pop target-alist))
(hop (pop target-alist)))
;; Is the method prepared for gateways?
(car tramp-current-connection)))
(> (tramp-time-diff
(current-time) (cdr tramp-current-connection))
- 5))
+ (or tramp-connection-min-time-diff 0)))
(throw 'suppress 'suppress))
;; If too much time has passed since last command was sent, look
(when (and (boundp 'non-essential) (symbol-value 'non-essential))
(throw 'non-essential 'non-essential))
- (tramp-with-progress-reporter
+ (with-tramp-progress-reporter
vec 3
(if (zerop (length (tramp-file-name-user vec)))
(format "Opening connection for %s using %s"
(setenv "PROMPT_COMMAND")
(setenv "PS1" tramp-initial-end-of-output)
(let* ((target-alist (tramp-compute-multi-hops vec))
+ ;; We will apply `tramp-ssh-controlmaster-options'
+ ;; only for the first hop.
+ (options tramp-ssh-controlmaster-options)
(process-connection-type tramp-process-connection-type)
(process-adaptive-read-buffering nil)
(coding-system-for-read nil)
;; temporary file has another name, and it is
;; created and protected by ssh. It is also
;; removed by ssh when the connection is
- ;; closed.
+ ;; closed. The temporary file name is cached
+ ;; in the main connection process, therefore
+ ;; we cannot use `tramp-get-connection-process'.
(tmpfile
- (tramp-set-connection-property
- p "temp-file"
- (make-temp-name
- (expand-file-name
- tramp-temp-name-prefix
- (tramp-compat-temporary-file-directory)))))
+ (with-tramp-connection-property
+ (get-process (tramp-buffer-name vec)) "temp-file"
+ (make-temp-name
+ (expand-file-name
+ tramp-temp-name-prefix
+ (tramp-compat-temporary-file-directory)))))
spec r-shell)
;; Add arguments for asynchronous processes.
l-host (or l-host "")
l-user (or l-user "")
l-port (or l-port "")
+ spec (format-spec-make ?t tmpfile)
+ options (format-spec options spec)
spec (format-spec-make
- ?h l-host ?u l-user ?p l-port ?t tmpfile)
+ ?h l-host ?u l-user ?p l-port ?c options)
command
(concat
;; We do not want to see the trailing local
(tramp-message
vec 3 "Found remote shell prompt on `%s'" l-host))
;; Next hop.
- (setq target-alist (cdr target-alist)))
+ (setq options ""
+ target-alist (cdr target-alist)))
;; Make initial shell settings.
(tramp-open-connection-setup-interactive-shell p vec))))
command (buffer-string))))))))
(defun tramp-convert-file-attributes (vec attr)
- "Convert file-attributes ATTR generated by perl script, stat or ls.
+ "Convert `file-attributes' ATTR generated by perl script, stat or ls.
Convert file mode bits to string and set virtual device number.
Return ATTR."
(when attr
(when (stringp (car attr))
(while (string-match tramp-color-escape-sequence-regexp (car attr))
(setcar attr (replace-match "" nil nil (car attr)))))
+ ;; Convert uid and gid. Use -1 as indication of unusable value.
+ (when (and (numberp (nth 2 attr)) (< (nth 2 attr) 0))
+ (setcar (nthcdr 2 attr) -1))
+ (when (and (floatp (nth 2 attr))
+ (<= (nth 2 attr) (tramp-compat-most-positive-fixnum)))
+ (setcar (nthcdr 2 attr) (round (nth 2 attr))))
+ (when (and (numberp (nth 3 attr)) (< (nth 3 attr) 0))
+ (setcar (nthcdr 3 attr) -1))
+ (when (and (floatp (nth 3 attr))
+ (<= (nth 3 attr) (tramp-compat-most-positive-fixnum)))
+ (setcar (nthcdr 3 attr) (round (nth 3 attr))))
;; Convert last access time.
(unless (listp (nth 4 attr))
(setcar (nthcdr 4 attr)
;; Variables local to connection.
(defun tramp-get-remote-path (vec)
- (with-connection-property
+ (with-tramp-connection-property
;; When `tramp-own-remote-path' is in `tramp-remote-path', we
;; cache the result for the session only. Otherwise, the result
;; is cached persistently.
remote-path)))))
(defun tramp-get-ls-command (vec)
- (with-connection-property vec "ls"
+ (with-tramp-connection-property vec "ls"
(tramp-message vec 5 "Finding a suitable `ls' command")
(or
(catch 'ls-found
(defun tramp-get-ls-command-with-dired (vec)
(save-match-data
- (with-connection-property vec "ls-dired"
+ (with-tramp-connection-property vec "ls-dired"
(tramp-message vec 5 "Checking, whether `ls --dired' works")
;; Some "ls" versions are sensible wrt the order of arguments,
;; they fail when "-al" is after the "--dired" argument (for
vec (format "%s --dired -al /dev/null" (tramp-get-ls-command vec))))))
(defun tramp-get-test-command (vec)
- (with-connection-property vec "test"
+ (with-tramp-connection-property vec "test"
(tramp-message vec 5 "Finding a suitable `test' command")
(if (tramp-send-command-and-check vec "test 0")
"test"
;; Does `test A -nt B' work? Use abominable `find' construct if it
;; doesn't. BSD/OS 4.0 wants the parentheses around the command,
;; for otherwise the shell crashes.
- (with-connection-property vec "test-nt"
+ (with-tramp-connection-property vec "test-nt"
(or
(progn
(tramp-send-command
"tramp_test_nt %s %s"))))
(defun tramp-get-file-exists-command (vec)
- (with-connection-property vec "file-exists"
+ (with-tramp-connection-property vec "file-exists"
(tramp-message vec 5 "Finding command to check if file exists")
(tramp-find-file-exists-command vec)))
(defun tramp-get-remote-ln (vec)
- (with-connection-property vec "ln"
+ (with-tramp-connection-property vec "ln"
(tramp-message vec 5 "Finding a suitable `ln' command")
(tramp-find-executable vec "ln" (tramp-get-remote-path vec))))
(defun tramp-get-remote-perl (vec)
- (with-connection-property vec "perl"
+ (with-tramp-connection-property vec "perl"
(tramp-message vec 5 "Finding a suitable `perl' command")
(let ((result
(or (tramp-find-executable vec "perl5" (tramp-get-remote-path vec))
vec "perl" (tramp-get-remote-path vec)))))
;; We must check also for some Perl modules.
(when result
- (with-connection-property vec "perl-file-spec"
+ (with-tramp-connection-property vec "perl-file-spec"
(tramp-send-command-and-check
vec (format "%s -e 'use File::Spec;'" result)))
- (with-connection-property vec "perl-cwd-realpath"
+ (with-tramp-connection-property vec "perl-cwd-realpath"
(tramp-send-command-and-check
vec (format "%s -e 'use Cwd \"realpath\";'" result))))
result)))
(defun tramp-get-remote-stat (vec)
- (with-connection-property vec "stat"
+ (with-tramp-connection-property vec "stat"
(tramp-message vec 5 "Finding a suitable `stat' command")
(let ((result (tramp-find-executable
vec "stat" (tramp-get-remote-path vec)))
result)))
(defun tramp-get-remote-readlink (vec)
- (with-connection-property vec "readlink"
+ (with-tramp-connection-property vec "readlink"
(tramp-message vec 5 "Finding a suitable `readlink' command")
(let ((result (tramp-find-executable
vec "readlink" (tramp-get-remote-path vec))))
result))))
(defun tramp-get-remote-trash (vec)
- (with-connection-property vec "trash"
+ (with-tramp-connection-property vec "trash"
(tramp-message vec 5 "Finding a suitable `trash' command")
(tramp-find-executable vec "trash" (tramp-get-remote-path vec))))
(defun tramp-get-remote-id (vec)
- (with-connection-property vec "id"
+ (with-tramp-connection-property vec "id"
(tramp-message vec 5 "Finding POSIX `id' command")
(or
(catch 'id-found
(tramp-error vec 'file-error "Couldn't find a POSIX `id' command"))))
(defun tramp-get-remote-uid (vec id-format)
- (with-connection-property vec (format "uid-%s" id-format)
+ (with-tramp-connection-property vec (format "uid-%s" id-format)
(let ((res (tramp-send-command-and-read
vec
(format "%s -u%s %s"
(if (and (equal id-format 'integer) (not (integerp res))) -1 res))))
(defun tramp-get-remote-gid (vec id-format)
- (with-connection-property vec (format "gid-%s" id-format)
+ (with-tramp-connection-property vec (format "gid-%s" id-format)
(let ((res (tramp-send-command-and-read
vec
(format "%s -g%s %s"
(if (equal id-format 'integer) (user-uid) (user-login-name)))
(defun tramp-get-local-gid (id-format)
- (nth 3 (tramp-compat-file-attributes "~/" id-format)))
+ (if (and (fboundp 'group-gid) (equal id-format 'integer))
+ (tramp-compat-funcall 'group-gid)
+ (nth 3 (tramp-compat-file-attributes "~/" id-format))))
;; Some predefined connection properties.
(defun tramp-get-inline-compress (vec prop size)
If no corresponding command is found, nil is returned."
(when (and (integerp tramp-inline-compress-start-size)
(> size tramp-inline-compress-start-size))
- (with-connection-property (tramp-get-connection-process vec) prop
+ (with-tramp-connection-property (tramp-get-connection-process vec) prop
(tramp-find-inline-compress vec)
(tramp-get-connection-property
(tramp-get-connection-process vec) prop nil))))
;; no inline coding is found.
(ignore-errors
(let ((coding
- (with-connection-property (tramp-get-connection-process vec) prop
+ (with-tramp-connection-property
+ (tramp-get-connection-process vec) prop
(tramp-find-inline-encoding vec)
(tramp-get-connection-property
(tramp-get-connection-process vec) prop nil)))
(t
(format "%s <%%s" coding)))))))
-;;; Integration of eshell.el:
-
-(eval-when-compile
- (defvar eshell-path-env))
-
-;; eshell.el keeps the path in `eshell-path-env'. We must change it
-;; when `default-directory' points to another host.
-(defun tramp-eshell-directory-change ()
- "Set `eshell-path-env' to $PATH of the host related to `default-directory'."
- (setq eshell-path-env
- (if (file-remote-p default-directory)
- (with-parsed-tramp-file-name default-directory nil
- (mapconcat
- 'identity
- (tramp-get-remote-path v)
- ":"))
- (getenv "PATH"))))
-
-(eval-after-load "esh-util"
- '(progn
- (tramp-eshell-directory-change)
- (add-hook 'eshell-directory-change-hook
- 'tramp-eshell-directory-change)
- (add-hook 'tramp-unload-hook
- (lambda ()
- (remove-hook 'eshell-directory-change-hook
- 'tramp-eshell-directory-change)))))
-
(add-hook 'tramp-unload-hook
(lambda ()
(unload-feature 'tramp-sh 'force)))