]> code.delx.au - gnu-emacs/blobdiff - lisp/net/tramp.el
Merge from origin/emacs-25
[gnu-emacs] / lisp / net / tramp.el
index 95f54490cac597788fec48b5a508b97b3cdcd1da..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.
@@ -321,25 +292,9 @@ useful only in combination with `tramp-default-proxies-alist'.")
    ;; 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"))
-       "scp"
-      "ssh"))
+   ((executable-find "scp") "scp")
    ;; Fallback.
    (t "ftp"))
   "Default method to use for transferring files.
@@ -456,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,
@@ -474,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"
@@ -533,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'
@@ -551,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"))
@@ -669,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
@@ -875,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
@@ -900,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.
 
@@ -911,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.")
@@ -920,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
@@ -932,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.
 
@@ -943,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.
@@ -964,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)
@@ -985,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
@@ -1097,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."
@@ -1165,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)
@@ -1212,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.
@@ -1234,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.
@@ -1273,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
@@ -1429,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.
@@ -1458,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"
@@ -1481,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.
@@ -1523,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
@@ -1552,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)
@@ -1622,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.
@@ -1646,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)
@@ -1677,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."
@@ -1693,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)
@@ -1721,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)
@@ -1736,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)))
 
@@ -1773,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))
@@ -1806,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
@@ -1826,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
@@ -1859,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
@@ -1879,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
@@ -1967,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))
@@ -2020,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))
@@ -2056,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))
@@ -2088,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
@@ -2158,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)))
@@ -2195,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
@@ -2209,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
@@ -2223,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)))
 
@@ -2328,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."
@@ -2336,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
@@ -2344,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.
@@ -2748,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.
@@ -2770,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.
@@ -2794,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 "\\)$"))))
@@ -2835,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)))
@@ -2846,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<)))))
@@ -2861,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)
@@ -2877,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)))
@@ -2899,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)
@@ -2927,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."
@@ -2954,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
@@ -2964,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."
@@ -2978,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
@@ -3062,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)
@@ -3079,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.
@@ -3103,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
@@ -3125,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)))
@@ -3194,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)))
 
@@ -3214,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
@@ -3290,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.
@@ -3312,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)
@@ -3348,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)
@@ -3377,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
@@ -3389,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:
 
@@ -3564,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")))))
@@ -3591,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)))))
 
@@ -3618,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))))))
@@ -3640,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)
@@ -3695,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)))
@@ -3761,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)))))))
@@ -3869,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)
@@ -3893,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)
@@ -3938,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
@@ -3955,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)
@@ -3985,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)))
@@ -4001,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.
@@ -4135,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).
@@ -4150,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
@@ -4180,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)
@@ -4223,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
@@ -4332,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)