]> code.delx.au - gnu-emacs/blobdiff - lisp/net/tramp.el
Merge from origin/emacs-25
[gnu-emacs] / lisp / net / tramp.el
index 953525f37e4e10512ea302ef96a725538b3633af..3da60e93b784766241055b323d1690e403e1d1a8 100644 (file)
@@ -1,6 +1,6 @@
 ;;; tramp.el --- Transparent Remote Access, Multiple Protocol
 
-;; Copyright (C) 1998-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2016 Free Software Foundation, Inc.
 
 ;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
 ;;         Michael Albinus <michael.albinus@gmx.de>
@@ -34,9 +34,7 @@
 ;; Notes:
 ;; -----
 ;;
-;; This package only works for Emacs 22.1 and higher, and for XEmacs 21.4
-;; and higher.  For XEmacs 21, you need the package `fsf-compat' for
-;; the `with-timeout' macro.
+;; This package only works for Emacs 23.1 and higher.
 ;;
 ;; Also see the todo list at the bottom of this file.
 ;;
 ;; Pacify byte-compiler.
 (eval-when-compile
   (require 'cl))
-(defvar bkup-backup-directory-info)
-(defvar directory-sep-char)
 (defvar eshell-path-env)
-(defvar ls-lisp-use-insert-directory-program)
-(defvar outline-regexp)
 
 ;;; User Customizable Internal Variables:
 
@@ -102,58 +96,32 @@ Any level x includes messages for all levels 1 .. x-1.  The levels are
   :group 'tramp
   :type 'integer)
 
-;; Emacs case.
-(eval-and-compile
-  (when (boundp 'backup-directory-alist)
-    (defcustom tramp-backup-directory-alist nil
-      "Alist of filename patterns and backup directory names.
+(defcustom tramp-backup-directory-alist nil
+  "Alist of filename patterns and backup directory names.
 Each element looks like (REGEXP . DIRECTORY), with the same meaning like
 in `backup-directory-alist'.  If a Tramp file is backed up, and DIRECTORY
 is a local file name, the backup directory is prepended with Tramp file
-name prefix \(method, user, host\) of file.
+name prefix \(method, user, host) of file.
 
-\(setq tramp-backup-directory-alist backup-directory-alist\)
+\(setq tramp-backup-directory-alist backup-directory-alist)
 
 gives the same backup policy for Tramp files on their hosts like the
 policy for local files."
-      :group 'tramp
-      :type '(repeat (cons (regexp :tag "Regexp matching filename")
-                          (directory :tag "Backup directory name"))))))
-
-;; XEmacs case.  We cannot check for `bkup-backup-directory-info', because
-;; the package "backup-dir" might not be loaded yet.
-(eval-and-compile
-  (when (featurep 'xemacs)
-    (defcustom tramp-bkup-backup-directory-info nil
-      "Alist of (FILE-REGEXP BACKUP-DIR OPTIONS ...))
-It has the same meaning like `bkup-backup-directory-info' from package
-`backup-dir'.  If a Tramp file is backed up, and BACKUP-DIR is a local
-file name, the backup directory is prepended with Tramp file name prefix
-\(method, user, host\) of file.
-
-\(setq tramp-bkup-backup-directory-info bkup-backup-directory-info\)
-
-gives the same backup policy for Tramp files on their hosts like the
-policy for local files."
-      :type '(repeat
-             (list (regexp :tag "File regexp")
-                   (string :tag "Backup Dir")
-                   (set :inline t
-                        (const ok-create)
-                        (const full-path)
-                        (const prepend-name)
-                        (const search-upward))))
-      :group 'tramp)))
+  :group 'tramp
+  :type '(repeat (cons (regexp :tag "Regexp matching filename")
+                      (directory :tag "Backup directory name"))))
 
 (defcustom tramp-auto-save-directory nil
   "Put auto-save files in this directory, if set.
-The idea is to use a local directory so that auto-saving is faster."
+The idea is to use a local directory so that auto-saving is faster.
+This setting has precedence over `auto-save-file-name-transforms'."
   :group 'tramp
-  :type '(choice (const nil) string))
+  :type '(choice (const :tag "Use default" nil)
+                (directory :tag "Auto save directory name")))
 
 (defcustom tramp-encoding-shell
-  (if (memq system-type '(windows-nt))
-      (getenv "COMSPEC")
+  (if (boundp 'w32-shell-name)
+      (symbol-value 'w32-shell-name)
     "/bin/sh")
   "Use this program for encoding and decoding commands on the local host.
 This shell is used to execute the encoding and decoding command on the
@@ -177,17 +145,14 @@ use for the remote host."
   :group 'tramp
   :type '(file :must-match t))
 
-(defcustom tramp-encoding-command-switch
-  (if (string-match "cmd\\.exe" tramp-encoding-shell)
-      "/c"
-    "-c")
+(defcustom tramp-encoding-command-switch (if (boundp 'w32-shell-name) "/c" "-c")
   "Use this switch together with `tramp-encoding-shell' for local commands.
 See the variable `tramp-encoding-shell' for more information."
   :group 'tramp
   :type 'string)
 
 (defcustom tramp-encoding-command-interactive
-  (unless (string-match "cmd\\.exe" tramp-encoding-shell) "-i")
+  (unless (boundp 'w32-shell-name) "-i")
   "Use this switch together with `tramp-encoding-shell' for interactive shells.
 See the variable `tramp-encoding-shell' for more information."
   :version "24.1"
@@ -208,6 +173,12 @@ pair of the form (KEY VALUE).  The following KEYs are defined:
     for it.  Also note that \"/bin/sh\" exists on all Unixen,
     this might not be true for the value that you decide to use.
     You Have Been Warned.
+  * `tramp-remote-shell-login'
+    This specifies the arguments to let `tramp-remote-shell' run
+    as a login shell.  It defaults to (\"-l\"), but some shells,
+    like ksh, require another argument.  See
+    `tramp-connection-properties' for a way to overwrite the
+    default value.
   * `tramp-remote-shell-args'
     For implementation of `shell-command', this specifies the
     arguments to let `tramp-remote-shell' run a single command.
@@ -300,50 +271,13 @@ are fit for gateways must have `tramp-default-port' at least.
 
 Notes:
 
-When using `su' or `sudo' the phrase `open connection to a remote
-host' sounds strange, but it is used nevertheless, for consistency.
+When using `su' or `sudo' the phrase \"open connection to a remote
+host\" sounds strange, but it is used nevertheless, for consistency.
 No connection is opened to a remote host, but `su' or `sudo' is
 started on the local host.  You should specify a remote host
 `localhost' or the name of the local host.  Another host name is
 useful only in combination with `tramp-default-proxies-alist'.")
 
-;;;###tramp-autoload
-(defconst tramp-ssh-controlmaster-options
-  (let ((result "")
-       (case-fold-search t))
-    (ignore-errors
-      (when (executable-find "ssh")
-       (with-temp-buffer
-         (call-process "ssh" nil t nil "-o" "ControlMaster")
-         (goto-char (point-min))
-         (when (search-forward-regexp "missing.+argument" nil t)
-           (setq result "-o ControlMaster=auto")))
-       (unless (zerop (length result))
-         (with-temp-buffer
-           (call-process
-            "ssh" nil t nil "-o" "ControlPath=%C" "host.does.not.exist")
-           (goto-char (point-min))
-           (if (search-forward-regexp "unknown.+key" nil t)
-               (setq result
-                     (concat result " -o ControlPath='tramp.%%r@%%h:%%p'"))
-             (setq result (concat result " -o ControlPath='tramp.%%C'"))))
-         (with-temp-buffer
-           (call-process "ssh" nil t nil "-o" "ControlPersist")
-           (goto-char (point-min))
-           (when (search-forward-regexp "missing.+argument" nil t)
-             (setq result (concat result " -o ControlPersist=no")))))))
-    result)
-    "Call ssh to detect whether it supports the Control* arguments.
-Return a string to be used in `tramp-methods'.")
-
-;;;###tramp-autoload
-(defcustom tramp-use-ssh-controlmaster-options
-  (not (zerop (length tramp-ssh-controlmaster-options)))
-  "Whether to use `tramp-ssh-controlmaster-options'."
-  :group 'tramp
-  :version "24.4"
-  :type 'boolean)
-
 (defcustom tramp-default-method
   ;; An external copy method seems to be preferred, because it performs
   ;; much better for large files, and it hasn't too serious delays
@@ -358,27 +292,9 @@ Return a string to be used in `tramp-methods'.")
    ;; PuTTY is installed.  We don't take it, if it is installed on a
    ;; non-windows system, or pscp from the pssh (parallel ssh) package
    ;; is found.
-   ((and (eq system-type 'windows-nt)
-        (executable-find "pscp"))
-    (if        (or (fboundp 'password-read)
-           (fboundp 'auth-source-user-or-password)
-           (fboundp 'auth-source-search)
-           ;; Pageant is running.
-           (tramp-compat-process-running-p "Pageant"))
-       "pscp"
-      "plink"))
+   ((and (eq system-type 'windows-nt) (executable-find "pscp")) "pscp")
    ;; There is an ssh installation.
-   ((executable-find "scp")
-    (if        (or (fboundp 'password-read)
-           (fboundp 'auth-source-user-or-password)
-           (fboundp 'auth-source-search)
-           ;; ssh-agent is running.
-           (getenv "SSH_AUTH_SOCK")
-           (getenv "SSH_AGENT_PID")
-           ;; We could reuse the connection.
-           (> (length tramp-ssh-controlmaster-options) 0))
-       "scp"
-      "ssh"))
+   ((executable-find "scp") "scp")
    ;; Fallback.
    (t "ftp"))
   "Default method to use for transferring files.
@@ -495,15 +411,15 @@ host runs a registered shell, it shall be added to this list, too."
   (concat
    "\\`"
    (regexp-opt
-    (list "localhost" "localhost6" (system-name) "127\.0\.0\.1" "::1") t)
+    (list "localhost" "localhost6" (system-name) "127.0.0.1" "::1") t)
    "\\'")
   "Host names which are regarded as local host.")
 
 (defvar tramp-completion-function-alist nil
   "Alist of methods for remote files.
-This is a list of entries of the form \(NAME PAIR1 PAIR2 ...\).
+This is a list of entries of the form \(NAME PAIR1 PAIR2 ...).
 Each NAME stands for a remote access method.  Each PAIR is of the form
-\(FUNCTION FILE\).  FUNCTION is responsible to extract user names and host
+\(FUNCTION FILE).  FUNCTION is responsible to extract user names and host
 names from FILE for completion.  The following predefined FUNCTIONs exists:
 
  * `tramp-parse-rhosts'      for \"~/.rhosts\" like files,
@@ -513,10 +429,11 @@ names from FILE for completion.  The following predefined FUNCTIONs exists:
  * `tramp-parse-sknownhosts' for \"~/.ssh2/knownhosts/*\" like files,
  * `tramp-parse-hosts'       for \"/etc/hosts\" like files,
  * `tramp-parse-passwd'      for \"/etc/passwd\" like files.
+ * `tramp-parse-etc-group'   for \"/etc/group\" like files.
  * `tramp-parse-netrc'       for \"~/.netrc\" like files.
  * `tramp-parse-putty'       for PuTTY registered sessions.
 
-FUNCTION can also be a customer defined function.  For more details see
+FUNCTION can also be a user defined function.  For more details see
 the info pages.")
 
 (defconst tramp-echo-mark-marker "_echo"
@@ -572,7 +489,7 @@ Sometimes the prompt is reported to look like \"login as:\"."
   ;; regexp works only for GNU Emacs.
   ;; Allow also [] style prompts.  They can appear only during
   ;; connection initialization; Tramp redefines the prompt afterwards.
-  (concat (if (featurep 'xemacs) "" "\\(?:^\\|\r\\)")
+  (concat "\\(?:^\\|\r\\)"
          "[^]#$%>\n]*#?[]#$%>] *\\(\e\\[[0-9;]*[a-zA-Z] *\\)*")
   "Regexp to match prompts from remote shell.
 Normally, Tramp expects you to configure `shell-prompt-pattern'
@@ -590,6 +507,7 @@ This regexp must match both `tramp-initial-end-of-output' and
 
 (defcustom tramp-password-prompt-regexp
   (format "^.*\\(%s\\).*:\^@? *"
+         ;; `password-word-equivalents' has been introduced with Emacs 24.4.
          (if (boundp 'password-word-equivalents)
              (regexp-opt (symbol-value 'password-word-equivalents))
            "password\\|passphrase"))
@@ -708,28 +626,17 @@ Useful for \"rsync\" like methods.")
 (make-variable-buffer-local 'tramp-temp-buffer-file-name)
 (put 'tramp-temp-buffer-file-name 'permanent-local t)
 
-;; XEmacs is distributed with few Lisp packages.  Further packages are
-;; installed using EFS.  If we use a unified filename format, then
-;; Tramp is required in addition to EFS.  (But why can't Tramp just
-;; disable EFS when Tramp is loaded?  Then XEmacs can ship with EFS
-;; just like before.)  Another reason for using a separate filename
-;; syntax on XEmacs is that EFS hooks into XEmacs in many places, but
-;; Tramp only knows how to deal with `file-name-handler-alist', not
-;; the other places.
-
-;; Currently, we have the choice between 'ftp and 'sep.
 ;;;###autoload
-(defcustom tramp-syntax
-  (if (featurep 'xemacs) 'sep 'ftp)
+(defcustom tramp-syntax 'ftp
   "Tramp filename syntax to be used.
 
 It can have the following values:
 
-  'ftp -- Ange-FTP respective EFS like syntax (GNU Emacs default)
-  'sep -- Syntax as defined for XEmacs."
+  `ftp' -- Ange-FTP like syntax
+  `sep' -- Syntax as defined for XEmacs originally."
   :group 'tramp
   :version "24.4"
-  :type `(choice (const :tag  ,(if (featurep 'xemacs) "EFS" "Ange-FTP") ftp)
+  :type '(choice (const :tag "Ange-FTP" ftp)
                 (const :tag "XEmacs" sep)))
 
 (defconst tramp-prefix-format
@@ -914,15 +821,13 @@ See also `tramp-file-name-regexp'.")
       "\\`/\\(\\[.*\\]\\|[^/|:]\\{2,\\}[^/|]*\\):"
     "\\`/[^/|:][^/|]*:")
   "Value for `tramp-file-name-regexp' for unified remoting.
-Emacs (not XEmacs) uses a unified filename syntax for Ange-FTP and
-Tramp.  See `tramp-file-name-structure' for more explanations.
+See `tramp-file-name-structure' for more explanations.
 
 On W32 systems, the volume letter must be ignored.")
 
 ;;;###autoload
 (defconst tramp-file-name-regexp-separate "\\`/\\[.*\\]"
   "Value for `tramp-file-name-regexp' for separate remoting.
-XEmacs uses a separate filename syntax for Tramp and EFS.
 See `tramp-file-name-structure' for more explanations.")
 
 ;;;###autoload
@@ -939,7 +844,7 @@ and is a bit too general, then some files might be considered Tramp
 files which are not really Tramp files.
 
 Please note that the entry in `file-name-handler-alist' is made when
-this file \(tramp.el\) is loaded.  This means that this variable must be set
+this file \(tramp.el) is loaded.  This means that this variable must be set
 before loading tramp.el.  Alternatively, `file-name-handler-alist' can be
 updated after changing this variable.
 
@@ -950,7 +855,6 @@ Also see `tramp-file-name-structure'.")
   (if (memq system-type '(cygwin windows-nt))
       "\\`/[^/]\\{2,\\}\\'" "\\`/[^/]*\\'")
   "Value for `tramp-completion-file-name-regexp' for unified remoting.
-GNU Emacs uses a unified filename syntax for Tramp and Ange-FTP.
 See `tramp-file-name-structure' for more explanations.
 
 On W32 systems, the volume letter must be ignored.")
@@ -959,7 +863,6 @@ On W32 systems, the volume letter must be ignored.")
 (defconst tramp-completion-file-name-regexp-separate
   "\\`/\\([[][^]]*\\)?\\'"
   "Value for `tramp-completion-file-name-regexp' for separate remoting.
-XEmacs uses a separate filename syntax for Tramp and EFS.
 See `tramp-file-name-structure' for more explanations.")
 
 ;;;###autoload
@@ -971,7 +874,7 @@ See `tramp-file-name-structure' for more explanations.")
 This regexp should match partial Tramp file names only.
 
 Please note that the entry in `file-name-handler-alist' is made when
-this file \(tramp.el\) is loaded.  This means that this variable must be set
+this file \(tramp.el) is loaded.  This means that this variable must be set
 before loading tramp.el.  Alternatively, `file-name-handler-alist' can be
 updated after changing this variable.
 
@@ -982,10 +885,7 @@ Also see `tramp-file-name-structure'.")
 ;; to drop bytes when data is sent too quickly.  There is also a connection
 ;; buffer local variable, which is computed depending on remote host properties
 ;; when `tramp-chunksize' is zero or nil.
-(defcustom tramp-chunksize
-  (when (and (not (featurep 'xemacs))
-            (memq system-type '(hpux)))
-    500)
+(defcustom tramp-chunksize (when (memq system-type '(hpux)) 500)
 ;; Parentheses in docstring starting at beginning of line are escaped.
 ;; Fontification is messed up when
 ;; `open-paren-in-column-0-is-defun-start' set to t.
@@ -1003,14 +903,14 @@ checked via the following code:
         (erase-buffer)
         (let ((proc (start-process (buffer-name) (current-buffer)
                                    \"ssh\" \"-l\" user host \"wc\" \"-c\")))
-          (when (memq (process-status proc) '(run open))
+          (when (memq (process-status proc) \\='(run open))
             (process-send-string proc (make-string sent ?\\ ))
             (process-send-eof proc)
             (process-send-eof proc))
           (while (not (progn (goto-char (point-min))
                              (re-search-forward \"\\\\w+\" (point-max) t)))
             (accept-process-output proc 1))
-          (when (memq (process-status proc) '(run open))
+          (when (memq (process-status proc) \\='(run open))
             (setq received (string-to-number (match-string 0)))
             (delete-process proc)
             (message \"Bytes sent: %s\\tBytes received: %s\" sent received)
@@ -1024,18 +924,18 @@ checked via the following code:
 
 In the Emacs normally running Tramp, evaluate the above code
 \(replace \"xxx\" and \"yyy\" by the remote user and host name,
-respectively\).  You can do this, for example, by pasting it into
+respectively).  You can do this, for example, by pasting it into
 the `*scratch*' buffer and then hitting C-j with the cursor after the
 last closing parenthesis.  Note that it works only if you have configured
-\"ssh\" to run without password query, see ssh-agent\(1\).
+\"ssh\" to run without password query, see ssh-agent(1).
 
 You will see the number of bytes sent successfully to the remote host.
 If that number exceeds 1000, you can stop the execution by hitting
 C-g, because your Emacs is likely clean.
 
 When it is necessary to set `tramp-chunksize', you might consider to
-use an out-of-the-band method \(like \"scp\"\) instead of an internal one
-\(like \"ssh\"\), because setting `tramp-chunksize' to non-nil decreases
+use an out-of-the-band method \(like \"scp\") instead of an internal one
+\(like \"ssh\"), because setting `tramp-chunksize' to non-nil decreases
 performance.
 
 If your Emacs is buggy, the code stops and gives you an indication
@@ -1073,7 +973,7 @@ The timeout does not include the time reading a password."
 This is necessary as self defense mechanism, in order to avoid
 yo-yo connection attempts when the remote host is unavailable.
 
-A value of 0 or `nil' suppresses this check.  This might be
+A value of 0 or nil suppresses this check.  This might be
 necessary, when several out-of-order copy operations are
 performed, or when several asynchronous processes will be started
 in a short time frame.  In those cases it is recommended to
@@ -1088,8 +988,8 @@ A remote directory might have changed its contents.  In order to
 make it visible during file name completion in the minibuffer,
 Tramp flushes its cache and rereads the directory contents when
 more than `tramp-completion-reread-directory-timeout' seconds
-have been gone since last remote command execution.  A value of `t'
-would require an immediate reread during filename completion, `nil'
+have been gone since last remote command execution.  A value of t
+would require an immediate reread during filename completion, nil
 means to use always cached values for the directory contents."
   :group 'tramp
   :type '(choice (const nil) (const t) integer))
@@ -1136,11 +1036,20 @@ calling HANDLER.")
 ;; internal data structure.  Convenience functions for internal
 ;; data structure.
 
-(defun tramp-get-method-parameter (method param)
+(defun tramp-get-method-parameter (vec param)
   "Return the method parameter PARAM.
-If the `tramp-methods' entry does not exist, return nil."
-  (let ((entry (assoc param (assoc method tramp-methods))))
-    (when entry (cadr entry))))
+If VEC is a vector, check first in connection properties.
+Afterwards, check in `tramp-methods'.  If the `tramp-methods'
+entry does not exist, return nil."
+  (let ((hash-entry
+        (replace-regexp-in-string "^tramp-" "" (symbol-name param))))
+    (if (tramp-connection-property-p vec hash-entry)
+       ;; We use the cached property.
+       (tramp-get-connection-property vec hash-entry nil)
+      ;; Use the static value from `tramp-methods'.
+      (let ((methods-entry
+            (assoc param (assoc (tramp-file-name-method vec) tramp-methods))))
+       (when methods-entry (cadr methods-entry))))))
 
 (defun tramp-file-name-p (vec)
   "Check, whether VEC is a Tramp object."
@@ -1204,7 +1113,7 @@ If the `tramp-methods' entry does not exist, return nil."
       (or (and (stringp host)
               (string-match tramp-host-with-port-regexp host)
               (string-to-number (match-string 2 host)))
-         (tramp-get-method-parameter method 'tramp-default-port)))))
+         (tramp-get-method-parameter vec 'tramp-default-port)))))
 
 ;;;###tramp-autoload
 (defun tramp-tramp-file-p (name)
@@ -1251,11 +1160,10 @@ their replacement."
       ;; This works with the current set of `tramp-obsolete-methods'.
       ;; Must be improved, if their are more sophisticated replacements.
       (setq result (substring result 0 -1)))
-    ;; We must mark, whether a default value has been used.  Not
-    ;; applicable for XEmacs.
-    (if (or method (null result) (null (functionp 'propertize)))
+    ;; We must mark, whether a default value has been used.
+    (if (or method (null result))
        result
-      (tramp-compat-funcall 'propertize result 'tramp-default t))))
+      (propertize result 'tramp-default t))))
 
 (defun tramp-find-user (method user host)
   "Return the right user string to use.
@@ -1273,11 +1181,10 @@ This is USER, if non-nil. Otherwise, do a lookup in
                   (setq choices nil)))
               luser)
             tramp-default-user)))
-    ;; We must mark, whether a default value has been used.  Not
-    ;; applicable for XEmacs.
-    (if (or user (null result) (null (functionp 'propertize)))
+    ;; We must mark, whether a default value has been used.
+    (if (or user (null result))
        result
-      (tramp-compat-funcall 'propertize result 'tramp-default t))))
+      (propertize result 'tramp-default t))))
 
 (defun tramp-find-host (method user host)
   "Return the right host string to use.
@@ -1312,8 +1219,8 @@ This is HOST, if non-nil. Otherwise, it is `tramp-default-host'."
 
 (defun tramp-dissect-file-name (name &optional nodefault)
   "Return a `tramp-file-name' structure.
-The structure consists of remote method, remote user, remote host
-and localname (file name on remote host).  If NODEFAULT is
+The structure consists of remote method, remote user, remote host,
+localname (file name on remote host) and hop.  If NODEFAULT is
 non-nil, the file name parts are not expanded to their default
 values."
   (save-match-data
@@ -1468,9 +1375,13 @@ ARGUMENTS to actually emit the message (if applicable)."
     (when (bobp)
       (insert
        (format
-       ";; %sEmacs: %s Tramp: %s -*- mode: outline; -*-"
-       (if (featurep 'sxemacs) "SX" (if (featurep 'xemacs) "X" "GNU "))
-       emacs-version tramp-version)))
+       ";; Emacs: %s Tramp: %s -*- mode: outline; -*-"
+       emacs-version tramp-version))
+      (when (>= tramp-verbose 10)
+       (insert
+        (format
+         "\n;; Location: %s Git: %s"
+         (locate-library "tramp") (tramp-repository-get-version)))))
     (unless (bolp)
       (insert "\n"))
     ;; Timestamp.
@@ -1497,7 +1408,6 @@ ARGUMENTS to actually emit the message (if applicable)."
                     '("tramp-backtrace"
                       "tramp-compat-condition-case-unless-debug"
                       "tramp-compat-funcall"
-                      "tramp-compat-with-temp-message"
                       "tramp-condition-case-unless-debug"
                       "tramp-debug-message"
                       "tramp-error"
@@ -1520,7 +1430,7 @@ ARGUMENTS to actually emit the message (if applicable)."
 ;          (1+ (count-lines (point-min) (cdr ffn)))))))
       (insert (format "%s " fn)))
     ;; The message.
-    (insert (apply 'format fmt-string arguments))))
+    (insert (apply #'format-message fmt-string arguments))))
 
 (defvar tramp-message-show-message t
   "Show Tramp message in the minibuffer.
@@ -1562,6 +1472,12 @@ applicable)."
            (let ((tramp-verbose 0))
              (setq vec-or-proc
                    (tramp-get-connection-property vec-or-proc "vector" nil))))
+         ;; Append connection buffer for error messages.
+         (when (= level 1)
+           (let ((tramp-verbose 0))
+             (with-current-buffer (tramp-get-connection-buffer vec-or-proc)
+               (setq fmt-string (concat fmt-string "\n%s")
+                     arguments (append arguments (list (buffer-string)))))))
          ;; Do it.
          (when (vectorp vec-or-proc)
            (apply 'tramp-debug-message
@@ -1591,8 +1507,8 @@ signal identifier to be raised, remaining arguments passed to
        (error-message-string
        (list signal
              (get signal 'error-message)
-             (apply 'format fmt-string arguments)))))
-    (signal signal (list (apply 'format fmt-string arguments)))))
+             (apply #'format-message fmt-string arguments)))))
+    (signal signal (list (apply #'format-message fmt-string arguments)))))
 
 (defsubst tramp-error-with-buffer
   (buf vec-or-proc signal fmt-string &rest arguments)
@@ -1661,14 +1577,13 @@ If VAR is nil, then we bind `v' to the structure and `method', `user',
 
 (put 'with-parsed-tramp-file-name 'lisp-indent-function 2)
 (put 'with-parsed-tramp-file-name 'edebug-form-spec '(form symbolp body))
-(tramp-compat-font-lock-add-keywords
- 'emacs-lisp-mode '("\\<with-parsed-tramp-file-name\\>"))
+(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-parsed-tramp-file-name\\>"))
 
 (defun tramp-progress-reporter-update (reporter &optional value)
   (let* ((parameters (cdr reporter))
         (message (aref parameters 3)))
     (when (string-match message (or (current-message) ""))
-      (tramp-compat-funcall 'progress-reporter-update reporter value))))
+      (progress-reporter-update reporter value))))
 
 (defmacro with-tramp-progress-reporter (vec level message &rest body)
   "Executes BODY, spinning a progress reporter with MESSAGE.
@@ -1685,19 +1600,18 @@ without a visible progress reporter."
                        ;; Display only when there is a minimum level.
                        (<= ,level (min tramp-verbose 3)))
               (ignore-errors
-                (let ((pr (tramp-compat-funcall
-                           #'make-progress-reporter ,message)))
+                (let ((pr (make-progress-reporter ,message nil nil)))
                   (when pr
-                    (run-at-time 3 0.1
-                                 #'tramp-progress-reporter-update pr)))))))
+                    (run-at-time
+                    3 0.1 #'tramp-progress-reporter-update pr)))))))
        (unwind-protect
            ;; Execute the body.
            (prog1 (progn ,@body) (setq cookie "done"))
          ;; Stop progress reporter.
-         (if tm (tramp-compat-funcall 'cancel-timer tm))
+         (if tm (cancel-timer tm))
          (tramp-message ,vec ,level "%s...%s" ,message cookie)))))
 
-(tramp-compat-font-lock-add-keywords
+(font-lock-add-keywords
  'emacs-lisp-mode '("\\<with-tramp-progress-reporter\\>"))
 
 (defmacro with-tramp-file-property (vec file property &rest body)
@@ -1716,8 +1630,7 @@ FILE must be a local file name on a connection identified via VEC."
 
 (put 'with-tramp-file-property 'lisp-indent-function 3)
 (put 'with-tramp-file-property 'edebug-form-spec t)
-(tramp-compat-font-lock-add-keywords
- 'emacs-lisp-mode '("\\<with-tramp-file-property\\>"))
+(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-tramp-file-property\\>"))
 
 (defmacro with-tramp-connection-property (key property &rest body)
   "Check in Tramp for property PROPERTY, otherwise executes BODY and set."
@@ -1732,7 +1645,7 @@ FILE must be a local file name on a connection identified via VEC."
 
 (put 'with-tramp-connection-property 'lisp-indent-function 2)
 (put 'with-tramp-connection-property 'edebug-form-spec t)
-(tramp-compat-font-lock-add-keywords
+(font-lock-add-keywords
  'emacs-lisp-mode '("\\<with-tramp-connection-property\\>"))
 
 (defun tramp-drop-volume-letter (name)
@@ -1760,7 +1673,7 @@ Example:
 
     (tramp-set-completion-function
      \"ssh\"
-     '((tramp-parse-sconfig \"/etc/ssh_config\")
+     \\='((tramp-parse-sconfig \"/etc/ssh_config\")
        (tramp-parse-sconfig \"~/.ssh/config\")))"
 
   (let ((r function-list)
@@ -1775,14 +1688,18 @@ Example:
        (setcdr v (delete (car v) (cdr v))))
       ;; Check for function and file or registry key.
       (unless (and (functionp (nth 0 (car v)))
-                  (if (string-match "^HKEY_CURRENT_USER" (nth 1 (car v)))
-                      ;; Windows registry.
-                      (and (memq system-type '(cygwin windows-nt))
-                           (zerop
-                            (tramp-call-process
-                             v "reg" nil nil nil "query" (nth 1 (car v)))))
-                    ;; Configuration file.
-                    (file-exists-p (nth 1 (car v)))))
+                  (cond
+                   ;; Windows registry.
+                   ((string-match "^HKEY_CURRENT_USER" (nth 1 (car v)))
+                    (and (memq system-type '(cygwin windows-nt))
+                         (zerop
+                          (tramp-call-process
+                           v "reg" nil nil nil "query" (nth 1 (car v))))))
+                   ;; Zeroconf service type.
+                   ((string-match
+                     "^_[[:alpha:]]+\\._[[:alpha:]]+$" (nth 1 (car v))))
+                   ;; Configuration file.
+                   (t (file-exists-p (nth 1 (car v))))))
        (setq r (delete (car v) r)))
       (setq v (cdr v)))
 
@@ -1812,28 +1729,22 @@ Adds another overlay hiding filename parts according to Tramp's
 special handling of `substitute-in-file-name'."
   (when (symbol-value 'minibuffer-completing-file-name)
     (setq tramp-rfn-eshadow-overlay
-         (tramp-compat-funcall
-          'make-overlay
-          (tramp-compat-funcall 'minibuffer-prompt-end)
-          (tramp-compat-funcall 'minibuffer-prompt-end)))
+         (make-overlay (minibuffer-prompt-end) (minibuffer-prompt-end)))
     ;; Copy rfn-eshadow-overlay properties.
-    (let ((props (tramp-compat-funcall
-                 'overlay-properties (symbol-value 'rfn-eshadow-overlay))))
+    (let ((props (overlay-properties (symbol-value 'rfn-eshadow-overlay))))
       (while props
        ;; The `field' property prevents correct minibuffer
        ;; completion; we exclude it.
        (if (not (eq (car props) 'field))
-           (tramp-compat-funcall
-            'overlay-put tramp-rfn-eshadow-overlay (pop props) (pop props))
+            (overlay-put tramp-rfn-eshadow-overlay (pop props) (pop props))
          (pop props) (pop props))))))
 
-(when (boundp 'rfn-eshadow-setup-minibuffer-hook)
-  (add-hook 'rfn-eshadow-setup-minibuffer-hook
-           'tramp-rfn-eshadow-setup-minibuffer)
-  (add-hook 'tramp-unload-hook
-           (lambda ()
-             (remove-hook 'rfn-eshadow-setup-minibuffer-hook
-                          'tramp-rfn-eshadow-setup-minibuffer))))
+(add-hook 'rfn-eshadow-setup-minibuffer-hook
+         'tramp-rfn-eshadow-setup-minibuffer)
+(add-hook 'tramp-unload-hook
+         (lambda ()
+           (remove-hook 'rfn-eshadow-setup-minibuffer-hook
+                        'tramp-rfn-eshadow-setup-minibuffer)))
 
 (defconst tramp-rfn-eshadow-update-overlay-regexp
   (format "[^%s/~]*\\(/\\|~\\)" tramp-postfix-host-format))
@@ -1845,15 +1756,13 @@ This is intended to be used as a minibuffer `post-command-hook' for
 been set up by `rfn-eshadow-setup-minibuffer'."
   ;; In remote files name, there is a shadowing just for the local part.
   (ignore-errors
-    (let ((end (or (tramp-compat-funcall
-                   'overlay-end (symbol-value 'rfn-eshadow-overlay))
-                  (tramp-compat-funcall 'minibuffer-prompt-end)))
+    (let ((end (or (overlay-end (symbol-value 'rfn-eshadow-overlay))
+                  (minibuffer-prompt-end)))
          ;; We do not want to send any remote command.
          (non-essential t))
       (when
          (tramp-tramp-file-p
-          (tramp-compat-funcall
-           'buffer-substring-no-properties end (point-max)))
+          (buffer-substring-no-properties end (point-max)))
        (save-excursion
          (save-restriction
            (narrow-to-region
@@ -1865,17 +1774,15 @@ been set up by `rfn-eshadow-setup-minibuffer'."
            (let ((rfn-eshadow-overlay tramp-rfn-eshadow-overlay)
                  (rfn-eshadow-update-overlay-hook nil)
                  file-name-handler-alist)
-             (tramp-compat-funcall
-              'move-overlay rfn-eshadow-overlay (point-max) (point-max))
-             (tramp-compat-funcall 'rfn-eshadow-update-overlay))))))))
-
-(when (boundp 'rfn-eshadow-update-overlay-hook)
-  (add-hook 'rfn-eshadow-update-overlay-hook
-           'tramp-rfn-eshadow-update-overlay)
-  (add-hook 'tramp-unload-hook
-           (lambda ()
-             (remove-hook 'rfn-eshadow-update-overlay-hook
-                          'tramp-rfn-eshadow-update-overlay))))
+             (move-overlay rfn-eshadow-overlay (point-max) (point-max))
+             (rfn-eshadow-update-overlay))))))))
+
+(add-hook 'rfn-eshadow-update-overlay-hook
+         'tramp-rfn-eshadow-update-overlay)
+(add-hook 'tramp-unload-hook
+         (lambda ()
+           (remove-hook 'rfn-eshadow-update-overlay-hook
+                        'tramp-rfn-eshadow-update-overlay)))
 
 ;; Inodes don't exist for some file systems.  Therefore we must
 ;; generate virtual ones.  Used in `find-buffer-visiting'.  The method
@@ -1898,12 +1805,13 @@ been set up by `rfn-eshadow-setup-minibuffer'."
 If the file modes of FILENAME cannot be determined, return the
 value of `default-file-modes', without execute permissions."
   (or (file-modes filename)
-      (logand (default-file-modes) (tramp-compat-octal-to-decimal "0666"))))
+      (logand (default-file-modes) (string-to-number "0666" 8))))
 
 (defun tramp-replace-environment-variables (filename)
  "Replace environment variables in FILENAME.
 Return the string with the replaced variables."
  (or (ignore-errors
+       ;; Optional arg has been introduced with Emacs 24 (?).
        (tramp-compat-funcall 'substitute-env-vars filename 'only-defined))
      ;; We need an own implementation.
      (save-match-data
@@ -1918,35 +1826,6 @@ Return the string with the replaced variables."
                  t nil filename)))
         filename))))
 
-;; In XEmacs, electricity is implemented via a key map for ?/ and ?~,
-;; which calls corresponding functions (see minibuf.el).
-(when (fboundp 'minibuffer-electric-separator)
-  (mapc
-   (lambda (x)
-     (eval
-      `(defadvice ,x
-        (around ,(intern (format "tramp-advice-%s" x)) activate)
-        "Invoke `substitute-in-file-name' for Tramp files."
-        (if (and (symbol-value 'minibuffer-electric-file-name-behavior)
-                 (tramp-tramp-file-p (buffer-substring)))
-            ;; We don't need to handle `last-input-event', because
-            ;; due to the key map we know it must be ?/ or ?~.
-            (let ((s (concat (buffer-substring (point-min) (point))
-                             (string last-command-char))))
-              (delete-region (point-min) (point))
-              (insert (substitute-in-file-name s))
-              (setq ad-return-value last-command-char))
-          ad-do-it)))
-     (eval
-      `(add-hook
-       'tramp-unload-hook
-       (lambda ()
-         (ad-remove-advice ',x 'around ',(intern (format "tramp-advice-%s" x)))
-         (ad-activate ',x)))))
-
-   '(minibuffer-electric-separator
-     minibuffer-electric-tilde)))
-
 (defun tramp-find-file-name-coding-system-alist (filename tmpname)
   "Like `find-operation-coding-system' for Tramp filenames.
 Tramp's `insert-file-contents' and `write-region' work over
@@ -2006,49 +1885,35 @@ ARGS are the arguments OPERATION has been called with."
   (cond
    ;; FILE resp DIRECTORY.
    ((member operation
-           (list 'access-file 'byte-compiler-base-file-name 'delete-directory
-                 'delete-file 'diff-latest-backup-file 'directory-file-name
-                 'directory-files 'directory-files-and-attributes
-                 'dired-compress-file 'dired-uncache
-                 'file-accessible-directory-p 'file-attributes
-                 'file-directory-p 'file-executable-p 'file-exists-p
-                 'file-local-copy 'file-modes
-                 'file-name-as-directory 'file-name-directory
-                 'file-name-nondirectory 'file-name-sans-versions
-                 'file-ownership-preserved-p 'file-readable-p
-                 'file-regular-p 'file-remote-p 'file-symlink-p 'file-truename
-                 'file-writable-p 'find-backup-file-name 'find-file-noselect
-                 'get-file-buffer 'insert-directory 'insert-file-contents
-                 'load 'make-directory 'make-directory-internal
-                 'set-file-modes 'substitute-in-file-name
-                 'unhandled-file-name-directory 'vc-registered
-                 ;; Emacs 22+ only.
-                 'set-file-times
-                 ;; Emacs 24+ only.
-                 'file-acl 'file-notify-add-watch
-                 'file-selinux-context 'set-file-acl 'set-file-selinux-context
-                 ;; XEmacs only.
-                 'abbreviate-file-name 'create-file-buffer
-                 'dired-file-modtime 'dired-make-compressed-filename
-                 'dired-recursive-delete-directory 'dired-set-file-modtime
-                 'dired-shell-unhandle-file-name 'dired-uucode-file
-                 'insert-file-contents-literally 'make-temp-name 'recover-file
-                 'vm-imap-check-mail 'vm-pop-check-mail 'vm-spool-check-mail))
+           '(access-file byte-compiler-base-file-name delete-directory
+             delete-file diff-latest-backup-file directory-file-name
+             directory-files directory-files-and-attributes
+             dired-compress-file dired-uncache
+             file-accessible-directory-p file-attributes
+             file-directory-p file-executable-p file-exists-p
+             file-local-copy file-modes
+             file-name-as-directory file-name-directory
+             file-name-nondirectory file-name-sans-versions
+             file-ownership-preserved-p file-readable-p
+             file-regular-p file-remote-p file-symlink-p file-truename
+             file-writable-p find-backup-file-name find-file-noselect
+             get-file-buffer insert-directory insert-file-contents
+             load make-directory make-directory-internal
+             set-file-modes set-file-times substitute-in-file-name
+             unhandled-file-name-directory vc-registered
+             ;; Emacs 24+ only.
+             file-acl file-notify-add-watch file-selinux-context
+             set-file-acl set-file-selinux-context))
     (if (file-name-absolute-p (nth 0 args))
        (nth 0 args)
       (expand-file-name (nth 0 args))))
    ;; FILE DIRECTORY resp FILE1 FILE2.
    ((member operation
-           (list 'add-name-to-file 'copy-file 'expand-file-name
-                 'file-name-all-completions 'file-name-completion
-                 'file-newer-than-file-p 'make-symbolic-link 'rename-file
-                 ;; Emacs 23+ only.
-                 'copy-directory
-                 ;; Emacs 24+ only.
-                 'file-equal-p 'file-in-directory-p
-                 ;; XEmacs only.
-                 'dired-make-relative-symlink
-                 'vm-imap-move-mail 'vm-pop-move-mail 'vm-spool-move-mail))
+           '(add-name-to-file copy-directory copy-file expand-file-name
+             file-name-all-completions file-name-completion
+             file-newer-than-file-p make-symbolic-link rename-file
+             ;; Emacs 24+ only.
+             file-equal-p file-in-directory-p))
     (save-match-data
       (cond
        ((tramp-tramp-file-p (nth 0 args)) (nth 0 args))
@@ -2059,35 +1924,28 @@ ARGS are the arguments OPERATION has been called with."
     (nth 2 args))
    ;; BUFFER.
    ((member operation
-           (list 'set-visited-file-modtime 'verify-visited-file-modtime
-                  ;; Emacs 22+ only.
-                 'make-auto-save-file-name
-                 ;; XEmacs only.
-                 'backup-buffer))
+           '(make-auto-save-file-name
+             set-visited-file-modtime verify-visited-file-modtime))
     (buffer-file-name
      (if (bufferp (nth 0 args)) (nth 0 args) (current-buffer))))
    ;; COMMAND.
    ((member operation
-           (list ;; not in Emacs 23+.
-                 'dired-call-process
-                  ;; Emacs only.
-                 'shell-command
-                  ;; Emacs 22+ only.
-                  'process-file
-                  ;; Emacs 23+ only.
-                  'start-file-process
-                 ;; XEmacs only.
-                 'dired-print-file 'dired-shell-call-process))
+           '(process-file shell-command start-file-process))
     default-directory)
    ;; PROC.
-   ((eq operation 'file-notify-rm-watch)
+   ((member operation
+           '(;; Emacs 24+ only.
+             file-notify-rm-watch
+             ;; Emacs 25+ only.
+             file-notify-valid-p))
     (when (processp (nth 0 args))
       (with-current-buffer (process-buffer (nth 0 args))
        default-directory)))
    ;; Unknown file primitive.
    (t (error "unknown file I/O primitive: %s" operation))))
 
-(defun tramp-find-foreign-file-name-handler (filename)
+(defun tramp-find-foreign-file-name-handler
+    (filename &optional operation completion)
   "Return foreign file name handler if exists."
   (when (tramp-tramp-file-p filename)
     (let ((v (tramp-dissect-file-name filename t))
@@ -2095,11 +1953,17 @@ ARGS are the arguments OPERATION has been called with."
          elt res)
       ;; When we are not fully sure that filename completion is safe,
       ;; we should not return a handler.
-      (when (or (tramp-file-name-method v) (tramp-file-name-user v)
+      (when (or (not completion)
+               (tramp-file-name-method v) (tramp-file-name-user v)
                (and (tramp-file-name-host v)
                     (not (member (tramp-file-name-host v)
                                  (mapcar 'car tramp-methods))))
-               (not (tramp-completion-mode-p)))
+               ;; Some operations are safe by default.
+               (member
+                operation
+                '(file-name-as-directory
+                  file-name-directory
+                  file-name-nondirectory)))
        (while handler
          (setq elt (car handler)
                handler (cdr handler))
@@ -2127,13 +1991,15 @@ Falls back to normal file name handler if no Tramp file name handler exists."
                (tramp-replace-environment-variables
                 (apply 'tramp-file-name-for-operation operation args)))
               (completion (tramp-completion-mode-p))
-              (foreign (tramp-find-foreign-file-name-handler filename)))
+              (foreign
+               (tramp-find-foreign-file-name-handler
+                filename operation completion))
+              result)
          (with-parsed-tramp-file-name filename nil
            ;; Call the backend function.
            (if foreign
                (tramp-condition-case-unless-debug err
-                   (let ((sf (symbol-function foreign))
-                         result)
+                   (let ((sf (symbol-function foreign)))
                      ;; Some packages set the default directory to a
                      ;; remote path, before respective Tramp packages
                      ;; are already loaded.  This results in
@@ -2197,8 +2063,13 @@ Falls back to normal file name handler if no Tramp file name handler exists."
                    ;; Propagate the error.
                    (t (signal (car err) (cdr err))))))
 
-             ;; Nothing to do for us.
-             (tramp-run-real-handler operation args)))))
+             ;; Nothing to do for us.  However, since we are in
+             ;; `tramp-mode', we must suppress the volume letter on
+             ;; MS Windows.
+             (setq result (tramp-run-real-handler operation args))
+             (if (stringp result)
+                 (tramp-drop-volume-letter result)
+               result)))))
 
     ;; When `tramp-mode' is not enabled, we don't do anything.
     (tramp-run-real-handler operation args)))
@@ -2234,10 +2105,7 @@ preventing reentrant calls of Tramp.")
 (progn (defun tramp-completion-file-name-handler (operation &rest args)
   "Invoke Tramp file name completion handler.
 Falls back to normal file name handler if no Tramp file name handler exists."
-  ;; We bind `directory-sep-char' here for XEmacs on Windows, which
-  ;; would otherwise use backslash.
-  (let ((directory-sep-char ?/)
-       (fn (assoc operation tramp-completion-file-name-handler-alist)))
+  (let ((fn (assoc operation tramp-completion-file-name-handler-alist)))
     (if (and
         ;; When `tramp-mode' is not enabled, we don't do anything.
          fn tramp-mode
@@ -2248,8 +2116,7 @@ Falls back to normal file name handler if no Tramp file name handler exists."
          ;; indicated his interest in using a fancier completion system.
          (or (eq tramp-syntax 'sep)
              (featurep 'tramp) ;; If it's loaded, we may as well use it.
-            ;; `partial-completion-mode' does not exist in XEmacs.
-            ;; It is obsoleted with Emacs 24.1.
+            ;; `partial-completion-mode' is obsoleted with Emacs 24.1.
              (and (boundp 'partial-completion-mode)
                  (symbol-value 'partial-completion-mode))
              ;; FIXME: These may have been loaded even if the user never
@@ -2262,9 +2129,8 @@ Falls back to normal file name handler if no Tramp file name handler exists."
 ;;;###autoload
 (progn (defun tramp-autoload-file-name-handler (operation &rest args)
   "Load Tramp file name handler, and perform OPERATION."
-  ;; Avoid recursive loading of tramp.el.  `temporary-file-directory'
-  ;; does not exist in XEmacs, so we must use something else.
-  (let ((default-directory "/"))
+  ;; Avoid recursive loading of tramp.el.
+  (let ((default-directory temporary-file-directory))
     (load "tramp" nil t))
   (apply operation args)))
 
@@ -2367,7 +2233,7 @@ should never be set globally, the intention is to let-bind it.")
 ;; variable. On the other hand, those files shouldn't have partial
 ;; Tramp file name syntax. Maybe another variable should be introduced
 ;; overwriting this check in such cases. Or we change Tramp file name
-;; syntax in order to avoid ambiguities, like in XEmacs ...
+;; syntax in order to avoid ambiguities.
 ;;;###tramp-autoload
 (defun tramp-completion-mode-p ()
   "Check, whether method / user name / host name completion is active."
@@ -2375,7 +2241,6 @@ should never be set globally, the intention is to let-bind it.")
    ;; Signal from outside.  `non-essential' has been introduced in Emacs 24.
    (and (boundp 'non-essential) (symbol-value 'non-essential))
    tramp-completion-mode
-   ;; Emacs.
    (equal last-input-event 'tab)
    (and (natnump last-input-event)
        (or
@@ -2383,24 +2248,7 @@ should never be set globally, the intention is to let-bind it.")
         (equal last-input-event ?\t)
         (and (not (event-modifiers last-input-event))
              (or (equal last-input-event ?\?)
-                 (equal last-input-event ?\ )))))
-   ;; XEmacs.
-   (and (featurep 'xemacs)
-       ;; `last-input-event' might be nil.
-       (not (null last-input-event))
-       ;; `last-input-event' may have no character approximation.
-       (tramp-compat-funcall 'event-to-character last-input-event)
-       (or
-        ;; ?\t has event-modifier 'control.
-        (equal
-         (tramp-compat-funcall 'event-to-character last-input-event) ?\t)
-        (and (not (event-modifiers last-input-event))
-             (or (equal
-                  (tramp-compat-funcall 'event-to-character last-input-event)
-                  ?\?)
-                 (equal
-                  (tramp-compat-funcall 'event-to-character last-input-event)
-                  ?\ )))))))
+                 (equal last-input-event ?\ )))))))
 
 (defun tramp-connectable-p (filename)
   "Check, whether it is possible to connect the remote host w/o side-effects.
@@ -2787,17 +2635,18 @@ User is always nil."
    (tramp-parse-group
     (concat "^\\(" tramp-ipv6-regexp "\\|" tramp-host-regexp "\\)") 1 " \t"))
 
-;; For su-alike methods it would be desirable to return "root@localhost"
-;; as default.  Unfortunately, we have no information whether any user name
-;; has been typed already.  So we use `tramp-current-user' as indication,
-;; assuming it is set in `tramp-completion-handle-file-name-all-completions'.
 ;;;###tramp-autoload
 (defun tramp-parse-passwd (filename)
   "Return a list of (user host) tuples allowed to access.
 Host is always \"localhost\"."
-  (if (zerop (length tramp-current-user))
-      '(("root" nil))
-    (tramp-parse-file filename 'tramp-parse-passwd-group)))
+  (with-tramp-connection-property nil "parse-passwd"
+    (if (executable-find "getent")
+       (with-temp-buffer
+         (when (zerop (tramp-call-process nil "getent" nil t nil "passwd"))
+           (goto-char (point-min))
+           (loop while (not (eobp)) collect
+                 (tramp-parse-etc-group-group))))
+      (tramp-parse-file filename 'tramp-parse-passwd-group))))
 
 (defun tramp-parse-passwd-group ()
    "Return a (user host) tuple allowed to access.
@@ -2809,6 +2658,29 @@ Host is always \"localhost\"."
      (forward-line 1)
      result))
 
+;;;###tramp-autoload
+(defun tramp-parse-etc-group (filename)
+  "Return a list of (group host) tuples allowed to access.
+Host is always \"localhost\"."
+  (with-tramp-connection-property nil "parse-group"
+    (if (executable-find "getent")
+       (with-temp-buffer
+         (when (zerop (tramp-call-process nil "getent" nil t nil "group"))
+           (goto-char (point-min))
+           (loop while (not (eobp)) collect
+                 (tramp-parse-etc-group-group))))
+      (tramp-parse-file filename 'tramp-parse-etc-group-group))))
+
+(defun tramp-parse-etc-group-group ()
+   "Return a (group host) tuple allowed to access.
+Host is always \"localhost\"."
+   (let ((result)
+        (split (split-string (buffer-substring (point) (point-at-eol)) ":")))
+     (when (member (user-login-name) (split-string (nth 3 split) "," 'omit))
+       (setq result (list (nth 0 split) "localhost")))
+     (forward-line 1)
+     result))
+
 ;;;###tramp-autoload
 (defun tramp-parse-netrc (filename)
   "Return a list of (user host) tuples allowed to access.
@@ -2833,12 +2705,13 @@ User may be nil."
   "Return a list of (user host) tuples allowed to access.
 User is always nil."
   (if (memq system-type '(windows-nt))
-      (with-temp-buffer
-       (when (zerop (tramp-call-process
-                     nil "reg" nil t nil "query" registry-or-dirname))
-         (goto-char (point-min))
-         (loop while (not (eobp)) collect
-               (tramp-parse-putty-group registry-or-dirname))))
+      (with-tramp-connection-property nil "parse-putty"
+       (with-temp-buffer
+         (when (zerop (tramp-call-process
+                       nil "reg" nil t nil "query" registry-or-dirname))
+           (goto-char (point-min))
+           (loop while (not (eobp)) collect
+                 (tramp-parse-putty-group registry-or-dirname)))))
     ;; UNIX case.
     (tramp-parse-shostkeys-sknownhosts
      registry-or-dirname (concat "^\\(" tramp-host-regexp "\\)$"))))
@@ -2874,10 +2747,8 @@ User is always nil."
        (substring directory 0 -1)
       directory)))
 
-(defun tramp-handle-directory-files
-  (directory &optional full match nosort files-only)
+(defun tramp-handle-directory-files (directory &optional full match nosort)
   "Like `directory-files' for Tramp files."
-  ;; FILES-ONLY is valid for XEmacs only.
   (when (file-directory-p directory)
     (setq directory (file-name-as-directory (expand-file-name directory)))
     (let ((temp (nreverse (file-name-all-completions "" directory)))
@@ -2885,12 +2756,7 @@ User is always nil."
 
       (while temp
        (setq item (directory-file-name (pop temp)))
-       (when (and (or (null match) (string-match match item))
-                  (or (null files-only)
-                      ;; Files only.
-                      (and (equal files-only t) (file-regular-p item))
-                      ;; Directories only.
-                      (file-directory-p item)))
+       (when (or (null match) (string-match match item))
          (push (if full (concat directory item) item)
                result)))
       (if nosort result (sort result 'string<)))))
@@ -2900,15 +2766,14 @@ User is always nil."
   "Like `directory-files-and-attributes' for Tramp files."
   (mapcar
    (lambda (x)
-     (cons x (tramp-compat-file-attributes
+     (cons x (file-attributes
              (if full x (expand-file-name x directory)) id-format)))
    (directory-files directory full match nosort)))
 
-(defun tramp-handle-dired-uncache (dir &optional dir-p)
+(defun tramp-handle-dired-uncache (dir)
   "Like `dired-uncache' for Tramp files."
-  ;; DIR-P is valid for XEmacs only.
   (with-parsed-tramp-file-name
-      (if (or dir-p (file-directory-p dir)) dir (file-name-directory dir)) nil
+      (if (file-directory-p dir) dir (file-name-directory dir)) nil
     (tramp-flush-directory-property v localname)))
 
 (defun tramp-handle-file-accessible-directory-p (filename)
@@ -2916,10 +2781,30 @@ User is always nil."
   (and (file-directory-p filename)
        (file-readable-p filename)))
 
+(defun tramp-handle-file-equal-p (filename1 filename2)
+  "Like `file-equalp-p' for Tramp files."
+  ;; Native `file-equalp-p' calls `file-truename', which requires a
+  ;; remote connection.  This can be avoided, if FILENAME1 and
+  ;; FILENAME2 are not located on the same remote host.
+  (when (string-equal
+        (file-remote-p (expand-file-name filename1))
+        (file-remote-p (expand-file-name filename2)))
+    (tramp-run-real-handler 'file-equal-p (list filename1 filename2))))
+
 (defun tramp-handle-file-exists-p (filename)
   "Like `file-exists-p' for Tramp files."
   (not (null (file-attributes filename))))
 
+(defun tramp-handle-file-in-directory-p (filename directory)
+  "Like `file-in-directory-p' for Tramp files."
+  ;; Native `file-in-directory-p' calls `file-truename', which
+  ;; requires a remote connection.  This can be avoided, if FILENAME
+  ;; and DIRECTORY are not located on the same remote host.
+  (when (string-equal
+        (file-remote-p (expand-file-name filename))
+        (file-remote-p (expand-file-name directory)))
+    (tramp-run-real-handler 'file-in-directory-p (list filename directory))))
+
 (defun tramp-handle-file-modes (filename)
   "Like `file-modes' for Tramp files."
   (let ((truename (or (file-truename filename) filename)))
@@ -2938,7 +2823,8 @@ User is always nil."
      (tramp-file-name-user v)
      (tramp-file-name-host v)
      (tramp-run-real-handler
-      'file-name-as-directory (list (or (tramp-file-name-localname v) ""))))))
+      'file-name-as-directory (list (or (tramp-file-name-localname v) "")))
+     (tramp-file-name-hop v))))
 
 (defun tramp-handle-file-name-completion
   (filename directory &optional predicate)
@@ -2966,7 +2852,8 @@ User is always nil."
      (tramp-file-name-user v)
      (tramp-file-name-host v)
      (tramp-run-real-handler
-      'file-name-directory (list (or (tramp-file-name-localname v) ""))))))
+      'file-name-directory (list (or (tramp-file-name-localname v) "")))
+     (tramp-file-name-hop v))))
 
 (defun tramp-handle-file-name-nondirectory (file)
   "Like `file-name-nondirectory' but aware of Tramp files."
@@ -2993,7 +2880,8 @@ User is always nil."
     (when (tramp-tramp-file-p filename)
       (let* ((v (tramp-dissect-file-name filename))
             (p (tramp-get-connection-process v))
-            (c (and p (processp p) (memq (process-status p) '(run open)))))
+            (c (and p (processp p) (memq (process-status p) '(run open))
+                    (tramp-get-connection-property p "connected" nil))))
        ;; We expand the file name only, if there is already a connection.
        (with-parsed-tramp-file-name
            (if c (expand-file-name filename) filename) nil
@@ -3003,7 +2891,8 @@ User is always nil."
                ((eq identification 'user) user)
                ((eq identification 'host) host)
                ((eq identification 'localname) localname)
-               (t (tramp-make-tramp-file-name method user host "")))))))))
+               ((eq identification 'hop) hop)
+               (t (tramp-make-tramp-file-name method user host "" hop)))))))))
 
 (defun tramp-handle-file-symlink-p (filename)
   "Like `file-symlink-p' for Tramp files."
@@ -3017,43 +2906,19 @@ User is always nil."
 (defun tramp-handle-find-backup-file-name (filename)
   "Like `find-backup-file-name' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    ;; We set both variables. It doesn't matter whether it is
-    ;; Emacs or XEmacs.
     (let ((backup-directory-alist
-          ;; Emacs case.
-          (when (boundp 'backup-directory-alist)
-            (if (symbol-value 'tramp-backup-directory-alist)
-                (mapcar
-                 (lambda (x)
-                   (cons
-                    (car x)
-                    (if (and (stringp (cdr x))
-                             (file-name-absolute-p (cdr x))
-                             (not (tramp-file-name-p (cdr x))))
-                        (tramp-make-tramp-file-name method user host (cdr x))
-                      (cdr x))))
-                 (symbol-value 'tramp-backup-directory-alist))
-              (symbol-value 'backup-directory-alist))))
-
-         (bkup-backup-directory-info
-          ;; XEmacs case.
-          (when (boundp 'bkup-backup-directory-info)
-            (if (symbol-value 'tramp-bkup-backup-directory-info)
-                (mapcar
-                 (lambda (x)
-                   (nconc
-                    (list (car x))
-                    (list
-                     (if (and (stringp (car (cdr x)))
-                              (file-name-absolute-p (car (cdr x)))
-                              (not (tramp-file-name-p (car (cdr x)))))
-                         (tramp-make-tramp-file-name
-                          method user host (car (cdr x)))
-                       (car (cdr x))))
-                    (cdr (cdr x))))
-                 (symbol-value 'tramp-bkup-backup-directory-info))
-              (symbol-value 'bkup-backup-directory-info)))))
-
+          (if tramp-backup-directory-alist
+              (mapcar
+               (lambda (x)
+                 (cons
+                  (car x)
+                  (if (and (stringp (cdr x))
+                           (file-name-absolute-p (cdr x))
+                           (not (tramp-file-name-p (cdr x))))
+                      (tramp-make-tramp-file-name method user host (cdr x))
+                    (cdr x))))
+               tramp-backup-directory-alist)
+            backup-directory-alist)))
       (tramp-run-real-handler 'find-backup-file-name (list filename)))))
 
 (defun tramp-handle-insert-directory
@@ -3101,7 +2966,7 @@ User is always nil."
               v 'file-error "File `%s' not found on remote host" filename)
 
            (with-tramp-progress-reporter
-               v 3 (format "Inserting `%s'" filename)
+               v 3 (format-message "Inserting `%s'" filename)
              (condition-case err
                  (if (and (tramp-local-host-p v)
                           (let (file-name-handler-alist)
@@ -3118,8 +2983,7 @@ User is always nil."
                    ;; name handlers.
                    (when (and (or beg end)
                               (tramp-get-method-parameter
-                               (tramp-file-name-method v)
-                               'tramp-login-program))
+                               v 'tramp-login-program))
                      (setq remote-copy (tramp-make-tramp-temp-file v))
                      ;; This is defined in tramp-sh.el.  Let's assume
                      ;; this is loaded already.
@@ -3142,9 +3006,10 @@ User is always nil."
                      (setq tramp-temp-buffer-file-name nil beg nil end nil))
 
                    ;; `insert-file-contents-literally' takes care to
-                   ;; avoid calling jka-compr.  By let-binding
-                   ;; `inhibit-file-name-operation', we propagate that
-                   ;; care to the `file-local-copy' operation.
+                   ;; avoid calling jka-compr.el and epa.el.  By
+                   ;; let-binding `inhibit-file-name-operation', we
+                   ;; propagate that care to the `file-local-copy'
+                   ;; operation.
                    (setq local-copy
                          (let ((inhibit-file-name-operation
                                 (when (eq inhibit-file-name-operation
@@ -3164,20 +3029,17 @@ User is always nil."
                    ;; When the file is not readable for the owner, it
                    ;; cannot be inserted, even if it is readable for the
                    ;; group or for everybody.
-                   (set-file-modes
-                    local-copy (tramp-compat-octal-to-decimal "0600"))
+                   (set-file-modes local-copy (string-to-number "0600" 8))
 
                    (when (and (null remote-copy)
                               (tramp-get-method-parameter
-                               method 'tramp-copy-keep-tmpfile))
+                               v 'tramp-copy-keep-tmpfile))
                      ;; We keep the local file for performance reasons,
                      ;; useful for "rsync".
                      (setq tramp-temp-buffer-file-name local-copy))
 
                    ;; We must ensure that `file-coding-system-alist'
-                   ;; matches `local-copy'.  We must also use `visit',
-                   ;; otherwise there might be an error in the
-                   ;; `revert-buffer' function under XEmacs.
+                   ;; matches `local-copy'.
                    (let ((file-coding-system-alist
                           (tramp-find-file-name-coding-system-alist
                            filename local-copy)))
@@ -3233,7 +3095,7 @@ User is always nil."
        (with-tramp-progress-reporter v 0 (format "Loading %s" file)
          (let ((local-copy (file-local-copy file)))
            (unwind-protect
-               (tramp-compat-load local-copy noerror t nosuffix must-suffix)
+               (load local-copy noerror t nosuffix must-suffix)
              (delete-file local-copy)))))
       t)))
 
@@ -3253,12 +3115,10 @@ User is always nil."
         (args (append
                (cons
                 (tramp-get-method-parameter
-                 (tramp-file-name-method
-                  (tramp-dissect-file-name default-directory))
+                 (tramp-dissect-file-name default-directory)
                  'tramp-remote-shell)
                 (tramp-get-method-parameter
-                 (tramp-file-name-method
-                  (tramp-dissect-file-name default-directory))
+                 (tramp-dissect-file-name default-directory)
                  'tramp-remote-shell-args))
                (list (substring command 0 asynchronous))))
         current-buffer-p
@@ -3329,9 +3189,7 @@ User is always nil."
                                     (current-buffer))))
          ;; There's some output, display it.
          (when (with-current-buffer output-buffer (> (point-max) (point-min)))
-           (if (functionp 'display-message-or-buffer)
-               (tramp-compat-funcall 'display-message-or-buffer output-buffer)
-             (pop-to-buffer output-buffer))))))))
+           (display-message-or-buffer output-buffer)))))))
 
 (defun tramp-handle-substitute-in-file-name (filename)
   "Like `substitute-in-file-name' for Tramp files.
@@ -3351,14 +3209,6 @@ User is always nil."
     (let (process-environment)
       (tramp-run-real-handler 'substitute-in-file-name (list filename)))))
 
-(defun tramp-handle-unhandled-file-name-directory (_filename)
-  "Like `unhandled-file-name-directory' for Tramp files."
-  ;; Starting with Emacs 23, we must simply return `nil'.  But we must
-  ;; keep backward compatibility, also with XEmacs.  "~/" cannot be
-  ;; returned, because there might be machines without a HOME
-  ;; directory (like hydra).
-  (and (< emacs-major-version 23) "/"))
-
 (defun tramp-handle-set-visited-file-modtime (&optional time-list)
   "Like `set-visited-file-modtime' for Tramp files."
   (unless (buffer-file-name)
@@ -3387,7 +3237,7 @@ of."
       ;; connection.
       (if (or (not f)
              (eq (visited-file-modtime) 0)
-             (not (tramp-file-name-handler 'file-remote-p f nil 'connected)))
+             (not (file-remote-p f nil 'connected)))
          t
        (with-parsed-tramp-file-name f nil
          (let* ((remote-file-name-inhibit-cache t)
@@ -3416,7 +3266,7 @@ of."
 (defun tramp-handle-file-notify-add-watch (filename _flags _callback)
   "Like `file-notify-add-watch' for Tramp files."
   ;; This is the default handler.  tramp-gvfs.el and tramp-sh.el have
-  ;; its own one.
+  ;; their own one.
   (setq filename (expand-file-name filename))
   (with-parsed-tramp-file-name filename nil
     (tramp-error
@@ -3428,7 +3278,17 @@ of."
   (unless (processp proc)
     (tramp-error proc 'file-notify-error "Not a valid descriptor %S" proc))
   (tramp-message proc 6 "Kill %S" proc)
-  (kill-process proc))
+  (delete-process proc))
+
+(defun tramp-handle-file-notify-valid-p (proc)
+  "Like `file-notify-valid-p' for Tramp files."
+  (and proc (processp proc) (memq (process-status proc) '(run open))
+       ;; Sometimes, the process is still in status `run' when the
+       ;; file or directory to be watched is deleted already.
+       (with-current-buffer (process-buffer proc)
+        (file-exists-p
+         (concat (file-remote-p default-directory)
+                 (process-get proc 'watch-name))))))
 
 ;;; Functions for establishing connection:
 
@@ -3603,11 +3463,12 @@ connection buffer."
           (cond
            ((eq exit 'permission-denied) "Permission denied")
            ((eq exit 'process-died)
-            (concat
-             "Tramp failed to connect.  If this happens repeatedly, try\n"
-             "    `M-x tramp-cleanup-this-connection'"))
+             (substitute-command-keys
+              (concat
+               "Tramp failed to connect.  If this happens repeatedly, try\n"
+               "    `\\[tramp-cleanup-this-connection]'")))
            ((eq exit 'timeout)
-            (format
+            (format-message
              "Timeout reached, see buffer `%s' for details"
              (tramp-get-connection-buffer vec)))
            (t "Login failed")))))
@@ -3630,9 +3491,7 @@ for process communication also."
       ;; Under Windows XP, accept-process-output doesn't return
       ;; sometimes.  So we add an additional timeout.
       (with-timeout ((or timeout 1))
-       (if (featurep 'xemacs)
-           (accept-process-output p timeout timeout-msecs)
-         (accept-process-output p timeout timeout-msecs (and proc t))))
+       (accept-process-output p timeout timeout-msecs (and proc t)))
       (tramp-message proc 10 "%s %s %s\n%s"
                     proc (process-status proc) p (buffer-string)))))
 
@@ -3657,11 +3516,10 @@ Erase echoed commands if exists."
     (when (or (not (tramp-get-connection-property proc "check-remote-echo" nil))
              ;; Sometimes, the echo string is suppressed on the remote side.
              (not (string-equal
-                   (tramp-compat-funcall
-                    'substring-no-properties tramp-echo-mark-marker
+                   (substring-no-properties
+                    tramp-echo-mark-marker
                     0 (min tramp-echo-mark-marker-length (1- (point-max))))
-                   (tramp-compat-funcall
-                    'buffer-substring-no-properties
+                   (buffer-substring-no-properties
                     (point-min)
                     (min (+ (point-min) tramp-echo-mark-marker-length)
                          (point-max))))))
@@ -3679,22 +3537,15 @@ Expects the output of PROC to be sent to the current buffer.  Returns
 the string that matched, or nil.  Waits indefinitely if TIMEOUT is
 nil."
   (with-current-buffer (process-buffer proc)
-    (let ((found (tramp-check-for-regexp proc regexp))
-         (start-time (current-time)))
+    (let ((found (tramp-check-for-regexp proc regexp)))
       (cond (timeout
-            ;; Work around a bug in XEmacs 21, where the timeout
-            ;; expires faster than it should.  This degenerates
-            ;; to polling for buggy XEmacsen, but oh, well.
-            (while (and (not found)
-                        (< (tramp-time-diff (current-time) start-time)
-                           timeout))
-              (with-timeout (timeout)
-                (while (not found)
-                  (tramp-accept-process-output proc 1)
-                  (unless (memq (process-status proc) '(run open))
-                    (tramp-error-with-buffer
-                     nil proc 'file-error "Process has died"))
-                  (setq found (tramp-check-for-regexp proc regexp))))))
+            (with-timeout (timeout)
+              (while (not found)
+                (tramp-accept-process-output proc 1)
+                (unless (memq (process-status proc) '(run open))
+                  (tramp-error-with-buffer
+                   nil proc 'file-error "Process has died"))
+                (setq found (tramp-check-for-regexp proc regexp)))))
            (t
             (while (not found)
               (tramp-accept-process-output proc 1)
@@ -3734,9 +3585,8 @@ the remote host use line-endings as defined in the variable
       (let (buffer-read-only) (delete-region (point-min) (point-max)))
       ;; Replace "\n" by `tramp-rsh-end-of-line'.
       (setq string
-           (mapconcat 'identity
-                      (tramp-compat-split-string string "\n")
-                      tramp-rsh-end-of-line))
+           (mapconcat
+            'identity (split-string string "\n") tramp-rsh-end-of-line))
       (unless (or (string= string "")
                  (string-equal (substring string -1) tramp-rsh-end-of-line))
        (setq string (concat string tramp-rsh-end-of-line)))
@@ -3776,7 +3626,7 @@ Example:
 
   (tramp-equal-remote \"/ssh::/etc\" \"/<your host name>:/home\")
 
-would yield `t'.  On the other hand, the following check results in nil:
+would yield t.  On the other hand, the following check results in nil:
 
   (tramp-equal-remote \"/sudo::/etc\" \"/su::/etc\")"
   (and (tramp-tramp-file-p file1)
@@ -3800,57 +3650,47 @@ would yield `t'.  On the other hand, the following check results in nil:
     (save-match-data
       (logior
        (cond
-       ((char-equal owner-read ?r) (tramp-compat-octal-to-decimal "00400"))
+       ((char-equal owner-read ?r) (string-to-number "00400" 8))
        ((char-equal owner-read ?-) 0)
        (t (error "Second char `%c' must be one of `r-'" owner-read)))
        (cond
-       ((char-equal owner-write ?w) (tramp-compat-octal-to-decimal "00200"))
+       ((char-equal owner-write ?w) (string-to-number "00200" 8))
        ((char-equal owner-write ?-) 0)
        (t (error "Third char `%c' must be one of `w-'" owner-write)))
        (cond
-       ((char-equal owner-execute-or-setid ?x)
-        (tramp-compat-octal-to-decimal "00100"))
-       ((char-equal owner-execute-or-setid ?S)
-        (tramp-compat-octal-to-decimal "04000"))
-       ((char-equal owner-execute-or-setid ?s)
-        (tramp-compat-octal-to-decimal "04100"))
+       ((char-equal owner-execute-or-setid ?x) (string-to-number "00100" 8))
+       ((char-equal owner-execute-or-setid ?S) (string-to-number "04000" 8))
+       ((char-equal owner-execute-or-setid ?s) (string-to-number "04100" 8))
        ((char-equal owner-execute-or-setid ?-) 0)
        (t (error "Fourth char `%c' must be one of `xsS-'"
                  owner-execute-or-setid)))
        (cond
-       ((char-equal group-read ?r) (tramp-compat-octal-to-decimal "00040"))
+       ((char-equal group-read ?r) (string-to-number "00040" 8))
        ((char-equal group-read ?-) 0)
        (t (error "Fifth char `%c' must be one of `r-'" group-read)))
        (cond
-       ((char-equal group-write ?w) (tramp-compat-octal-to-decimal "00020"))
+       ((char-equal group-write ?w) (string-to-number "00020" 8))
        ((char-equal group-write ?-) 0)
        (t (error "Sixth char `%c' must be one of `w-'" group-write)))
        (cond
-       ((char-equal group-execute-or-setid ?x)
-        (tramp-compat-octal-to-decimal "00010"))
-       ((char-equal group-execute-or-setid ?S)
-        (tramp-compat-octal-to-decimal "02000"))
-       ((char-equal group-execute-or-setid ?s)
-        (tramp-compat-octal-to-decimal "02010"))
+       ((char-equal group-execute-or-setid ?x) (string-to-number "00010" 8))
+       ((char-equal group-execute-or-setid ?S) (string-to-number "02000" 8))
+       ((char-equal group-execute-or-setid ?s) (string-to-number "02010" 8))
        ((char-equal group-execute-or-setid ?-) 0)
        (t (error "Seventh char `%c' must be one of `xsS-'"
                  group-execute-or-setid)))
        (cond
-       ((char-equal other-read ?r)
-        (tramp-compat-octal-to-decimal "00004"))
+       ((char-equal other-read ?r) (string-to-number "00004" 8))
        ((char-equal other-read ?-) 0)
        (t (error "Eighth char `%c' must be one of `r-'" other-read)))
        (cond
-         ((char-equal other-write ?w) (tramp-compat-octal-to-decimal "00002"))
-        ((char-equal other-write ?-) 0)
-         (t (error "Ninth char `%c' must be one of `w-'" other-write)))
+       ((char-equal other-write ?w) (string-to-number "00002" 8))
+       ((char-equal other-write ?-) 0)
+       (t (error "Ninth char `%c' must be one of `w-'" other-write)))
        (cond
-       ((char-equal other-execute-or-sticky ?x)
-        (tramp-compat-octal-to-decimal "00001"))
-       ((char-equal other-execute-or-sticky ?T)
-        (tramp-compat-octal-to-decimal "01000"))
-       ((char-equal other-execute-or-sticky ?t)
-        (tramp-compat-octal-to-decimal "01001"))
+       ((char-equal other-execute-or-sticky ?x) (string-to-number "00001" 8))
+       ((char-equal other-execute-or-sticky ?T) (string-to-number "01000" 8))
+       ((char-equal other-execute-or-sticky ?t) (string-to-number "01001" 8))
        ((char-equal other-execute-or-sticky ?-) 0)
        (t (error "Tenth char `%c' must be one of `xtT-'"
                  other-execute-or-sticky)))))))
@@ -3908,9 +3748,30 @@ This is used internally by `tramp-file-mode-from-int'."
 
 ;;;###tramp-autoload
 (defun tramp-get-local-gid (id-format)
+  ;; `group-gid' has been introduced with Emacs 24.4.
   (if (and (fboundp 'group-gid) (equal id-format 'integer))
       (tramp-compat-funcall 'group-gid)
-    (nth 3 (tramp-compat-file-attributes "~/" id-format))))
+    (nth 3 (file-attributes "~/" id-format))))
+
+(defun tramp-get-local-locale (&optional vec)
+  ;; We use key nil for local connection properties.
+  (with-tramp-connection-property nil "locale"
+    (let ((candidates '("en_US.utf8" "C.utf8" "en_US.UTF-8"))
+         locale)
+      (with-temp-buffer
+       (unless (or (memq system-type '(windows-nt))
+                    (not (zerop (tramp-call-process
+                                 nil "locale" nil t nil "-a"))))
+         (while candidates
+           (goto-char (point-min))
+           (if (string-match (format "^%s\r?$" (regexp-quote (car candidates)))
+                             (buffer-string))
+               (setq locale (car candidates)
+                     candidates nil)
+             (setq candidates (cdr candidates))))))
+      ;; Return value.
+      (when vec (tramp-message vec 7 "locale %s" (or locale "C")))
+      (or locale "C"))))
 
 ;;;###tramp-autoload
 (defun tramp-check-cached-permissions (vec access)
@@ -3932,7 +3793,7 @@ be granted."
                (tramp-get-file-property
                 vec (tramp-file-name-localname vec)
                 (concat "file-attributes-" suffix) nil)
-               (tramp-compat-file-attributes
+               (file-attributes
                 (tramp-make-tramp-file-name
                  (tramp-file-name-method vec)
                  (tramp-file-name-user vec)
@@ -3977,8 +3838,7 @@ be granted."
      ;; The method shall be applied to one of the shell file name
      ;; handlers.  `tramp-local-host-p' is also called for "smb" and
      ;; alike, where it must fail.
-     (tramp-get-method-parameter
-      (tramp-file-name-method vec) 'tramp-login-program)
+     (tramp-get-method-parameter vec 'tramp-login-program)
      ;; The local temp directory must be writable for the other user.
      (file-writable-p
       (tramp-make-tramp-file-name
@@ -3994,18 +3854,19 @@ be granted."
 
 (defun tramp-get-remote-tmpdir (vec)
   "Return directory for temporary files on the remote host identified by VEC."
-  (with-tramp-connection-property vec "tmpdir"
-    (let ((dir (tramp-make-tramp-file-name
-               (tramp-file-name-method vec)
-               (tramp-file-name-user vec)
-               (tramp-file-name-host vec)
-               (or
-                (tramp-get-method-parameter
-                 (tramp-file-name-method vec) 'tramp-tmpdir)
-                "/tmp"))))
-      (if (and (file-directory-p dir) (file-writable-p dir))
-         dir
-       (tramp-error vec 'file-error "Directory %s not accessible" dir)))))
+  (when (file-remote-p (tramp-get-connection-property vec "tmpdir" ""))
+    ;; Compatibility code: Cached value shall be the local path only.
+    (tramp-set-connection-property vec "tmpdir" 'undef))
+  (let ((dir (tramp-make-tramp-file-name
+             (tramp-file-name-method vec)
+             (tramp-file-name-user vec)
+             (tramp-file-name-host vec)
+             (or (tramp-get-method-parameter vec 'tramp-tmpdir) "/tmp"))))
+    (with-tramp-connection-property vec "tmpdir"
+      (or (and (file-directory-p dir) (file-writable-p dir)
+              (file-remote-p dir 'localname))
+         (tramp-error vec 'file-error "Directory %s not accessible" dir)))
+    dir))
 
 ;;;###tramp-autoload
 (defun tramp-make-tramp-temp-file (vec)
@@ -4024,7 +3885,7 @@ Return the local name of the temporary file."
          (setq result nil)
        ;; This creates the file by side effect.
        (set-file-times result)
-       (set-file-modes result (tramp-compat-octal-to-decimal "0700"))))
+       (set-file-modes result (string-to-number "0700" 8))))
 
     ;; Return the local part.
     (with-parsed-tramp-file-name result nil localname)))
@@ -4040,94 +3901,37 @@ Return the local name of the temporary file."
            (remove-hook 'kill-buffer-hook
                         'tramp-delete-temp-file-function)))
 
-;;; Auto saving to a special directory:
-
 (defun tramp-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)
+Returns a file name in `tramp-auto-save-directory' for autosaving
+this file, if that variable is non-nil."
+  (when (stringp tramp-auto-save-directory)
+    (setq tramp-auto-save-directory
+         (expand-file-name tramp-auto-save-directory)))
+  ;; Create directory.
+  (unless (or (null tramp-auto-save-directory)
+             (file-exists-p tramp-auto-save-directory))
+    (make-directory tramp-auto-save-directory t))
+
+  (let ((system-type 'not-windows)
+       (auto-save-file-name-transforms
+        (if (null tramp-auto-save-directory)
+            auto-save-file-name-transforms))
        (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)))))
-
-(unless (tramp-exists-file-name-handler 'make-auto-save-file-name)
-  (defadvice make-auto-save-file-name
-    (around tramp-advice-make-auto-save-file-name () activate)
-    "Invoke `tramp-*-handle-make-auto-save-file-name' for Tramp files."
-    (if (tramp-tramp-file-p (buffer-file-name))
-       ;; We cannot call `tramp-handle-make-auto-save-file-name'
-       ;; directly, because this would bypass the locking mechanism.
-       (setq ad-return-value
-             (tramp-file-name-handler 'make-auto-save-file-name))
-      ad-do-it))
-  (add-hook
-   'tramp-unload-hook
-   (lambda ()
-     (ad-remove-advice
-      'make-auto-save-file-name
-      'around 'tramp-advice-make-auto-save-file-name)
-     (ad-activate 'make-auto-save-file-name))))
-
-;; In XEmacs < 21.5, autosaved remote files have permission 0666 minus
-;; umask. This is a security threat.
-
-(defun tramp-set-auto-save-file-modes ()
-  "Set permissions of autosaved remote files to the original permissions."
-  (let ((bfn (buffer-file-name)))
-    (when (and (tramp-tramp-file-p bfn)
-              (buffer-modified-p)
-              (stringp buffer-auto-save-file-name)
-              (not (equal bfn buffer-auto-save-file-name)))
-      (unless (file-exists-p buffer-auto-save-file-name)
-       (write-region "" nil buffer-auto-save-file-name))
-      ;; Permissions should be set always, because there might be an old
-      ;; auto-saved file belonging to another original file.  This could
-      ;; be a security threat.
-      (set-file-modes
-       buffer-auto-save-file-name
-       (or (file-modes bfn) (tramp-compat-octal-to-decimal "0600"))))))
-
-(unless (and (featurep 'xemacs)
-            (= emacs-major-version 21)
-            (> emacs-minor-version 4))
-  (add-hook 'auto-save-hook 'tramp-set-auto-save-file-modes)
-  (add-hook 'tramp-unload-hook
-           (lambda ()
-             (remove-hook 'auto-save-hook 'tramp-set-auto-save-file-modes))))
+        (if (null tramp-auto-save-directory)
+            buffer-file-name
+          (expand-file-name
+           (tramp-subst-strs-in-string
+            '(("_" . "|")
+              ("/" . "_a")
+              (":" . "_b")
+              ("|" . "__")
+              ("[" . "_l")
+              ("]" . "_r"))
+            (buffer-file-name))
+           tramp-auto-save-directory))))
+    ;; Run plain `make-auto-save-file-name'.
+    (tramp-run-real-handler 'make-auto-save-file-name nil)))
 
 (defun tramp-subst-strs-in-string (alist string)
   "Replace all occurrences of the string FROM with TO in STRING.
@@ -4174,6 +3978,38 @@ are written with verbosity of 6."
        (tramp-message v 6 "%d\n%s" result (error-message-string err))))
     result))
 
+(defun tramp-call-process-region
+  (vec start end program &optional delete buffer display &rest args)
+  "Calls `call-process-region' on the local host.
+It always returns a return code.  The Lisp error raised when
+PROGRAM is nil is trapped also, returning 1.  Furthermore, traces
+are written with verbosity of 6."
+  (let ((v (or vec
+              (vector tramp-current-method tramp-current-user
+                      tramp-current-host nil nil)))
+       (buffer (if (eq buffer t) (current-buffer) buffer))
+       result)
+    (tramp-message
+     v 6 "`%s %s' %s %s %s %s"
+     program (mapconcat 'identity args " ") start end delete buffer)
+    (condition-case err
+       (progn
+         (setq result
+               (apply
+                'call-process-region
+                start end program delete buffer display args))
+         ;; `result' could also be an error string.
+         (when (stringp result)
+           (signal 'file-error (list result)))
+         (with-current-buffer (if (bufferp buffer) buffer (current-buffer))
+            (if (zerop result)
+                (tramp-message v 6 "%d" result)
+              (tramp-message v 6 "%d\n%s" result (buffer-string)))))
+      (error
+       (setq result 1)
+       (tramp-message v 6 "%d\n%s" result (error-message-string err))))
+    result))
+
 ;;;###tramp-autoload
 (defun tramp-read-passwd (proc &optional prompt)
   "Read a password from user (compat function).
@@ -4189,27 +4025,24 @@ Invokes `password-read' if available, `read-passwd' else."
                (tramp-check-for-regexp proc tramp-password-prompt-regexp)
                (format "%s for %s " (capitalize (match-string 1)) key))))
         ;; We suspend the timers while reading the password.
-         (stimers (and (functionp 'with-timeout-suspend)
-                      (tramp-compat-funcall 'with-timeout-suspend)))
+         (stimers (with-timeout-suspend))
         auth-info auth-passwd)
 
     (unwind-protect
        (with-parsed-tramp-file-name key nil
          (prog1
              (or
-              ;; See if auth-sources contains something useful, if
-              ;; it's bound.  `auth-source-user-or-password' is an
-              ;; obsoleted function, it has been replaced by
+              ;; See if auth-sources contains something useful.
+              ;; `auth-source-user-or-password' is an obsoleted
+              ;; function since Emacs 24.1, it has been replaced by
               ;; `auth-source-search'.
               (ignore-errors
-                (and (boundp 'auth-sources)
-                     (tramp-get-connection-property
+                (and (tramp-get-connection-property
                       v "first-password-request" nil)
                      ;; Try with Tramp's current method.
                      (if (fboundp 'auth-source-search)
                          (setq auth-info
-                               (tramp-compat-funcall
-                                'auth-source-search
+                               (auth-source-search
                                 :max 1
                                 :user (or tramp-current-user t)
                                 :host tramp-current-host
@@ -4219,27 +4052,32 @@ Invokes `password-read' if available, `read-passwd' else."
                                auth-passwd (if (functionp auth-passwd)
                                                (funcall auth-passwd)
                                              auth-passwd))
-                       (tramp-compat-funcall
-                        'auth-source-user-or-password
+                       (tramp-compat-funcall 'auth-source-user-or-password
                         "password" tramp-current-host tramp-current-method))))
               ;; Try the password cache.
-              (when (functionp 'password-read)
-                (let ((password
-                       (tramp-compat-funcall 'password-read pw-prompt key)))
-                  (tramp-compat-funcall 'password-cache-add key password)
-                  password))
+              (let ((password (password-read pw-prompt key)))
+                (password-cache-add key password)
+                password)
               ;; Else, get the password interactively.
               (read-passwd pw-prompt))
            (tramp-set-connection-property v "first-password-request" nil)))
       ;; Reenable the timers.
-      (and (functionp 'with-timeout-unsuspend)
-          (tramp-compat-funcall 'with-timeout-unsuspend stimers)))))
+      (with-timeout-unsuspend stimers))))
 
 ;;;###tramp-autoload
 (defun tramp-clear-passwd (vec)
   "Clear password cache for connection related to VEC."
-  (tramp-compat-funcall
-   'password-cache-remove
+  (let ((hop (tramp-file-name-hop vec)))
+    (when hop
+      ;; Clear also the passwords of the hops.
+      (tramp-clear-passwd
+       (tramp-dissect-file-name
+       (concat
+        tramp-prefix-format
+        (replace-regexp-in-string
+         (concat tramp-postfix-hop-regexp "$")
+         tramp-postfix-host-format hop))))))
+  (password-cache-remove
    (tramp-make-tramp-file-name
     (tramp-file-name-method vec)
     (tramp-file-name-user vec)
@@ -4262,24 +4100,7 @@ Invokes `password-read' if available, `read-passwd' else."
 (defun tramp-time-diff (t1 t2)
   "Return the difference between the two times, in seconds.
 T1 and T2 are time values (as returned by `current-time' for example)."
-  (cond ((and (fboundp 'subtract-time)
-             (fboundp 'float-time))
-         (tramp-compat-funcall
-         'float-time (tramp-compat-funcall 'subtract-time t1 t2)))
-       ((and (fboundp 'subtract-time)
-             (fboundp 'time-to-seconds))
-         (tramp-compat-funcall
-         'time-to-seconds (tramp-compat-funcall 'subtract-time t1 t2)))
-        ((fboundp 'itimer-time-difference)
-        (tramp-compat-funcall
-         'itimer-time-difference
-         (if (< (length t1) 3) (append t1 '(0)) t1)
-         (if (< (length t2) 3) (append t2 '(0)) t2)))
-        (t
-        (let ((time (time-subtract t1 t2)))
-          (+ (* (car time) 65536.0)
-             (cadr time)
-             (/ (or (nth 2 time) 0) 1000000.0))))))
+  (float-time (subtract-time t1 t2)))
 
 ;; Currently (as of Emacs 20.5), the function `shell-quote-argument'
 ;; does not deal well with newline characters.  Newline is replaced by
@@ -4371,12 +4192,9 @@ Only works for Bourne-like shells."
 
 ;;; TODO:
 
-;; * Rewrite `tramp-shell-quote-argument' to abstain from using
-;;   `shell-quote-argument'.
 ;; * In Emacs 21, `insert-directory' shows total number of bytes used
 ;;   by the files in that directory.  Add this here.
 ;; * Avoid screen blanking when hitting `g' in dired.  (Eli Tziperman)
-;; * abbreviate-file-name
 ;; * Better error checking.  At least whenever we see something
 ;;   strange when doing zerop, we should kill the process and start
 ;;   again.  (Greg Stark)