;;; Code:
-(eval-when-compile (require 'cl)) ; ignore-errors
(require 'tramp)
-;; Pacify byte-compiler. The function is needed on XEmacs only. I'm
-;; not sure at all that this is the right way to do it, but let's hope
-;; it works for now, and wait for a guru to point out the Right Way to
-;; achieve this.
-;;(eval-when-compile
-;; (unless (fboundp 'dired-insert-set-properties)
-;; (fset 'dired-insert-set-properties 'ignore)))
-;; Gerd suggests this:
-(eval-when-compile (require 'dired))
-;; Note that dired is required at run-time, too, when it is needed.
-;; It is only needed on XEmacs for the function
-;; `dired-insert-set-properties'.
+;; Pacify byte-compiler.
+(eval-when-compile
+ (require 'cl)
+ (require 'dired))
+(defvar directory-sep-char)
+(defvar tramp-gw-tunnel-method)
+(defvar tramp-gw-socks-method)
(defcustom tramp-inline-compress-start-size 4096
"The minimum size of compressing where inline transfer.
(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"
- (tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-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 (("-1") ("-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
- '("scp2"
- (tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-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 (("-2") ("-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
- '("scpc"
+ '("scp"
(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 "scp")
- (tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q") ("-r")
- ("-o" "ControlPath=%t.%%r@%%h:%%p")
- ("-o" "ControlMaster=auto")))
+ (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
'("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-async-args (("-q")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (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
- '("ssh1"
- (tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-1") ("-e" "none") ("%h")))
- (tramp-async-args (("-q")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (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
- '("ssh2"
- (tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p")
- ("-2") ("-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
'("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-login-program "su")
(tramp-login-args (("-") ("%u")))
(tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))))
+ (tramp-remote-shell-args ("-c"))
+ (tramp-connection-timeout 10)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
'("sudo"
(tramp-login-program "sudo")
(tramp-login-args (("-u" "%u") ("-s") ("-H") ("-p" "Password:")))
(tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))))
+ (tramp-remote-shell-args ("-c"))
+ (tramp-connection-timeout 10)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
'("ksu"
(tramp-login-program "ksu")
(tramp-login-args (("%u") ("-q")))
(tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))))
+ (tramp-remote-shell-args ("-c"))
+ (tramp-connection-timeout 10)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
'("krlogin"
(tramp-remote-shell-args ("-c"))
(tramp-default-port 22)))
;;;###tramp-autoload
-(add-to-list 'tramp-methods
- '("plink1"
- (tramp-login-program "plink")
- (tramp-login-args (("-l" "%u") ("-P" "%p") ("-1" "-ssh") ("%h")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-default-port 22)))
-;;;###tramp-autoload
(add-to-list 'tramp-methods
`("plinkx"
(tramp-login-program "plink")
(tramp-set-completion-function "rcp" tramp-completion-function-alist-rsh)
(tramp-set-completion-function "remcp" tramp-completion-function-alist-rsh)
(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)
(tramp-set-completion-function
"krlogin" tramp-completion-function-alist-rsh)
(tramp-set-completion-function "plink" tramp-completion-function-alist-ssh)
- (tramp-set-completion-function
- "plink1" tramp-completion-function-alist-ssh)
(tramp-set-completion-function
"plinkx" tramp-completion-function-alist-putty)
(tramp-set-completion-function "pscp" tramp-completion-function-alist-ssh)
(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"
+ `("HISTFILE=$HOME/.tramp_history" "HISTSIZE=1" "TMOUT=0" "LC_ALL=C"
,(format "TERM=%s" tramp-terminal-type)
"EMACS=t" ;; Deprecated.
,(format "INSIDE_EMACS='%s,tramp:%s'" emacs-version tramp-version)
Escape sequence %s is replaced with name of Perl binary.
This string is passed to `format', so percent characters need to be doubled.")
+(defconst tramp-perl-pack
+ "%s -e 'binmode STDIN; binmode STDOUT; print pack(q{u*}, join q{}, <>)'"
+ "Perl program to use for encoding a file.
+Escape sequence %s is replaced with name of Perl binary.")
+
+(defconst tramp-perl-unpack
+ "%s -e 'binmode STDIN; binmode STDOUT; print unpack(q{u*}, join q{}, <>)'"
+ "Perl program to use for decoding a file.
+Escape sequence %s is replaced with name of Perl binary.")
+
(defconst tramp-vc-registered-read-file-names
"echo \"(\"
while read file; do
here-document, otherwise the command could exceed maximum length
of command line.")
-(defconst tramp-file-mode-type-map
- '((0 . "-") ; Normal file (SVID-v2 and XPG2)
- (1 . "p") ; fifo
- (2 . "c") ; character device
- (3 . "m") ; multiplexed character device (v7)
- (4 . "d") ; directory
- (5 . "?") ; Named special file (XENIX)
- (6 . "b") ; block device
- (7 . "?") ; multiplexed block device (v7)
- (8 . "-") ; regular file
- (9 . "n") ; network special file (HP-UX)
- (10 . "l") ; symlink
- (11 . "?") ; ACL shadow inode (Solaris, not userspace)
- (12 . "s") ; socket
- (13 . "D") ; door special (Solaris)
- (14 . "w")) ; whiteout (BSD)
- "A list of file types returned from the `stat' system call.
-This is used to map a mode number to a permission string.")
-
-;; New handlers should be added here. The following operations can be
-;; handled using the normal primitives: file-name-sans-versions,
-;; get-file-buffer.
+;; New handlers should be added here.
(defconst tramp-sh-file-name-handler-alist
- '((load . tramp-handle-load)
- (make-symbolic-link . tramp-sh-handle-make-symbolic-link)
- (file-name-as-directory . tramp-handle-file-name-as-directory)
- (file-name-directory . tramp-handle-file-name-directory)
- (file-name-nondirectory . tramp-handle-file-name-nondirectory)
- (file-truename . tramp-sh-handle-file-truename)
- (file-exists-p . tramp-sh-handle-file-exists-p)
+ '(;; `access-file' performed by default handler.
+ (add-name-to-file . tramp-sh-handle-add-name-to-file)
+ ;; `byte-compiler-base-file-name' performed by default handler.
+ (copy-directory . tramp-sh-handle-copy-directory)
+ (copy-file . tramp-sh-handle-copy-file)
+ (delete-directory . tramp-sh-handle-delete-directory)
+ (delete-file . tramp-sh-handle-delete-file)
+ ;; `diff-latest-backup-file' performed by default handler.
+ (directory-file-name . tramp-handle-directory-file-name)
+ (directory-files . tramp-handle-directory-files)
+ (directory-files-and-attributes
+ . tramp-sh-handle-directory-files-and-attributes)
+ ;; `dired-call-process' performed by default handler.
+ (dired-compress-file . tramp-sh-handle-dired-compress-file)
+ (dired-recursive-delete-directory
+ . tramp-sh-handle-dired-recursive-delete-directory)
+ (dired-uncache . tramp-handle-dired-uncache)
+ (expand-file-name . tramp-sh-handle-expand-file-name)
(file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
+ (file-acl . tramp-sh-handle-file-acl)
+ (file-attributes . tramp-sh-handle-file-attributes)
(file-directory-p . tramp-sh-handle-file-directory-p)
+ ;; `file-equal-p' performed by default handler.
(file-executable-p . tramp-sh-handle-file-executable-p)
+ (file-exists-p . tramp-sh-handle-file-exists-p)
+ ;; `file-in-directory-p' performed by default handler.
+ (file-local-copy . tramp-sh-handle-file-local-copy)
+ (file-modes . tramp-handle-file-modes)
+ (file-name-all-completions . tramp-sh-handle-file-name-all-completions)
+ (file-name-as-directory . tramp-handle-file-name-as-directory)
+ (file-name-completion . tramp-handle-file-name-completion)
+ (file-name-directory . tramp-handle-file-name-directory)
+ (file-name-nondirectory . tramp-handle-file-name-nondirectory)
+ ;; `file-name-sans-versions' performed by default handler.
+ (file-newer-than-file-p . tramp-sh-handle-file-newer-than-file-p)
+ (file-notify-add-watch . tramp-sh-handle-file-notify-add-watch)
+ (file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
+ (file-ownership-preserved-p . tramp-sh-handle-file-ownership-preserved-p)
(file-readable-p . tramp-sh-handle-file-readable-p)
(file-regular-p . tramp-handle-file-regular-p)
+ (file-remote-p . tramp-handle-file-remote-p)
+ (file-selinux-context . tramp-sh-handle-file-selinux-context)
(file-symlink-p . tramp-handle-file-symlink-p)
+ (file-truename . tramp-sh-handle-file-truename)
(file-writable-p . tramp-sh-handle-file-writable-p)
- (file-ownership-preserved-p . tramp-sh-handle-file-ownership-preserved-p)
- (file-newer-than-file-p . tramp-sh-handle-file-newer-than-file-p)
- (file-attributes . tramp-sh-handle-file-attributes)
- (file-modes . tramp-handle-file-modes)
- (directory-files . tramp-handle-directory-files)
- (directory-files-and-attributes
- . tramp-sh-handle-directory-files-and-attributes)
- (file-name-all-completions . tramp-sh-handle-file-name-all-completions)
- (file-name-completion . tramp-handle-file-name-completion)
- (add-name-to-file . tramp-sh-handle-add-name-to-file)
- (copy-file . tramp-sh-handle-copy-file)
- (copy-directory . tramp-sh-handle-copy-directory)
+ (find-backup-file-name . tramp-handle-find-backup-file-name)
+ ;; `find-file-noselect' performed by default handler.
+ ;; `get-file-buffer' performed by default handler.
+ (insert-directory . tramp-sh-handle-insert-directory)
+ (insert-file-contents . tramp-handle-insert-file-contents)
+ (insert-file-contents-literally
+ . tramp-sh-handle-insert-file-contents-literally)
+ (load . tramp-handle-load)
+ (make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
+ (make-directory . tramp-sh-handle-make-directory)
+ (make-symbolic-link . tramp-sh-handle-make-symbolic-link)
+ (process-file . tramp-sh-handle-process-file)
(rename-file . tramp-sh-handle-rename-file)
+ (set-file-acl . tramp-sh-handle-set-file-acl)
(set-file-modes . tramp-sh-handle-set-file-modes)
+ (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context)
(set-file-times . tramp-sh-handle-set-file-times)
- (make-directory . tramp-sh-handle-make-directory)
- (delete-directory . tramp-sh-handle-delete-directory)
- (delete-file . tramp-sh-handle-delete-file)
- (directory-file-name . tramp-handle-directory-file-name)
- ;; `executable-find' is not official yet.
- (executable-find . tramp-sh-handle-executable-find)
- (start-file-process . tramp-sh-handle-start-file-process)
- (process-file . tramp-sh-handle-process-file)
+ (set-visited-file-modtime . tramp-sh-handle-set-visited-file-modtime)
(shell-command . tramp-handle-shell-command)
- (insert-directory . tramp-sh-handle-insert-directory)
- (expand-file-name . tramp-sh-handle-expand-file-name)
+ (start-file-process . tramp-sh-handle-start-file-process)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
- (file-local-copy . tramp-sh-handle-file-local-copy)
- (file-remote-p . tramp-handle-file-remote-p)
- (insert-file-contents . tramp-handle-insert-file-contents)
- (insert-file-contents-literally
- . tramp-sh-handle-insert-file-contents-literally)
- (write-region . tramp-sh-handle-write-region)
- (find-backup-file-name . tramp-handle-find-backup-file-name)
- (make-auto-save-file-name . tramp-sh-handle-make-auto-save-file-name)
(unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory)
- (dired-compress-file . tramp-sh-handle-dired-compress-file)
- (dired-recursive-delete-directory
- . tramp-sh-handle-dired-recursive-delete-directory)
- (dired-uncache . tramp-handle-dired-uncache)
- (set-visited-file-modtime . tramp-sh-handle-set-visited-file-modtime)
+ (vc-registered . tramp-sh-handle-vc-registered)
(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))
+ (write-region . tramp-sh-handle-write-region))
"Alist of handler functions.
Operations not mentioned here will be handled by the normal Emacs functions.")
(tramp-shell-quote-argument l-localname))
t))))
-(defun tramp-sh-handle-file-truename (filename &optional counter prev-dirs)
+(defun tramp-sh-handle-file-truename (filename)
"Like `file-truename' for Tramp files."
(with-parsed-tramp-file-name (expand-file-name filename) nil
(tramp-make-tramp-file-name method user host
(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)
;; This function makes the same assumption as
;; `tramp-sh-handle-set-visited-file-modtime'.
-(defun tramp-sh-handle-verify-visited-file-modtime (buf)
+(defun tramp-sh-handle-verify-visited-file-modtime (&optional buf)
"Like `verify-visited-file-modtime' for Tramp files.
At the time `verify-visited-file-modtime' calls this function, we
already know that the buffer is visiting a file and that
`visited-file-modtime' does not return 0. Do not call this
function directly, unless those two cases are already taken care
of."
- (with-current-buffer buf
+ (with-current-buffer (or buf (current-buffer))
(let ((f (buffer-file-name)))
;; There is no file visiting the buffer, or the buffer has no
;; recorded last modification time, or there is no established
(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))
;; without `set-file-times', this function is an alias for this.
;; We are local, so we don't need the UTC settings.
(zerop
- (tramp-compat-call-process
+ (tramp-call-process
"touch" nil nil nil "-t"
(format-time-string "%Y%m%d%H%M.%S" time)
(tramp-shell-quote-argument filename)))))
;; `set-file-uid-gid'. On W32 "chown" might not work.
(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
+ (tramp-call-process
"chown" nil nil nil
(format "%d:%d" uid gid) (tramp-shell-quote-argument filename))))))
'copy-file (list filename newname ok-if-already-exists keep-date)))))
(defun tramp-sh-handle-copy-directory
- (dirname newname &optional keep-date parents copy-contents)
+ (dirname newname &optional keep-date parents _copy-contents)
"Like `copy-directory' for Tramp files."
(let ((t1 (tramp-tramp-file-p dirname))
(t2 (tramp-tramp-file-p newname)))
(t2 (tramp-tramp-file-p newname))
(length (nth 7 (file-attributes (file-truename filename))))
(attributes (and preserve-extended-attributes
- (apply 'file-extended-attributes (list filename))))
- pr tm)
+ (apply 'file-extended-attributes (list filename)))))
(with-parsed-tramp-file-name (if t1 filename newname) nil
(when (and (not ok-if-already-exists) (file-exists-p newname))
(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
+ (if tramp-use-ssh-controlmaster-options
+ 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)
(tramp-get-method-parameter method 'tramp-copy-env))))
;; Check for program.
- (unless (let ((default-directory
- (tramp-compat-temporary-file-directory)))
- (executable-find copy-program))
+ (unless (executable-find copy-program)
(tramp-error
v 'file-error "Cannot find copy program: %s" 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
(tramp-error
v 'file-error "Failed to recursively delete %s" filename))))
-(defun tramp-sh-handle-dired-compress-file (file &rest ok-flag)
+(defun tramp-sh-handle-dired-compress-file (file &rest _ok-flag)
"Like `dired-compress-file' for Tramp files."
;; OK-FLAG is valid for XEmacs only, but not implemented.
;; Code stolen mainly from dired-aux.el.
'file-name-nondirectory (list localname)))
(setq localname (tramp-run-real-handler
'file-name-directory (list localname))))
- (unless full-directory-p
- (setq switches (add-to-list 'switches "-d" 'append)))
+ (unless (or full-directory-p (member "-d" switches))
+ (setq switches (append switches '("-d"))))
(setq switches (mapconcat 'tramp-shell-quote-argument switches " "))
(when wildcard
(setq switches (concat switches " " wildcard)))
(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
+ (and (boundp 'default-file-name-coding-system)
+ (symbol-value '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))
;;; Remote commands:
-(defun tramp-sh-handle-executable-find (command)
- "Like `executable-find' for Tramp files."
- (with-parsed-tramp-file-name default-directory nil
- (tramp-find-executable v command (tramp-get-remote-path v) t)))
-
(defun tramp-process-sentinel (proc event)
"Flush file caches."
(unless (memq (process-status proc) '(run open))
(let ((vec (tramp-get-connection-property proc "vector" nil)))
(when vec
- (tramp-message vec 5 "Sentinel called: `%s' `%s'" proc event)
+ (tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event)
(tramp-flush-connection-property proc)
(tramp-flush-directory-property vec "")))))
(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))
(rem-enc
(save-excursion
(with-tramp-progress-reporter
- v 3 (format "Encoding remote file %s" filename)
+ v 3
+ (format "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"))
- (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.
- (with-temp-buffer
- (set-buffer-multibyte nil)
- (insert-buffer-substring (tramp-get-buffer v))
- (with-tramp-progress-reporter
- v 3 (format "Decoding remote file %s with function %s"
- filename loc-dec)
+ (with-tramp-progress-reporter
+ v 3 (format "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.
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert-buffer-substring (tramp-get-buffer v))
(funcall loc-dec (point-min) (point-max))
;; Unset `file-name-handler-alist'. Otherwise,
;; epa-file gets confused.
(let (file-name-handler-alist
(coding-system-for-write 'binary))
- (write-region (point-min) (point-max) tmpfile))))
-
- ;; 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))
- (write-region (point-min) (point-max) tmpfile2))
- (with-tramp-progress-reporter
- v 3 (format "Decoding remote file %s with command %s"
- filename loc-dec)
+ (write-region (point-min) (point-max) tmpfile)))
+
+ ;; 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)))
(unwind-protect
(tramp-call-local-coding-command
loc-dec tmpfile2 tmpfile)
(inhibit-file-name-operation 'insert-file-contents))
(unwind-protect
(progn
- (fset 'find-buffer-file-type (lambda (filename) t))
+ (fset 'find-buffer-file-type (lambda (_filename) t))
(insert-file-contents filename visit beg end replace))
;; Save exit.
(if find-buffer-file-type-function
(fset 'find-buffer-file-type find-buffer-file-type-function)
(fmakunbound 'find-buffer-file-type)))))
-(defun tramp-sh-handle-make-auto-save-file-name ()
- "Like `make-auto-save-file-name' for Tramp files.
-Returns a file name in `tramp-auto-save-directory' for autosaving this file."
- (let ((tramp-auto-save-directory tramp-auto-save-directory)
- (buffer-file-name
- (tramp-subst-strs-in-string
- '(("_" . "|")
- ("/" . "_a")
- (":" . "_b")
- ("|" . "__")
- ("[" . "_l")
- ("]" . "_r"))
- (buffer-file-name))))
- ;; File name must be unique. This is ensured with Emacs 22 (see
- ;; UNIQUIFY element of `auto-save-file-name-transforms'); but for
- ;; all other cases we must do it ourselves.
- (when (boundp 'auto-save-file-name-transforms)
- (mapc
- (lambda (x)
- (when (and (string-match (car x) buffer-file-name)
- (not (car (cddr x))))
- (setq tramp-auto-save-directory
- (or tramp-auto-save-directory
- (tramp-compat-temporary-file-directory)))))
- (symbol-value 'auto-save-file-name-transforms)))
- ;; Create directory.
- (when tramp-auto-save-directory
- (setq buffer-file-name
- (expand-file-name buffer-file-name tramp-auto-save-directory))
- (unless (file-exists-p tramp-auto-save-directory)
- (make-directory tramp-auto-save-directory t)))
- ;; Run plain `make-auto-save-file-name'. There might be an advice when
- ;; it is not a magic file name operation (since Emacs 22).
- ;; We must deactivate it temporarily.
- (if (not (ad-is-active 'make-auto-save-file-name))
- (tramp-run-real-handler 'make-auto-save-file-name nil)
- ;; else
- (ad-deactivate 'make-auto-save-file-name)
- (prog1
- (tramp-run-real-handler 'make-auto-save-file-name nil)
- (ad-activate 'make-auto-save-file-name)))))
-
;; CCC grok LOCKNAME
(defun tramp-sh-handle-write-region
(start end filename &optional append visit lockname confirm)
(with-temp-buffer
(set-buffer-multibyte nil)
;; Use encoding function or command.
- (if (functionp loc-enc)
- (with-tramp-progress-reporter
- v 3 (format "Encoding region using function `%s'"
- loc-enc)
- (let ((coding-system-for-read 'binary))
- (insert-file-contents-literally tmpfile))
- ;; The following `let' is a workaround for the
- ;; base64.el that comes with pgnus-0.84. If
- ;; both of the following conditions are
+ (with-tramp-progress-reporter
+ v 3 (format "Encoding local file `%s' using `%s'"
+ tmpfile loc-enc)
+ (if (functionp loc-enc)
+ ;; The following `let' is a workaround for
+ ;; the base64.el that comes with pgnus-0.84.
+ ;; If both of the following conditions are
;; satisfied, it tries to write to a local
;; file in default-directory, but at this
;; point, default-directory is remote.
;; (`call-process-region' can't write to
;; remote files, it seems.) The file in
;; question is a tmp file anyway.
- (let ((default-directory
+ (let ((coding-system-for-read 'binary)
+ (default-directory
(tramp-compat-temporary-file-directory)))
- (funcall loc-enc (point-min) (point-max))))
+ (insert-file-contents-literally tmpfile)
+ (funcall loc-enc (point-min) (point-max)))
- (with-tramp-progress-reporter
- v 3 (format "Encoding region using command `%s'"
- loc-enc)
(unless (zerop (tramp-call-local-coding-command
loc-enc tmpfile t))
(tramp-error
;; writes to remote file. Because this happens on
;; the remote host, we cannot use the function.
(with-tramp-progress-reporter
- v 3
- (format "Decoding region into remote file %s" filename)
+ v 3 (format "Decoding remote file `%s' using `%s'"
+ filename rem-dec)
(goto-char (point-max))
(unless (bolp) (newline))
(tramp-send-command
(erase-buffer)
(and
;; cksum runs locally, if possible.
- (zerop (tramp-compat-call-process "cksum" tmpfile t))
+ (zerop (tramp-call-process "cksum" tmpfile t))
;; cksum runs remotely.
(tramp-send-command-and-check
v
;; `process-file-side-effects' in order to keep the cache when
;; `process-file' calls appear.
(let (process-file-side-effects)
- (tramp-run-real-handler 'vc-registered (list file)))))))
+ (ignore-errors
+ (tramp-run-real-handler 'vc-registered (list file))))))))
;;;###tramp-autoload
(defun tramp-sh-file-name-handler (operation &rest args)
;; Default file name handlers, we don't care.
(t (tramp-run-real-handler operation args)))))))
+(defun tramp-sh-handle-file-notify-add-watch (file-name flags _callback)
+ "Like `file-notify-add-watch' for Tramp files."
+ (setq file-name (expand-file-name file-name))
+ (with-parsed-tramp-file-name file-name nil
+ (let* ((default-directory (file-name-directory file-name))
+ command events filter p)
+ (cond
+ ;; gvfs-monitor-dir.
+ ((setq command (tramp-get-remote-gvfs-monitor-dir v))
+ (setq filter 'tramp-sh-file-gvfs-monitor-dir-process-filter
+ p (start-file-process
+ "gvfs-monitor-dir" (generate-new-buffer " *gvfs-monitor-dir*")
+ command localname)))
+ ;; inotifywait.
+ ((setq command (tramp-get-remote-inotifywait v))
+ (setq filter 'tramp-sh-file-inotifywait-process-filter
+ events
+ (cond
+ ((and (memq 'change flags) (memq 'attribute-change flags))
+ "create,modify,move,delete,attrib")
+ ((memq 'change flags) "create,modify,move,delete")
+ ((memq 'attribute-change flags) "attrib"))
+ p (start-file-process
+ "inotifywait" (generate-new-buffer " *inotifywait*")
+ command "-mq" "-e" events localname)))
+ ;; None.
+ (t (tramp-error
+ v 'file-notify-error
+ "No file notification program found on %s"
+ (file-remote-p file-name))))
+ ;; Return the process object as watch-descriptor.
+ (if (not (processp p))
+ (tramp-error
+ v 'file-notify-error "`%s' failed to start on remote host" command)
+ (tramp-compat-set-process-query-on-exit-flag p nil)
+ (set-process-filter p filter)
+ p))))
+
+(defun tramp-sh-file-gvfs-monitor-dir-process-filter (proc string)
+ "Read output from \"gvfs-monitor-dir\" and add corresponding file-notify events."
+ (let ((remote-prefix
+ (with-current-buffer (process-buffer proc)
+ (file-remote-p default-directory)))
+ (rest-string (tramp-compat-process-get proc 'rest-string)))
+ (when rest-string
+ (tramp-message proc 10 "Previous string:\n%s" rest-string))
+ (tramp-message proc 6 "%S\n%s" proc string)
+ (setq string (concat rest-string string)
+ ;; Attribute change is returned in unused wording.
+ string (tramp-compat-replace-regexp-in-string
+ "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string))
+
+ (while (string-match
+ (concat "^[\n\r]*"
+ "Directory Monitor Event:[\n\r]+"
+ "Child = \\([^\n\r]+\\)[\n\r]+"
+ "\\(Other = \\([^\n\r]+\\)[\n\r]+\\)?"
+ "Event = \\([^[:blank:]]+\\)[\n\r]+")
+ string)
+ (let ((object
+ (list
+ proc
+ (intern-soft
+ (tramp-compat-replace-regexp-in-string
+ "_" "-" (downcase (match-string 4 string))))
+ ;; File names are returned as absolute paths. We must
+ ;; add the remote prefix.
+ (concat remote-prefix (match-string 1 string))
+ (when (match-string 3 string)
+ (concat remote-prefix (match-string 3 string))))))
+ (setq string (replace-match "" nil nil string))
+ ;; Usually, we would add an Emacs event now. Unfortunately,
+ ;; `unread-command-events' does not accept several events at
+ ;; once. Therefore, we apply the callback directly.
+ (tramp-compat-funcall 'file-notify-callback object)))
+
+ ;; Save rest of the string.
+ (when (zerop (length string)) (setq string nil))
+ (when string (tramp-message proc 10 "Rest string:\n%s" string))
+ (tramp-compat-process-put proc 'rest-string string)))
+
+(defun tramp-sh-file-inotifywait-process-filter (proc string)
+ "Read output from \"inotifywait\" and add corresponding file-notify events."
+ (tramp-message proc 6 "%S\n%s" proc string)
+ (dolist (line (split-string string "[\n\r]+" 'omit-nulls))
+ ;; Check, whether there is a problem.
+ (unless
+ (string-match
+ (concat "^[^[:blank:]]+"
+ "[[:blank:]]+\\([^[:blank:]]+\\)+"
+ "\\([[:blank:]]+\\([^\n\r]+\\)\\)?")
+ line)
+ (tramp-error proc 'file-notify-error "%s" line))
+
+ (let ((object
+ (list
+ proc
+ (mapcar
+ (lambda (x)
+ (intern-soft
+ (tramp-compat-replace-regexp-in-string "_" "-" (downcase x))))
+ (split-string (match-string 1 line) "," 'omit-nulls))
+ (match-string 3 line))))
+ ;; Usually, we would add an Emacs event now. Unfortunately,
+ ;; `unread-command-events' does not accept several events at
+ ;; once. Therefore, we apply the callback directly.
+ (tramp-compat-funcall 'file-notify-callback object))))
+
;;; Internal Functions:
(defun tramp-maybe-send-script (vec script name)
(unless (member name scripts)
(with-tramp-progress-reporter vec 5 (format "Sending script `%s'" name)
;; The script could contain a call of Perl. This is masked with `%s'.
+ (when (and (string-match "%s" script)
+ (not (tramp-get-remote-perl vec)))
+ (tramp-error vec 'file-error "No Perl available on remote host"))
(tramp-barf-unless-okay
vec
(format "%s () {\n%s\n}" name
I.e., for each directory in `tramp-remote-path', it is tested
whether it exists and if so, it is added to the environment
variable PATH."
- (tramp-message vec 5 (format "Setting $PATH environment variable"))
+ (tramp-message vec 5 "Setting $PATH environment variable")
(tramp-send-command
vec (format "PATH=%s; export PATH"
(mapconcat 'identity (tramp-get-remote-path vec) ":"))))
(unless (string-equal shell default-shell)
(tramp-message
vec 5 "Starting remote shell `%s' for tilde expansion" shell)
- (tramp-open-shell vec shell))
-
- ;; Busyboxes tend to behave strange. We check for the existence.
- (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))))))
+ (tramp-open-shell vec shell)))))
;; Utility functions.
"Wait for shell prompt and barf if none appears.
Looks at process PROC to see if a shell prompt appears in TIMEOUT
seconds. If not, it produces an error message with the given ERROR-ARGS."
- (unless
- (tramp-wait-for-regexp
- proc timeout
- (format
- "\\(%s\\|%s\\)\\'" shell-prompt-pattern tramp-shell-prompt-pattern))
- (apply 'tramp-error-with-buffer nil proc 'file-error error-args)))
+ (let ((vec (tramp-get-connection-property proc "vector" nil)))
+ (condition-case nil
+ (tramp-wait-for-regexp
+ proc timeout
+ (format
+ "\\(%s\\|%s\\)\\'" shell-prompt-pattern tramp-shell-prompt-pattern))
+ (error
+ (delete-process proc)
+ (apply 'tramp-error-with-buffer
+ (tramp-get-connection-buffer vec) vec 'file-error error-args)))))
(defun tramp-open-connection-setup-interactive-shell (proc vec)
"Set up an interactive shell.
vec "uname"
(tramp-send-command-and-read vec "echo \\\"`uname -sr`\\\""))))
(when (and (stringp old-uname) (not (string-equal old-uname new-uname)))
- (tramp-cleanup vec)
(tramp-message
vec 3
"Connection reset, because remote host changed from `%s' to `%s'"
old-uname new-uname)
+ ;; We want to keep the password.
+ (tramp-cleanup-connection vec t t)
(throw 'uname-changed (tramp-maybe-open-connection vec))))
;; Check whether the remote host suffers from buggy
(tramp-send-command
vec (format "unset %s" (mapconcat 'identity unset " ")) t))))
-;; CCC: We should either implement a Perl version of base64 encoding
-;; and decoding. Then we just use that in the last item. The other
-;; alternative is to use the Perl version of UU encoding. But then
-;; we need a Lisp version of uuencode.
-;;
;; Old text from documentation of tramp-methods:
;; Using a uuencode/uudecode inline method is discouraged, please use one
;; of the base64 methods instead since base64 encoding is much more
(autoload 'uudecode-decode-region "uudecode")
(defconst tramp-local-coding-commands
- '((b64 base64-encode-region base64-decode-region)
+ `((b64 base64-encode-region base64-decode-region)
(uu tramp-uuencode-region uudecode-decode-region)
- (pack
- "perl -e 'binmode STDIN; binmode STDOUT; print pack(q{u*}, join q{}, <>)'"
- "perl -e 'binmode STDIN; binmode STDOUT; print unpack(q{u*}, join q{}, <>)'"))
+ (pack ,(format tramp-perl-pack "perl") ,(format tramp-perl-unpack "perl")))
"List of local coding commands for inline transfer.
Each item is a list that looks like this:
(uu "uuencode xxx" "uudecode -o -")
(uu "uuencode xxx" "uudecode -p")
(uu "uuencode xxx" tramp-uudecode)
- (pack
- "perl -e 'binmode STDIN; binmode STDOUT; print pack(q{u*}, join q{}, <>)'"
- "perl -e 'binmode STDIN; binmode STDOUT; print unpack(q{u*}, join q{}, <>)'"))
+ (pack tramp-perl-pack tramp-perl-unpack))
"List of remote coding commands for inline transfer.
Each item is a list that looks like this:
OUTPUT can be a string (which specifies a filename), or t (which
means standard output and thus the current buffer), or nil (which
means discard it)."
- (tramp-compat-call-process
+ (tramp-call-process
tramp-encoding-shell
(when (and input (not (string-match "%s" cmd))) input)
(if (eq output t) t nil)
tramp-encoding-command-switch
(concat
(if (string-match "%s" cmd) (format cmd input) cmd)
- (if (stringp output) (concat "> " output) ""))))
+ (if (stringp output) (concat " >" output) ""))))
(defconst tramp-inline-compress-commands
'(("gzip" "gzip -d")
decompress (nth 1 item))
(tramp-message
vec 5
- "Checking local compress command `%s', `%s' for sanity"
+ "Checking local compress commands `%s', `%s' for sanity"
compress decompress)
(unless
(zerop
(throw 'next nil))
(tramp-message
vec 5
- "Checking remote compress command `%s', `%s' for sanity"
+ "Checking remote compress commands `%s', `%s' for sanity"
compress decompress)
(unless (tramp-send-command-and-check
vec (format "echo %s | %s | %s" magic compress decompress) t)
?h (or (tramp-file-name-host (car target-alist)) ""))))
(with-parsed-tramp-file-name proxy l
;; Add the hop.
- (add-to-list 'target-alist l)
+ (push l target-alist)
;; Start next search.
(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?
vec 'file-error
"Connection `%s' is not supported for gateway access." hop))
;; Open the gateway connection.
- (add-to-list
- 'target-alist
+ (push
(vector
(tramp-file-name-method hop) (tramp-file-name-user hop)
- (tramp-compat-funcall 'tramp-gw-open-connection vec gw hop) nil nil))
+ (tramp-compat-funcall 'tramp-gw-open-connection vec gw hop) nil nil)
+ target-alist)
;; For the password prompt, we need the correct values.
;; Therefore, we must remember the gateway vector. But we
;; cannot do it as connection property, because it shouldn't
;; Result.
target-alist))
-(defvar tramp-current-connection nil
- "Last connection timestamp.")
-
(defun tramp-maybe-open-connection (vec)
"Maybe open a connection VEC.
Does not do anything if a connection is already open, but re-opens the
connection if a previous connection has died for some reason."
- (catch 'uname-changed
- (let ((p (tramp-get-connection-process vec))
- (process-name (tramp-get-connection-property vec "process-name" nil))
- (process-environment (copy-sequence process-environment))
- (pos (with-current-buffer (tramp-get-connection-buffer vec) (point))))
-
- ;; If Tramp opens the same connection within a short time frame,
- ;; there is a problem. We shall signal this.
- (unless (or (and p (processp p) (memq (process-status p) '(run open)))
- (not (equal (butlast (append vec nil))
- (car tramp-current-connection)))
- (> (tramp-time-diff
- (current-time) (cdr tramp-current-connection))
- 5))
- (throw 'suppress 'suppress))
-
- ;; If too much time has passed since last command was sent, look
- ;; whether process is still alive. If it isn't, kill it. When
- ;; using ssh, it can sometimes happen that the remote end has
- ;; hung up but the local ssh client doesn't recognize this until
- ;; it tries to send some data to the remote end. So that's why
- ;; we try to send a command from time to time, then look again
- ;; whether the process is really alive.
- (condition-case nil
- (when (and (> (tramp-time-diff
- (current-time)
- (tramp-get-connection-property
- p "last-cmd-time" '(0 0 0)))
- 60)
- p (processp p) (memq (process-status p) '(run open)))
- (tramp-send-command vec "echo are you awake" t t)
- (unless (and (memq (process-status p) '(run open))
- (tramp-wait-for-output p 10))
- ;; The error will be caught locally.
- (tramp-error vec 'file-error "Awake did fail")))
- (file-error
- (tramp-cleanup vec)
- (setq p nil)))
-
- ;; New connection must be opened.
- (condition-case err
- (unless (and p (processp p) (memq (process-status p) '(run open)))
-
- ;; We call `tramp-get-buffer' in order to get a debug
- ;; buffer for messages from the beginning.
- (tramp-get-buffer vec)
-
- ;; If `non-essential' is non-nil, don't reopen a new connection.
- (when (and (boundp 'non-essential) (symbol-value 'non-essential))
- (throw 'non-essential 'non-essential))
-
- (with-tramp-progress-reporter
- vec 3
- (if (zerop (length (tramp-file-name-user vec)))
- (format "Opening connection for %s using %s"
- (tramp-file-name-host vec)
- (tramp-file-name-method vec))
- (format "Opening connection for %s@%s using %s"
- (tramp-file-name-user vec)
+ (tramp-check-proper-method-and-host vec)
+
+ (let ((p (tramp-get-connection-process vec))
+ (process-name (tramp-get-connection-property vec "process-name" nil))
+ (process-environment (copy-sequence process-environment))
+ (pos (with-current-buffer (tramp-get-connection-buffer vec) (point))))
+
+ ;; If Tramp opens the same connection within a short time frame,
+ ;; there is a problem. We shall signal this.
+ (unless (or (and p (processp p) (memq (process-status p) '(run open)))
+ (not (equal (butlast (append vec nil) 2)
+ (car tramp-current-connection)))
+ (> (tramp-time-diff
+ (current-time) (cdr tramp-current-connection))
+ (or tramp-connection-min-time-diff 0)))
+ (throw 'suppress 'suppress))
+
+ ;; If too much time has passed since last command was sent, look
+ ;; whether process is still alive. If it isn't, kill it. When
+ ;; using ssh, it can sometimes happen that the remote end has hung
+ ;; up but the local ssh client doesn't recognize this until it
+ ;; tries to send some data to the remote end. So that's why we
+ ;; try to send a command from time to time, then look again
+ ;; whether the process is really alive.
+ (condition-case nil
+ (when (and (> (tramp-time-diff
+ (current-time)
+ (tramp-get-connection-property
+ p "last-cmd-time" '(0 0 0)))
+ 60)
+ p (processp p) (memq (process-status p) '(run open)))
+ (tramp-send-command vec "echo are you awake" t t)
+ (unless (and (memq (process-status p) '(run open))
+ (tramp-wait-for-output p 10))
+ ;; The error will be caught locally.
+ (tramp-error vec 'file-error "Awake did fail")))
+ (file-error
+ (tramp-cleanup-connection vec t)
+ (setq p nil)))
+
+ ;; New connection must be opened.
+ (condition-case err
+ (unless (and p (processp p) (memq (process-status p) '(run open)))
+
+ ;; We call `tramp-get-buffer' in order to get a debug buffer
+ ;; for messages from the beginning.
+ (tramp-get-buffer vec)
+
+ ;; If `non-essential' is non-nil, don't reopen a new connection.
+ (when (and (boundp 'non-essential) (symbol-value 'non-essential))
+ (throw 'non-essential 'non-essential))
+
+ (with-tramp-progress-reporter
+ vec 3
+ (if (zerop (length (tramp-file-name-user vec)))
+ (format "Opening connection for %s using %s"
(tramp-file-name-host vec)
- (tramp-file-name-method vec)))
+ (tramp-file-name-method vec))
+ (format "Opening connection for %s@%s using %s"
+ (tramp-file-name-user vec)
+ (tramp-file-name-host vec)
+ (tramp-file-name-method vec)))
+ (catch 'uname-changed
;; Start new process.
(when (and p (processp p))
(delete-process p))
(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 (if tramp-use-ssh-controlmaster-options
+ tramp-ssh-controlmaster-options ""))
(process-connection-type tramp-process-connection-type)
(process-adaptive-read-buffering nil)
(coding-system-for-read nil)
(set-process-sentinel p 'tramp-process-sentinel)
(tramp-compat-set-process-query-on-exit-flag p nil)
(setq tramp-current-connection
- (cons (butlast (append vec nil)) (current-time))
+ (cons (butlast (append vec nil) 2) (current-time))
tramp-current-host (system-name))
(tramp-message
;; Check whether process is alive.
(tramp-barf-if-no-shell-prompt
- p 60
- "Couldn't find local shell prompt %s" tramp-encoding-shell)
+ p 10
+ "Couldn't find local shell prompt for %s" tramp-encoding-shell)
;; Now do all the connections as specified.
(while target-alist
(async-args
(tramp-get-method-parameter
l-method 'tramp-async-args))
+ (connection-timeout
+ (tramp-get-method-parameter
+ l-method 'tramp-connection-timeout))
(gw-args
(tramp-get-method-parameter l-method 'tramp-gw-args))
(gw (tramp-get-file-property hop "" "gateway" 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 "Sending command `%s'" command)
(tramp-send-command vec command t t)
(tramp-process-actions
- p vec pos tramp-actions-before-shell 60)
+ p vec pos tramp-actions-before-shell
+ (or connection-timeout tramp-connection-timeout))
(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))))
+ (tramp-open-connection-setup-interactive-shell p vec)))))
- ;; When the user did interrupt, we must cleanup.
- (quit
- (tramp-cleanup vec)
- ;; Propagate the quit signal.
- (signal (car err) (cdr err)))))))
+ ;; When the user did interrupt, we must cleanup.
+ (quit
+ (tramp-cleanup-connection vec t)
+ ;; Propagate the quit signal.
+ (signal (car err) (cdr err))))))
(defun tramp-send-command (vec command &optional neveropen nooutput)
"Send the COMMAND to connection VEC.
;; We mark the command string that it can be erased in the output buffer.
(tramp-set-connection-property p "check-remote-echo" t)
(setq command (format "%s%s%s" tramp-echo-mark command tramp-echo-mark)))
+ ;; Some busyboxes tend to close the connection when we use the
+ ;; following syntax for here-documents. This we cannot test; it
+ ;; shall be set via `tramp-connection-properties'.
(when (and (string-match "<<'EOF'" command)
(not (tramp-get-connection-property vec "busybox" nil)))
;; Unset $PS1 when using here documents, in order to avoid
(tramp-get-device vec))
attr))
-(defun tramp-check-cached-permissions (vec access)
- "Check `file-attributes' caches for VEC.
-Return t if according to the cache access type ACCESS is known to
-be granted."
- (let ((result nil)
- (offset (cond
- ((eq ?r access) 1)
- ((eq ?w access) 2)
- ((eq ?x access) 3))))
- (dolist (suffix '("string" "integer") result)
- (setq
- result
- (or
- result
- (let ((file-attr
- (tramp-get-file-property
- vec (tramp-file-name-localname vec)
- (concat "file-attributes-" suffix) nil))
- (remote-uid
- (tramp-get-connection-property
- vec (concat "uid-" suffix) nil))
- (remote-gid
- (tramp-get-connection-property
- vec (concat "gid-" suffix) nil)))
- (and
- file-attr
- (or
- ;; Not a symlink
- (eq t (car file-attr))
- (null (car file-attr)))
- (or
- ;; World accessible.
- (eq access (aref (nth 8 file-attr) (+ offset 6)))
- ;; User accessible and owned by user.
- (and
- (eq access (aref (nth 8 file-attr) offset))
- (equal remote-uid (nth 2 file-attr)))
- ;; Group accessible and owned by user's
- ;; principal group.
- (and
- (eq access (aref (nth 8 file-attr) (+ offset 3)))
- (equal remote-gid (nth 3 file-attr)))))))))))
-
-(defun tramp-file-mode-from-int (mode)
- "Turn an integer representing a file mode into an ls(1)-like string."
- (let ((type (cdr
- (assoc (logand (lsh mode -12) 15) tramp-file-mode-type-map)))
- (user (logand (lsh mode -6) 7))
- (group (logand (lsh mode -3) 7))
- (other (logand (lsh mode -0) 7))
- (suid (> (logand (lsh mode -9) 4) 0))
- (sgid (> (logand (lsh mode -9) 2) 0))
- (sticky (> (logand (lsh mode -9) 1) 0)))
- (setq user (tramp-file-mode-permissions user suid "s"))
- (setq group (tramp-file-mode-permissions group sgid "s"))
- (setq other (tramp-file-mode-permissions other sticky "t"))
- (concat type user group other)))
-
-(defun tramp-file-mode-permissions (perm suid suid-text)
- "Convert a permission bitset into a string.
-This is used internally by `tramp-file-mode-from-int'."
- (let ((r (> (logand perm 4) 0))
- (w (> (logand perm 2) 0))
- (x (> (logand perm 1) 0)))
- (concat (or (and r "r") "-")
- (or (and w "w") "-")
- (or (and suid x suid-text) ; suid, execute
- (and suid (upcase suid-text)) ; suid, !execute
- (and x "x") "-")))) ; !suid
-
(defun tramp-shell-case-fold (string)
"Converts STRING to shell glob pattern which ignores case."
(mapconcat
(tramp-message vec 5 "Finding a suitable `trash' command")
(tramp-find-executable vec "trash" (tramp-get-remote-path vec))))
+(defun tramp-get-remote-gvfs-monitor-dir (vec)
+ (with-tramp-connection-property vec "gvfs-monitor-dir"
+ (tramp-message vec 5 "Finding a suitable `gvfs-monitor-dir' command")
+ (tramp-find-executable
+ vec "gvfs-monitor-dir" (tramp-get-remote-path vec) t t)))
+
+(defun tramp-get-remote-inotifywait (vec)
+ (with-tramp-connection-property vec "inotifywait"
+ (tramp-message vec 5 "Finding a suitable `inotifywait' command")
+ (tramp-find-executable vec "inotifywait" (tramp-get-remote-path vec) t t)))
+
(defun tramp-get-remote-id (vec)
(with-tramp-connection-property vec "id"
(tramp-message vec 5 "Finding POSIX `id' command")
;; The command might not always return a number.
(if (and (equal id-format 'integer) (not (integerp res))) -1 res))))
-(defun tramp-get-local-uid (id-format)
- (if (equal id-format 'integer) (user-uid) (user-login-name)))
-
-(defun tramp-get-local-gid (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)
"Return the compress command related to PROP.
;; Windows shells need the program file name after
;; the pipe symbol be quoted if they use forward
;; slashes as directory separators.
- (if (and (string-match "local" prop)
- (memq system-type '(windows-nt)))
- "(%s | \"%s\" >%%s)"
- "(%s | %s >%%s)")
+ (cond
+ ((and (string-match "local" prop)
+ (memq system-type '(windows-nt)))
+ "(%s | \"%s\")")
+ ((string-match "local" prop) "(%s | %s)")
+ (t "(%s | %s >%%s)"))
coding compress))
(compress
(format
"(%s <%%s | %s)")
compress coding))
((string-match "decoding" prop)
- (format "%s >%%s" coding))
+ (cond
+ ((string-match "local" prop) (format "%s" coding))
+ (t (format "%s >%%s" coding))))
(t
(format "%s <%%s" coding)))))))