]> code.delx.au - gnu-emacs/blobdiff - lisp/net/tramp.el
Merged from emacs@sv.gnu.org.
[gnu-emacs] / lisp / net / tramp.el
index 6df8a5dab42542975500381e5d3ac4f9a3a3703f..822a995230e2540056e61f9e9a57890051d95110 100644 (file)
@@ -2,7 +2,7 @@
 ;;; tramp.el --- Transparent Remote Access, Multiple Protocol
 
 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;; tramp.el --- Transparent Remote Access, Multiple Protocol
 
 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005 Free Software Foundation, Inc.
+;;   2005, 2006 Free Software Foundation, Inc.
 
 ;; Author: Kai Gro\e,A_\e(Bjohann <kai.grossjohann@gmx.net>
 ;;         Michael Albinus <michael.albinus@gmx.de>
 
 ;; Author: Kai Gro\e,A_\e(Bjohann <kai.grossjohann@gmx.net>
 ;;         Michael Albinus <michael.albinus@gmx.de>
 
 ;; The Tramp version number and bug report address, as prepared by configure.
 (require 'trampver)
 
 ;; The Tramp version number and bug report address, as prepared by configure.
 (require 'trampver)
+(add-hook 'tramp-unload-hook
+         '(lambda ()
+            (when (featurep 'trampver)
+              (unload-feature 'trampver 'force))))
+
+(if (featurep 'xemacs)
+    (require 'timer-funcs)
+  (require 'timer))
 
 
-(require 'timer)
 (require 'format-spec)                  ;from Gnus 5.8, also in tar ball
 ;; As long as password.el is not part of (X)Emacs, it shouldn't
 ;; be mandatory
 (require 'format-spec)                  ;from Gnus 5.8, also in tar ball
 ;; As long as password.el is not part of (X)Emacs, it shouldn't
 ;; be mandatory
 
 (autoload 'tramp-uuencode-region "tramp-uu"
   "Implementation of `uuencode' in Lisp.")
 
 (autoload 'tramp-uuencode-region "tramp-uu"
   "Implementation of `uuencode' in Lisp.")
+(add-hook 'tramp-unload-hook
+         '(lambda ()
+            (when (featurep 'tramp-uu)
+              (unload-feature 'tramp-uu 'force))))
 
 (unless (fboundp 'uudecode-decode-region)
   (autoload 'uudecode-decode-region "uudecode"))
 
 (unless (fboundp 'uudecode-decode-region)
   (autoload 'uudecode-decode-region "uudecode"))
 ;;;###autoload
 (defvar tramp-unified-filenames (not (featurep 'xemacs))
   "Non-nil means to use unified Ange-FTP/Tramp filename syntax.
 ;;;###autoload
 (defvar tramp-unified-filenames (not (featurep 'xemacs))
   "Non-nil means to use unified Ange-FTP/Tramp filename syntax.
-Nil means to use a separate filename syntax for Tramp.")
+Otherwise, use a separate filename syntax for Tramp.")
 
 ;; Load foreign methods.  Because they do require Tramp internally, this
 ;; must be done with the `eval-after-load' trick.
 
 ;; Load foreign methods.  Because they do require Tramp internally, this
 ;; must be done with the `eval-after-load' trick.
@@ -110,10 +121,20 @@ Nil means to use a separate filename syntax for Tramp.")
 ;; tramp-ftp supports Ange-FTP only.  Not suited for XEmacs therefore.
 (unless (featurep 'xemacs)
   (eval-after-load "tramp"
 ;; tramp-ftp supports Ange-FTP only.  Not suited for XEmacs therefore.
 (unless (featurep 'xemacs)
   (eval-after-load "tramp"
-    '(require 'tramp-ftp)))
+    '(progn
+       (require 'tramp-ftp)
+       (add-hook 'tramp-unload-hook
+                '(lambda ()
+                   (when (featurep 'tramp-ftp)
+                     (unload-feature 'tramp-ftp 'force)))))))
 (when (and tramp-unified-filenames (featurep 'xemacs))
   (eval-after-load "tramp"
 (when (and tramp-unified-filenames (featurep 'xemacs))
   (eval-after-load "tramp"
-    '(require 'tramp-efs)))
+    '(progn
+       (require 'tramp-efs)
+       (add-hook 'tramp-unload-hook
+                '(lambda ()
+                   (when (featurep 'tramp-efs)
+                     (unload-feature 'tramp-efs 'force)))))))
 
 ;; tramp-smb uses "smbclient" from Samba.
 ;; Not available under Cygwin and Windows, because they don't offer
 
 ;; tramp-smb uses "smbclient" from Samba.
 ;; Not available under Cygwin and Windows, because they don't offer
@@ -121,14 +142,18 @@ Nil means to use a separate filename syntax for Tramp.")
 ;; UNC file names like "//host/share/localname".
 (unless (memq system-type '(cygwin windows-nt))
   (eval-after-load "tramp"
 ;; UNC file names like "//host/share/localname".
 (unless (memq system-type '(cygwin windows-nt))
   (eval-after-load "tramp"
-    '(require 'tramp-smb)))
-
-(eval-when-compile
-  (require 'cl)
-  (require 'custom)
-  ;; Emacs 19.34 compatibility hack -- is this needed?
-  (or (>= emacs-major-version 20)
-      (load "cl-seq")))
+    '(progn
+       (require 'tramp-smb)
+       (add-hook 'tramp-unload-hook
+                '(lambda ()
+                   (when (featurep 'tramp-smb)
+                     (unload-feature 'tramp-smb 'force)))))))
+
+(require 'cl)
+(require 'custom)
+;; Emacs 19.34 compatibility hack -- is this needed?
+(or (>= emacs-major-version 20)
+    (load "cl-seq"))
 
 (unless (boundp 'custom-print-functions)
   (defvar custom-print-functions nil)) ; not autoloaded before Emacs 20.4
 
 (unless (boundp 'custom-print-functions)
   (defvar custom-print-functions nil)) ; not autoloaded before Emacs 20.4
@@ -447,6 +472,17 @@ This variable defaults to the value of `tramp-encoding-shell'."
               (tramp-copy-args            nil)
               (tramp-copy-keep-date-arg   nil)
              (tramp-password-end-of-line nil))
               (tramp-copy-args            nil)
               (tramp-copy-keep-date-arg   nil)
              (tramp-password-end-of-line nil))
+     ("scpc"  (tramp-connection-function  tramp-open-connection-rsh)
+              (tramp-login-program        "ssh")
+              (tramp-copy-program         "scp")
+              (tramp-remote-sh            "/bin/sh")
+              (tramp-login-args           ("-o" "ControlPath=%t.%%r@%%h:%%p"
+                                          "-o" "ControlMaster=yes"
+                                          "-e" "none"))
+              (tramp-copy-args            ("-o" "ControlPath=%t.%%r@%%h:%%p"
+                                          "-o" "ControlMaster=auto"))
+              (tramp-copy-keep-date-arg   "-p")
+             (tramp-password-end-of-line nil))
      ("scpx"  (tramp-connection-function  tramp-open-connection-rsh)
               (tramp-login-program        "ssh")
               (tramp-copy-program         "scp")
      ("scpx"  (tramp-connection-function  tramp-open-connection-rsh)
               (tramp-login-program        "ssh")
               (tramp-copy-program         "scp")
@@ -541,6 +577,7 @@ pair of the form (KEY VALUE).  The following KEYs are defined:
     If `tramp-connection-function' is `tramp-open-connection-su', then
     \"%u\" in this list is replaced by the user name, and \"%%\" can
     be used to obtain a literal percent character.
     If `tramp-connection-function' is `tramp-open-connection-su', then
     \"%u\" in this list is replaced by the user name, and \"%%\" can
     be used to obtain a literal percent character.
+    \"%t\" is replaced by the temporary file name for `scp'-like methods.
   * `tramp-copy-program'
     This specifies the name of the program to use for remotely copying
     the file; this might be the absolute filename of rcp or the name of
   * `tramp-copy-program'
     This specifies the name of the program to use for remotely copying
     the file; this might be the absolute filename of rcp or the name of
@@ -647,10 +684,39 @@ various functions for details."
   :type '(repeat (list string function string)))
 
 (defcustom tramp-default-method
   :type '(repeat (list string function string)))
 
 (defcustom tramp-default-method
-  (if (and (fboundp 'executable-find)
-          (executable-find "plink"))
-      "plink"
-    "ssh")
+  ;; An external copy method seems to be preferred, because it is much
+  ;; more performant for large files, and it hasn't too serious delays
+  ;; for small files.  But it must be ensured that there aren't
+  ;; permanent password queries.  Either a password agent like
+  ;; "ssh-agent" or "Pageant" shall run, or the optional password.el
+  ;; package shall be active for password caching.  "scpc" would be
+  ;; another good choice because of the "ControlMaster" option, but
+  ;; this is a more modern alternative in OpenSSH 4, which cannot be
+  ;; taken as default.
+  (let ((e-f (fboundp 'executable-find)))
+    (cond
+     ;; PuTTY is installed.
+     ((and e-f (funcall 'executable-find "pscp"))
+      (if (or (fboundp 'password-read)
+             ;; Pageant is running.
+             (and (fboundp 'w32-window-exists-p)
+                  (funcall 'w32-window-exists-p "Pageant" "Pageant")))
+         "pscp"
+       "plink"))
+     ;; There is an ssh installation.
+     ((and e-f (funcall 'executable-find "scp"))
+      (if (or (fboundp 'password-read)
+             ;; ssh-agent is running.
+             (getenv "SSH_AUTH_SOCK")
+             (getenv "SSH_AGENT_PID"))
+         "scp"
+       "ssh"))
+     ;; Under Emacs 20, `executable-find' does not exists.  So we
+     ;; couldn't check whether there is an ssh implementation.  Let's
+     ;; hope the best.
+     ((not e-f) "ssh")
+     ;; Fallback.
+     (t "ftp")))
   "*Default method to use for transferring files.
 See `tramp-methods' for possibilities.
 Also see `tramp-default-method-alist'."
   "*Default method to use for transferring files.
 See `tramp-methods' for possibilities.
 Also see `tramp-default-method-alist'."
@@ -810,8 +876,10 @@ The default value is to use the same value as `tramp-rsh-end-of-line'."
   :type 'string)
 
 (defcustom tramp-remote-path
   :type 'string)
 
 (defcustom tramp-remote-path
-  '("/bin" "/usr/bin" "/usr/sbin" "/usr/local/bin" "/usr/ccs/bin"
-    "/local/bin" "/local/freeware/bin" "/local/gnu/bin"
+  ;; "/usr/xpg4/bin" has been placed first, because on Solaris a POSIX
+  ;; compatible "id" is needed.
+  '("/usr/xpg4/bin" "/bin" "/usr/bin" "/usr/sbin" "/usr/local/bin"
+    "/usr/ccs/bin" "/local/bin" "/local/freeware/bin" "/local/gnu/bin"
     "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin")
   "*List of directories to search for executables on remote host.
 Please notify me about other semi-standard directories to include here.
     "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin")
   "*List of directories to search for executables on remote host.
 Please notify me about other semi-standard directories to include here.
@@ -886,8 +954,10 @@ See also `tramp-yn-prompt-regexp'."
   :type 'regexp)
 
 (defcustom tramp-yn-prompt-regexp
   :type 'regexp)
 
 (defcustom tramp-yn-prompt-regexp
-  (concat (regexp-opt '("Store key in cache? (y/n)") t)
-         "\\s-*")
+  (concat
+   (regexp-opt '("Store key in cache? (y/n)"
+                "Update cached key? (y/n, Return cancels connection)") t)
+   "\\s-*")
   "Regular expression matching all y/n queries which need to be confirmed.
 The confirmation should be done with y or n.
 The regexp should match at end of buffer.
   "Regular expression matching all y/n queries which need to be confirmed.
 The confirmation should be done with y or n.
 The regexp should match at end of buffer.
@@ -916,6 +986,17 @@ be ignored safely."
   :group 'tramp
   :type 'regexp)
 
   :group 'tramp
   :type 'regexp)
 
+(defcustom tramp-copy-failed-regexp
+  (concat "\\(.+: "
+          (regexp-opt '("Permission denied"
+                        "not a regular file"
+                        "is a directory"
+                        "No such file or directory") t)
+          "\\)\\s-*")
+  "Regular expression matching copy problems in (s)cp operations."
+  :group 'tramp
+  :type 'regexp)
+
 (defcustom tramp-process-alive-regexp
   ""
   "Regular expression indicating a process has finished.
 (defcustom tramp-process-alive-regexp
   ""
   "Regular expression indicating a process has finished.
@@ -1313,6 +1394,7 @@ corresponding PATTERN matches, the ACTION function is called."
 (defcustom tramp-actions-copy-out-of-band
   '((tramp-password-prompt-regexp tramp-action-password)
     (tramp-wrong-passwd-regexp tramp-action-permission-denied)
 (defcustom tramp-actions-copy-out-of-band
   '((tramp-password-prompt-regexp tramp-action-password)
     (tramp-wrong-passwd-regexp tramp-action-permission-denied)
+    (tramp-copy-failed-regexp tramp-action-copy-failed)
     (tramp-process-alive-regexp tramp-action-out-of-band))
   "List of pattern/action pairs.
 This list is used for copying/renaming with out-of-band methods.
     (tramp-process-alive-regexp tramp-action-out-of-band))
   "List of pattern/action pairs.
 This list is used for copying/renaming with out-of-band methods.
@@ -1358,6 +1440,9 @@ autocorrect\" to the remote host."
   (when (and (not (featurep 'xemacs))
             (memq system-type '(hpux)))
     500)
   (when (and (not (featurep 'xemacs))
             (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.
   "*If non-nil, chunksize for sending input to local process.
 It is necessary only on systems which have a buggy `process-send-string'
 implementation.  The necessity, whether this variable must be set, can be
   "*If non-nil, chunksize for sending input to local process.
 It is necessary only on systems which have a buggy `process-send-string'
 implementation.  The necessity, whether this variable must be set, can be
@@ -1392,7 +1477,7 @@ checked via the following code:
         (sit-for 30))))
 
 In the Emacs normally running Tramp, evaluate the above code
         (sit-for 30))))
 
 In the Emacs normally running Tramp, evaluate the above code
-(replace \"xxx\" and \"yyy\" by the remote user and host name,
+\(replace \"xxx\" and \"yyy\" by the remote user and host name,
 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
 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
@@ -1409,7 +1494,7 @@ in the third line of the code.
 
 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
 
 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
+\(like \"ssh\"), because setting `tramp-chunksize' to non-nil decreases
 performance.
 
 Please raise a bug report via \"M-x tramp-bug\" if your system needs
 performance.
 
 Please raise a bug report via \"M-x tramp-bug\" if your system needs
@@ -1442,7 +1527,7 @@ the visited file modtime.")
        ((fboundp 'md5-encode)
         (lambda (x) (base64-encode-string
                      (funcall (symbol-function 'md5-encode) x))))
        ((fboundp 'md5-encode)
         (lambda (x) (base64-encode-string
                      (funcall (symbol-function 'md5-encode) x))))
-       (t (error "Coulnd't find an `md5' function")))
+       (t (error "Couldn't find an `md5' function")))
   "Function to call for running the MD5 algorithm.")
 
 (defvar tramp-end-of-output
   "Function to call for running the MD5 algorithm.")
 
 (defvar tramp-end-of-output
@@ -1706,7 +1791,7 @@ on the remote host.")
 (defvar tramp-perl-encode
   "%s -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
 (defvar tramp-perl-encode
   "%s -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2006 Free Software Foundation, Inc.
 use strict;
 
 my %%trans = do {
 use strict;
 
 my %%trans = do {
@@ -1748,7 +1833,7 @@ This string is passed to `format', so percent characters need to be doubled.")
 (defvar tramp-perl-decode
   "%s -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
 (defvar tramp-perl-decode
   "%s -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2006 Free Software Foundation, Inc.
 use strict;
 
 my %%trans = do {
 use strict;
 
 my %%trans = do {
@@ -1790,8 +1875,6 @@ while (my $data = <STDIN>) {
 Escape sequence %s is replaced with name of Perl binary.
 This string is passed to `format', so percent characters need to be doubled.")
 
 Escape sequence %s is replaced with name of Perl binary.
 This string is passed to `format', so percent characters need to be doubled.")
 
-; These values conform to `file-attributes' from XEmacs 21.2.
-; GNU Emacs and other tools not checked.
 (defconst tramp-file-mode-type-map '((0  . "-")  ; Normal file (SVID-v2 and XPG2)
                                     (1  . "p")  ; fifo
                                     (2  . "c")  ; character device
 (defconst tramp-file-mode-type-map '((0  . "-")  ; Normal file (SVID-v2 and XPG2)
                                     (1  . "p")  ; fifo
                                     (2  . "c")  ; character device
@@ -1896,17 +1979,12 @@ on the FILENAME argument, even if VISIT was a string.")
   "Alist of handler functions.
 Operations not mentioned here will be handled by the normal Emacs functions.")
 
   "Alist of handler functions.
 Operations not mentioned here will be handled by the normal Emacs functions.")
 
-;; Handlers for partial tramp file names. For GNU Emacs just
-;; `file-name-all-completions' is needed. The other ones are necessary
-;; for XEmacs.
+;; Handlers for partial tramp file names.  For Emacs just
+;; `file-name-all-completions' is needed.
+;;;###autoload
 (defconst tramp-completion-file-name-handler-alist
 (defconst tramp-completion-file-name-handler-alist
-  '(
-    (file-name-directory . tramp-completion-handle-file-name-directory)
-    (file-name-nondirectory . tramp-completion-handle-file-name-nondirectory)
-    (file-exists-p . tramp-completion-handle-file-exists-p)
-    (file-name-all-completions . tramp-completion-handle-file-name-all-completions)
-    (file-name-completion . tramp-completion-handle-file-name-completion)
-    (expand-file-name . tramp-completion-handle-expand-file-name))
+  '((file-name-all-completions . tramp-completion-handle-file-name-all-completions)
+    (file-name-completion . tramp-completion-handle-file-name-completion))
   "Alist of completion handler functions.
 Used for file names matching `tramp-file-name-regexp'. Operations not
 mentioned here will be handled by `tramp-file-name-handler-alist' or the
   "Alist of completion handler functions.
 Used for file names matching `tramp-file-name-regexp'. Operations not
 mentioned here will be handled by `tramp-file-name-handler-alist' or the
@@ -1994,11 +2072,12 @@ If VAR is nil, then we bind `v' to the structure and `multi-method',
      ,@body))
 
 (put 'with-parsed-tramp-file-name 'lisp-indent-function 2)
      ,@body))
 
 (put 'with-parsed-tramp-file-name 'lisp-indent-function 2)
-;; To be activated for debugging containing this macro
-;; It works only when VAR is nil.  Otherwise, it can be deactivated by
-;; (put 'with-parsed-tramp-file-name 'edebug-form-spec 0)
-;; I'm too stupid to write a precise SPEC for it.
-(put 'with-parsed-tramp-file-name 'edebug-form-spec t)
+;; Enable debugging.
+(def-edebug-spec with-parsed-tramp-file-name (form symbolp body))
+;; Highlight as keyword.
+(when (functionp 'font-lock-add-keywords)
+  (funcall 'font-lock-add-keywords
+          'emacs-lisp-mode '("\\<with-parsed-tramp-file-name\\>")))
 
 (defmacro tramp-let-maybe (variable value &rest body)
   "Let-bind VARIABLE to VALUE in BODY, but only if VARIABLE is not obsolete.
 
 (defmacro tramp-let-maybe (variable value &rest body)
   "Let-bind VARIABLE to VALUE in BODY, but only if VARIABLE is not obsolete.
@@ -2009,6 +2088,7 @@ The intent is to protect against `obsolete variable' warnings."
      (let ((,variable ,value))
        ,@body)))
 (put 'tramp-let-maybe 'lisp-indent-function 2)
      (let ((,variable ,value))
        ,@body)))
 (put 'tramp-let-maybe 'lisp-indent-function 2)
+(put 'tramp-let-maybe 'edebug-form-spec t)
 
 ;;; Config Manipulation Functions:
 
 
 ;;; Config Manipulation Functions:
 
@@ -2140,28 +2220,11 @@ target of the symlink differ."
 ;; Localname manipulation functions that grok TRAMP localnames...
 (defun tramp-handle-file-name-directory (file)
   "Like `file-name-directory' but aware of TRAMP files."
 ;; Localname manipulation functions that grok TRAMP localnames...
 (defun tramp-handle-file-name-directory (file)
   "Like `file-name-directory' but aware of TRAMP files."
-  ;; everything except the last filename thing is the directory
+  ;; Everything except the last filename thing is the directory.
   (with-parsed-tramp-file-name file nil
   (with-parsed-tramp-file-name file nil
-    ;; For the following condition, two possibilities should be tried:
-    ;; (1) (string= localname "")
-    ;; (2) (or (string= localname "") (string= localname "/"))
-    ;; The second variant fails when completing a "/" directory on
-    ;; the remote host, that is a filename which looks like
-    ;; "/user@host:/".  But maybe wildcards fail with the first variant.
-    ;; We should do some investigation.
-    (if (string= localname "")
-       ;; For a filename like "/[foo]", we return "/".  The `else'
-       ;; case would return "/[foo]" unchanged.  But if we do that,
-       ;; then `file-expand-wildcards' ceases to work.  It's not
-       ;; quite clear to me what's the intuition that tells that this
-       ;; behavior is the right behavior, but oh, well.
-       "/"
-      ;; run the command on the localname portion only
-      ;; CCC: This should take into account the remote machine type, no?
-      ;;  --daniel <daniel@danann.net>
-      (tramp-make-tramp-file-name multi-method method user host
-                                 ;; This will not recurse...
-                                 (or (file-name-directory localname) "")))))
+    ;; Run the command on the localname portion only.
+    (tramp-make-tramp-file-name
+     multi-method method user host (file-name-directory (or localname "")))))
 
 (defun tramp-handle-file-name-nondirectory (file)
   "Like `file-name-nondirectory' but aware of TRAMP files."
 
 (defun tramp-handle-file-name-nondirectory (file)
   "Like `file-name-nondirectory' but aware of TRAMP files."
@@ -2367,8 +2430,8 @@ target of the symlink differ."
      ;; 8. File modes, as a string of ten letters or dashes as in ls -l.
      res-filemodes
      ;; 9. t iff file's gid would change if file were deleted and
      ;; 8. File modes, as a string of ten letters or dashes as in ls -l.
      res-filemodes
      ;; 9. t iff file's gid would change if file were deleted and
-     ;; recreated.
-     nil                               ;hm?
+     ;; recreated.  Will be set in `tramp-convert-file-attributes'
+     t
      ;; 10. inode number.
      res-inode
      ;; 11. Device number.  Will be replaced by a virtual device number.
      ;; 10. inode number.
      res-inode
      ;; 11. Device number.  Will be replaced by a virtual device number.
@@ -2624,9 +2687,12 @@ of."
 (defun tramp-handle-file-ownership-preserved-p (filename)
   "Like `file-ownership-preserved-p' for tramp files."
   (with-parsed-tramp-file-name filename nil
 (defun tramp-handle-file-ownership-preserved-p (filename)
   "Like `file-ownership-preserved-p' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (or (not (file-exists-p filename))
-       ;; Existing files must be writable.
-       (zerop (tramp-run-test "-O" filename)))))
+    (let ((attributes (file-attributes filename)))
+      ;; Return t if the file doesn't exist, since it's true that no
+      ;; information would be lost by an (attempted) delete and create.
+      (or (null attributes)
+         (= (nth 2 attributes)
+            (tramp-get-remote-uid multi-method method user host))))))
 
 ;; Other file name ops.
 
 
 ;; Other file name ops.
 
@@ -2801,17 +2867,18 @@ of."
 
 
 ;; The following isn't needed for Emacs 20 but for 19.34?
 
 
 ;; The following isn't needed for Emacs 20 but for 19.34?
-(defun tramp-handle-file-name-completion (filename directory)
+(defun tramp-handle-file-name-completion
+  (filename directory &optional predicate)
   "Like `file-name-completion' for tramp files."
   (unless (tramp-tramp-file-p directory)
     (error
      "tramp-handle-file-name-completion invoked on non-tramp directory `%s'"
      directory))
   "Like `file-name-completion' for tramp files."
   (unless (tramp-tramp-file-p directory)
     (error
      "tramp-handle-file-name-completion invoked on non-tramp directory `%s'"
      directory))
-  (with-parsed-tramp-file-name directory nil
-    (try-completion
-     filename
-     (mapcar (lambda (x) (cons x nil))
-            (file-name-all-completions filename directory)))))
+  (try-completion
+   filename
+   (mapcar 'list (file-name-all-completions filename directory))
+   (when predicate
+     (lambda (x) (funcall predicate (expand-file-name (car x) directory))))))
 
 ;; cp, mv and ln
 
 
 ;; cp, mv and ln
 
@@ -2894,7 +2961,7 @@ and `rename'.  FILENAME and NEWNAME must be absolute file names."
   (unless ok-if-already-exists
     (when (file-exists-p newname)
       (signal 'file-already-exists
   (unless ok-if-already-exists
     (when (file-exists-p newname)
       (signal 'file-already-exists
-              (list newname))))
+              (list "File already exists" newname))))
   (let ((t1 (tramp-tramp-file-p filename))
        (t2 (tramp-tramp-file-p newname))
        v1-multi-method v1-method v1-user v1-host v1-localname
   (let ((t1 (tramp-tramp-file-p filename))
        (t2 (tramp-tramp-file-p newname))
        v1-multi-method v1-method v1-user v1-host v1-localname
@@ -2967,10 +3034,10 @@ and `rename'.  FILENAME and NEWNAME must be absolute file names."
       ;; copy-program can be invoked.
       (if (and (not v1-multi-method)
               (not v2-multi-method)
       ;; copy-program can be invoked.
       (if (and (not v1-multi-method)
               (not v2-multi-method)
-              (or (tramp-method-out-of-band-p
-                   v1-multi-method v1-method v1-user v1-host)
-                  (tramp-method-out-of-band-p
-                   v2-multi-method v2-method v2-user v2-host)))
+              (or (and t1 (tramp-method-out-of-band-p
+                            v1-multi-method v1-method v1-user v1-host))
+                  (and t2 (tramp-method-out-of-band-p
+                            v2-multi-method v2-method v2-user v2-host))))
          (tramp-do-copy-or-rename-file-out-of-band
           op filename newname keep-date)
        ;; Use the generic method via a Tramp buffer.
          (tramp-do-copy-or-rename-file-out-of-band
           op filename newname keep-date)
        ;; Use the generic method via a Tramp buffer.
@@ -3131,6 +3198,14 @@ be a local filename.  The method used must be an out-of-band method."
              v2-user v2-host
              (tramp-shell-quote-argument v2-localname))))
 
              v2-user v2-host
              (tramp-shell-quote-argument v2-localname))))
 
+    ;; Handle ControlMaster/ControlPath
+    (setq copy-args
+         (mapcar
+          (lambda (x)
+            (format-spec
+             x `((?t . ,(format "/tmp/%s" tramp-temp-name-prefix)))))
+          copy-args))
+
     ;; Handle keep-date argument
     (when keep-date
       (if t1
     ;; Handle keep-date argument
     (when keep-date
       (if t1
@@ -3165,12 +3240,13 @@ be a local filename.  The method used must be an out-of-band method."
       (message "Transferring %s to %s..." filename newname)
 
       ;; Use rcp-like program for file transfer.
       (message "Transferring %s to %s..." filename newname)
 
       ;; Use rcp-like program for file transfer.
-      (let ((p (apply 'start-process (buffer-name trampbuf) trampbuf
-                     copy-program copy-args)))
-       (tramp-set-process-query-on-exit-flag p nil)
-       (tramp-process-actions p multi-method method user host
-                              tramp-actions-copy-out-of-band))
-      (kill-buffer trampbuf)
+      (unwind-protect
+          (let ((p (apply 'start-process (buffer-name trampbuf) trampbuf
+                          copy-program copy-args)))
+            (tramp-set-process-query-on-exit-flag p nil)
+            (tramp-process-actions p multi-method method user host
+                                   tramp-actions-copy-out-of-band))
+        (kill-buffer trampbuf))
       (message "Transferring %s to %s...done" filename newname)
 
       ;; Set the mode.
       (message "Transferring %s to %s...done" filename newname)
 
       ;; Set the mode.
@@ -3484,6 +3560,17 @@ the result will be a local, non-Tramp, filename."
        (when (string-match "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
          (let ((uname (match-string 1 localname))
                (fname (match-string 2 localname)))
        (when (string-match "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
          (let ((uname (match-string 1 localname))
                (fname (match-string 2 localname)))
+           ;; We cannot simply apply "~/", because under sudo "~/" is
+           ;; expanded to the local user home directory but to the
+           ;; root home directory.  On the other hand, using always
+           ;; the default user name for tilde expansion is not
+           ;; appropriate either, because ssh and companions might
+           ;; use a user name from the config file.
+           (when (and (string-equal uname "~")
+                      (string-match
+                       "\\`su\\(do\\)?\\'"
+                       (tramp-find-method multi-method method user host)))
+             (setq uname (concat uname (or user "root"))))
            ;; CCC fanatic error checking?
            (set-buffer (tramp-get-buffer multi-method method user host))
            (erase-buffer)
            ;; CCC fanatic error checking?
            (set-buffer (tramp-get-buffer multi-method method user host))
            (erase-buffer)
@@ -3496,17 +3583,24 @@ the result will be a local, non-Tramp, filename."
            (setq uname (buffer-substring (point) (tramp-line-end-position)))
            (setq localname (concat uname fname))
            (erase-buffer)))
            (setq uname (buffer-substring (point) (tramp-line-end-position)))
            (setq localname (concat uname fname))
            (erase-buffer)))
+       ;; There might be a double slash, for example when "~/"
+       ;; expands to "/". Remove this.
+       (while (string-match "//" localname)
+         (setq localname (replace-match "/" t t localname)))
        ;; No tilde characters in file name, do normal
        ;; expand-file-name (this does "/./" and "/../").  We bind
        ;; No tilde characters in file name, do normal
        ;; expand-file-name (this does "/./" and "/../").  We bind
-       ;; directory-sep-char here for XEmacs on Windows, which
-       ;; would otherwise use backslash.
+       ;; directory-sep-char here for XEmacs on Windows, which would
+       ;; otherwise use backslash.  `default-directory' is bound to
+       ;; "/", because on Windows there would be problems with UNC
+       ;; shares or Cygwin mounts.
        (tramp-let-maybe directory-sep-char ?/
        (tramp-let-maybe directory-sep-char ?/
-         (tramp-make-tramp-file-name
-          multi-method (or method (tramp-find-default-method user host))
-          user host
-          (tramp-drop-volume-letter
-           (tramp-run-real-handler 'expand-file-name
-                                   (list localname)))))))))
+         (let ((default-directory "/"))
+           (tramp-make-tramp-file-name
+            multi-method (or method (tramp-find-default-method user host))
+            user host
+            (tramp-drop-volume-letter
+             (tramp-run-real-handler 'expand-file-name
+                                     (list localname))))))))))
 
 ;; old version follows.  it uses ".." to cross file handler
 ;; boundaries.
 
 ;; old version follows.  it uses ".." to cross file handler
 ;; boundaries.
@@ -3531,6 +3625,10 @@ the result will be a local, non-Tramp, filename."
   "Global variable keeping asynchronous process object.
 Used in `tramp-handle-shell-command'")
 
   "Global variable keeping asynchronous process object.
 Used in `tramp-handle-shell-command'")
 
+(defvar tramp-display-shell-command-buffer t
+  "Whether to display output buffer of `shell-command'.
+This is necessary for handling DISPLAY of `process-file'.")
+
 (defun tramp-handle-shell-command (command &optional output-buffer error-buffer)
   "Like `shell-command' for tramp files.
 This will break if COMMAND prints a newline, followed by the value of
 (defun tramp-handle-shell-command (command &optional output-buffer error-buffer)
   "Like `shell-command' for tramp files.
 This will break if COMMAND prints a newline, followed by the value of
@@ -3539,7 +3637,8 @@ This will break if COMMAND prints a newline, followed by the value of
   ;; for `find-grep-dired' and `find-name-dired' in Emacs 22.
   (if (tramp-tramp-file-p default-directory)
       (with-parsed-tramp-file-name default-directory nil
   ;; for `find-grep-dired' and `find-name-dired' in Emacs 22.
   (if (tramp-tramp-file-p default-directory)
       (with-parsed-tramp-file-name default-directory nil
-       (let ((asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
+       (let ((curbuf (current-buffer))
+             (asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
              status)
          (unless output-buffer
            (setq output-buffer
              status)
          (unless output-buffer
            (setq output-buffer
@@ -3639,7 +3738,9 @@ This will break if COMMAND prints a newline, followed by the value of
              (skip-chars-forward "^ ")
              (setq status (read (current-buffer)))))
          (unless (zerop (buffer-size))
              (skip-chars-forward "^ ")
              (setq status (read (current-buffer)))))
          (unless (zerop (buffer-size))
-           (display-buffer output-buffer))
+           (when tramp-display-shell-command-buffer
+             (display-buffer output-buffer)))
+         (set-buffer curbuf)
          status))
     ;; The following is only executed if something strange was
     ;; happening.  Emit a helpful message and do it anyway.
          status))
     ;; The following is only executed if something strange was
     ;; happening.  Emit a helpful message and do it anyway.
@@ -3654,11 +3755,10 @@ This will break if COMMAND prints a newline, followed by the value of
   (when (and (numberp buffer) (zerop buffer))
     (error "Implementation does not handle immediate return"))
   (when (consp buffer) (error "Implementation does not handle error files"))
   (when (and (numberp buffer) (zerop buffer))
     (error "Implementation does not handle immediate return"))
   (when (consp buffer) (error "Implementation does not handle error files"))
-  (shell-command
-   (mapconcat 'tramp-shell-quote-argument
-              (cons program args)
-              " ")
-   buffer))
+  (let ((tramp-display-shell-command-buffer display))
+    (shell-command
+     (mapconcat 'tramp-shell-quote-argument (cons program args) " ")
+     buffer)))
 
 ;; File Editing.
 
 
 ;; File Editing.
 
@@ -3853,37 +3953,50 @@ This will break if COMMAND prints a newline, followed by the value of
 (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."
 (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."
-  (when tramp-auto-save-directory
-    (unless (file-exists-p tramp-auto-save-directory)
-      (make-directory tramp-auto-save-directory t)))
-  ;; jka-compr doesn't like auto-saving, so by appending "~" to the
-  ;; file name we make sure that jka-compr isn't used for the
-  ;; auto-save file.
-  (let ((buffer-file-name
-        (if tramp-auto-save-directory
-            (expand-file-name
-             (tramp-subst-strs-in-string
-              '(("_" . "|")
-                ("/" . "_a")
-                (":" . "_b")
-                ("|" . "__")
-                ("[" . "_l")
-                ("]" . "_r"))
-              (buffer-file-name))
-             tramp-auto-save-directory)
-          (buffer-file-name))))
-    ;; 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)))))
+  (let ((tramp-auto-save-directory tramp-auto-save-directory))
+    ;; 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)
+      (mapcar
+       '(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 temporary-file-directory))))
+       (symbol-value 'auto-save-file-name-transforms)))
+    ;; Create directory.
+    (when tramp-auto-save-directory
+      (unless (file-exists-p tramp-auto-save-directory)
+       (make-directory tramp-auto-save-directory t)))
+    ;; jka-compr doesn't like auto-saving, so by appending "~" to the
+    ;; file name we make sure that jka-compr isn't used for the
+    ;; auto-save file.
+    (let ((buffer-file-name
+          (if tramp-auto-save-directory
+              (expand-file-name
+               (tramp-subst-strs-in-string
+                '(("_" . "|")
+                  ("/" . "_a")
+                  (":" . "_b")
+                  ("|" . "__")
+                  ("[" . "_l")
+                  ("]" . "_r"))
+                (buffer-file-name))
+               tramp-auto-save-directory)
+            (buffer-file-name))))
+      ;; Run plain `make-auto-save-file-name'.  There might be an advice when
+      ;; it is not a magic file name operation (since Emacs 22).
+      ;; We must deactivate it temporarily.
+      (if (not (ad-is-active 'make-auto-save-file-name))
+         (tramp-run-real-handler
+          'make-auto-save-file-name nil)
+       ;; else
+       (ad-deactivate 'make-auto-save-file-name)
+       (prog1
+           (tramp-run-real-handler
+            'make-auto-save-file-name nil)
+         (ad-activate 'make-auto-save-file-name))))))
 
 
 ;; CCC grok APPEND, LOCKNAME, CONFIRM
 
 
 ;; CCC grok APPEND, LOCKNAME, CONFIRM
@@ -4087,7 +4200,8 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
 ;;         (inhibit-file-name-operation operation))
 ;;     (apply operation args)))
 
 ;;         (inhibit-file-name-operation operation))
 ;;     (apply operation args)))
 
-(defun tramp-run-real-handler (operation args)
+;;;###autoload
+(progn (defun tramp-run-real-handler (operation args)
   "Invoke normal file name handler for OPERATION.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
   "Invoke normal file name handler for OPERATION.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
@@ -4100,13 +4214,14 @@ pass to the OPERATION."
            ,(and (eq inhibit-file-name-operation operation)
                  inhibit-file-name-handlers)))
         (inhibit-file-name-operation operation))
            ,(and (eq inhibit-file-name-operation operation)
                  inhibit-file-name-handlers)))
         (inhibit-file-name-operation operation))
-    (apply operation args)))
+    (apply operation args))))
 
 ;; This function is used from `tramp-completion-file-name-handler' functions
 ;; only, if `tramp-completion-mode' is true. But this cannot be checked here
 ;; because the check is based on a full filename, not available for all
 ;; basic I/O operations.
 
 ;; This function is used from `tramp-completion-file-name-handler' functions
 ;; only, if `tramp-completion-mode' is true. But this cannot be checked here
 ;; because the check is based on a full filename, not available for all
 ;; basic I/O operations.
-(defun tramp-completion-run-real-handler (operation args)
+;;;###autoload
+(progn (defun tramp-completion-run-real-handler (operation args)
   "Invoke `tramp-file-name-handler' for OPERATION.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
   "Invoke `tramp-file-name-handler' for OPERATION.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
@@ -4118,7 +4233,7 @@ pass to the OPERATION."
            ,(and (eq inhibit-file-name-operation operation)
                  inhibit-file-name-handlers)))
         (inhibit-file-name-operation operation))
            ,(and (eq inhibit-file-name-operation operation)
                  inhibit-file-name-handlers)))
         (inhibit-file-name-operation operation))
-    (apply operation args)))
+    (apply operation args))))
 
 ;; We handle here all file primitives.  Most of them have the file
 ;; name as first parameter; nevertheless we check for them explicitly
 
 ;; We handle here all file primitives.  Most of them have the file
 ;; name as first parameter; nevertheless we check for them explicitly
@@ -4215,12 +4330,25 @@ ARGS are the arguments OPERATION has been called with."
 (defun tramp-file-name-handler (operation &rest args)
   "Invoke Tramp file name handler.
 Falls back to normal file name handler if no tramp file name handler exists."
 (defun tramp-file-name-handler (operation &rest args)
   "Invoke Tramp file name handler.
 Falls back to normal file name handler if no tramp file name handler exists."
+;;  (setq edebug-trace t)
+;;  (edebug-trace "%s" (with-output-to-string (backtrace)))
   (save-match-data
     (let* ((filename (apply 'tramp-file-name-for-operation operation args))
   (save-match-data
     (let* ((filename (apply 'tramp-file-name-for-operation operation args))
+          (completion (tramp-completion-mode filename))
           (foreign (tramp-find-foreign-file-name-handler filename)))
           (foreign (tramp-find-foreign-file-name-handler filename)))
-      (cond
-       (foreign (apply foreign operation args))
-       (t (tramp-run-real-handler operation args))))))
+      (with-parsed-tramp-file-name filename nil
+       (cond
+        ;; When we are in completion mode, some operations shouldn' be
+        ;; handled by backend.
+        ((and completion (memq operation '(expand-file-name)))
+         (tramp-run-real-handler operation args))
+        ((and completion (zerop (length localname))
+              (memq operation '(file-exists-p file-directory-p)))
+         t)
+        ;; Call the backend function.
+        (foreign (apply foreign operation args))
+        ;; Nothing to do for us.
+        (t (tramp-run-real-handler operation args)))))))
 
 
 ;; In Emacs, there is some concurrency due to timers.  If a timer
 
 
 ;; In Emacs, there is some concurrency due to timers.  If a timer
@@ -4268,38 +4396,56 @@ Fall back to normal file name handler if no Tramp handler exists."
       (setq tramp-locked tl))))
 
 ;;;###autoload
       (setq tramp-locked tl))))
 
 ;;;###autoload
-(defun tramp-completion-file-name-handler (operation &rest args)
+(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."
   "Invoke tramp file name completion handler.
 Falls back to normal file name handler if no tramp file name handler exists."
-;;   (setq tramp-debug-buffer t)
-;;   (tramp-message 1 "%s %s" operation args)
-;;   (tramp-message 1 "%s %s\n%s"
-;;              operation args (with-output-to-string (backtrace)))
+;;  (setq edebug-trace t)
+;;  (edebug-trace "%s" (with-output-to-string (backtrace)))
   (let ((fn (assoc operation tramp-completion-file-name-handler-alist)))
     (if fn
        (save-match-data (apply (cdr fn) args))
   (let ((fn (assoc operation tramp-completion-file-name-handler-alist)))
     (if fn
        (save-match-data (apply (cdr fn) args))
-      (tramp-completion-run-real-handler operation args))))
+      (tramp-completion-run-real-handler operation args)))))
 
 ;;;###autoload
 
 ;;;###autoload
-(put 'tramp-completion-file-name-handler 'safe-magic t)
-
-;; Register in file name handler alist
-;;;###autoload
-(add-to-list 'file-name-handler-alist
-            (cons tramp-file-name-regexp 'tramp-file-name-handler))
-(add-to-list 'file-name-handler-alist
-            (cons tramp-completion-file-name-regexp
-                  'tramp-completion-file-name-handler))
-
-(defun tramp-repair-jka-compr ()
-  "If jka-compr is already loaded, move it to the front of
-`file-name-handler-alist'.  On Emacs 22 or so this will not be
-necessary anymore."
+(defsubst tramp-register-file-name-handlers ()
+  "Add tramp file name handlers to `file-name-handler-alist'."
+  (add-to-list 'file-name-handler-alist
+              (cons tramp-file-name-regexp 'tramp-file-name-handler))
+  ;; `partial-completion-mode' is unknown in XEmacs.  So we should
+  ;; load it unconditionally there.  In the GNU Emacs case, method/
+  ;; user/host name completion shall be bound to `partial-completion-mode'.
+  (when (or (not (boundp 'partial-completion-mode))
+           (symbol-value 'partial-completion-mode)
+           (featurep 'ido))
+    (add-to-list 'file-name-handler-alist
+                (cons tramp-completion-file-name-regexp
+                      'tramp-completion-file-name-handler))
+    (put 'tramp-completion-file-name-handler 'safe-magic t))
+  ;; If jka-compr is already loaded, move it to the front of
+  ;; `file-name-handler-alist'.
   (let ((jka (rassoc 'jka-compr-handler file-name-handler-alist)))
     (when jka
       (setq file-name-handler-alist
            (cons jka (delete jka file-name-handler-alist))))))
   (let ((jka (rassoc 'jka-compr-handler file-name-handler-alist)))
     (when jka
       (setq file-name-handler-alist
            (cons jka (delete jka file-name-handler-alist))))))
-(tramp-repair-jka-compr)
+
+;; During autoload, it shall be checked whether
+;; `partial-completion-mode' is active.  Therefore registering will be
+;; delayed.
+;;;###autoload(add-hook
+;;;###autoload 'after-init-hook
+;;;###autoload '(lambda () (tramp-register-file-name-handlers)))
+(tramp-register-file-name-handlers)
+
+;;;###autoload
+(defun tramp-unload-file-name-handlers ()
+  (setq file-name-handler-alist
+       (delete (rassoc 'tramp-file-name-handler
+                       file-name-handler-alist)
+               (delete (rassoc 'tramp-completion-file-name-handler
+                               file-name-handler-alist)
+                       file-name-handler-alist))))
+
+(add-hook 'tramp-unload-hook 'tramp-unload-file-name-handlers)
 
 
 ;;; Interactions with other packages:
 
 
 ;;; Interactions with other packages:
@@ -4350,25 +4496,22 @@ necessary anymore."
                 (read (current-buffer))))))
        (list (expand-file-name name))))))
 
                 (read (current-buffer))))))
        (list (expand-file-name name))))))
 
-;; Check for complete.el and override PC-expand-many-files if appropriate.
-(eval-and-compile
-  (defun tramp-save-PC-expand-many-files (name))); avoid compiler warning
-
-(defun tramp-setup-complete ()
-  (fset 'tramp-save-PC-expand-many-files
-        (symbol-function 'PC-expand-many-files))
-  (defun PC-expand-many-files (name)
-    (if (tramp-tramp-file-p name)
-        (funcall (symbol-function 'expand-many-files) name)
-      (tramp-save-PC-expand-many-files name))))
-
-;; Why isn't eval-after-load sufficient?
-(if (fboundp 'PC-expand-many-files)
-    (tramp-setup-complete)
-  (eval-after-load "complete" '(tramp-setup-complete)))
+(eval-after-load "complete"
+  '(progn
+     (defadvice PC-expand-many-files
+       (around tramp-advice-PC-expand-many-files (name) activate)
+       "Invoke `tramp-handle-expand-many-files' for tramp files."
+       (if (tramp-tramp-file-p name)
+          (setq ad-return-value (tramp-handle-expand-many-files name))
+        ad-do-it))
+     (add-hook 'tramp-unload-hook
+              '(lambda () (ad-unadvise 'PC-expand-many-files)))))
 
 ;;; File name handler functions for completion mode
 
 
 ;;; File name handler functions for completion mode
 
+(defvar tramp-completion-mode nil
+  "If non-nil, we are in file name completion mode.")
+
 ;; Necessary because `tramp-file-name-regexp-unified' and
 ;; `tramp-completion-file-name-regexp-unified' aren't different.
 ;; If nil, `tramp-completion-run-real-handler' is called (i.e. forwarding to
 ;; Necessary because `tramp-file-name-regexp-unified' and
 ;; `tramp-completion-file-name-regexp-unified' aren't different.
 ;; If nil, `tramp-completion-run-real-handler' is called (i.e. forwarding to
@@ -4384,7 +4527,7 @@ necessary anymore."
 (defun tramp-completion-mode (file)
   "Checks whether method / user name / host name completion is active."
   (cond
 (defun tramp-completion-mode (file)
   "Checks whether method / user name / host name completion is active."
   (cond
-   ((not tramp-unified-filenames) t)
+   (tramp-completion-mode t)
    ((string-match "^/.*:.*:$" file) nil)
    ((string-match
      (concat tramp-prefix-regexp
    ((string-match "^/.*:.*:$" file) nil)
    ((string-match
      (concat tramp-prefix-regexp
@@ -4392,118 +4535,117 @@ necessary anymore."
      file)
     (member (match-string 1 file) (mapcar 'car tramp-methods)))
    ((or (equal last-input-event 'tab)
      file)
     (member (match-string 1 file) (mapcar 'car tramp-methods)))
    ((or (equal last-input-event 'tab)
-       ;; Emacs
-       (and (integerp last-input-event)
-            (not (event-modifiers last-input-event))
-            (or (char-equal last-input-event ?\?)
-                (char-equal last-input-event ?\t) ; handled by 'tab already?
-                (char-equal last-input-event ?\ )))
+       ;; Emacs
+       (and (wholenump last-input-event)
+            (or
+             ;; ?\t has event-modifier 'control
+             (char-equal last-input-event ?\t)
+             (and (not (event-modifiers last-input-event))
+                  (or (char-equal last-input-event ?\?)
+                      (char-equal last-input-event ?\ )))))
        ;; XEmacs
        (and (featurep 'xemacs)
        ;; XEmacs
        (and (featurep 'xemacs)
-            (not (event-modifiers last-input-event))
-            (or (char-equal
-                 (funcall (symbol-function 'event-to-character)
-                          last-input-event) ?\?)
-                (char-equal
-                 (funcall (symbol-function 'event-to-character)
-                          last-input-event) ?\t)
-                (char-equal
-                 (funcall (symbol-function 'event-to-character)
-                          last-input-event) ?\ ))))
+            (or
+             ;; ?\t has event-modifier 'control
+             (char-equal
+              (funcall (symbol-function 'event-to-character)
+                       last-input-event) ?\t)
+             (and (not (event-modifiers last-input-event))
+                  (or (char-equal
+                       (funcall (symbol-function 'event-to-character)
+                                last-input-event) ?\?)
+                      (char-equal
+                       (funcall (symbol-function 'event-to-character)
+                                last-input-event) ?\ ))))))
     t)))
 
     t)))
 
-(defun tramp-completion-handle-file-exists-p (filename)
-  "Like `file-exists-p' for tramp files."
-  (if (tramp-completion-mode filename)
-      (tramp-run-real-handler
-       'file-exists-p (list filename))
-    (tramp-completion-run-real-handler
-     'file-exists-p (list filename))))
-
-;; Localname manipulation in case of partial TRAMP file names.
-(defun tramp-completion-handle-file-name-directory (file)
-  "Like `file-name-directory' but aware of TRAMP files."
-  (if (tramp-completion-mode file)
-      "/"
-    (tramp-completion-run-real-handler
-     'file-name-directory (list file))))
-
-;; Localname manipulation in case of partial TRAMP file names.
-(defun tramp-completion-handle-file-name-nondirectory (file)
-  "Like `file-name-nondirectory' but aware of TRAMP files."
-  (substring
-   file (length (tramp-completion-handle-file-name-directory file))))
-
 ;; Method, host name and user name completion.
 ;; `tramp-completion-dissect-file-name' returns a list of
 ;; tramp-file-name structures. For all of them we return possible completions.
 ;; Method, host name and user name completion.
 ;; `tramp-completion-dissect-file-name' returns a list of
 ;; tramp-file-name structures. For all of them we return possible completions.
+;;;###autoload
 (defun tramp-completion-handle-file-name-all-completions (filename directory)
   "Like `file-name-all-completions' for partial tramp files."
 
 (defun tramp-completion-handle-file-name-all-completions (filename directory)
   "Like `file-name-all-completions' for partial tramp files."
 
-  (let*
-      ((fullname (concat directory filename))
-       ;; local files
-       (result
-       (if (tramp-completion-mode fullname)
-           (tramp-run-real-handler
-            'file-name-all-completions (list filename directory))
-         (tramp-completion-run-real-handler
-          'file-name-all-completions (list filename directory))))
-       ;; possible completion structures
-       (v (tramp-completion-dissect-file-name fullname)))
-
-    (while v
-      (let* ((car (car v))
-            (multi-method (tramp-file-name-multi-method car))
-            (method (tramp-file-name-method car))
-            (user (tramp-file-name-user car))
-            (host (tramp-file-name-host car))
-            (localname (tramp-file-name-localname car))
-            (m (tramp-find-method multi-method method user host))
-            (tramp-current-user user) ; see `tramp-parse-passwd'
-            all-user-hosts)
-
-       (unless (or multi-method ;; Not handled (yet).
-                   localname)        ;; Nothing to complete
-
-         (if (or user host)
-
-           ;; Method dependent user / host combinations
-           (progn
-             (mapcar
-              (lambda (x)
-                (setq all-user-hosts
-                      (append all-user-hosts
-                              (funcall (nth 0 x) (nth 1 x)))))
-              (tramp-get-completion-function m))
-
-             (setq result (append result
-               (mapcar
-                (lambda (x)
-                  (tramp-get-completion-user-host
-                   method user host (nth 0 x) (nth 1 x)))
-                (delq nil all-user-hosts)))))
-
-           ;; Possible methods
-           (setq result
-                 (append result (tramp-get-completion-methods m)))))
-
-      (setq v (delq car v))))
-
-    ;;; unify list, remove nil elements
-    (let (result1)
-      (while result
-       (let ((car (car result)))
-         (when car (add-to-list 'result1 car))
-         (setq result (delq car result))))
-
-      result1)))
+  (unwind-protect
+      ;; We need to reset `tramp-completion-mode'.
+      (progn
+       (setq tramp-completion-mode t)
+       (let*
+           ((fullname (concat directory filename))
+            ;; possible completion structures
+            (v (tramp-completion-dissect-file-name fullname))
+            result result1)
+
+         (while v
+           (let* ((car (car v))
+                  (multi-method (tramp-file-name-multi-method car))
+                  (method (tramp-file-name-method car))
+                  (user (tramp-file-name-user car))
+                  (host (tramp-file-name-host car))
+                  (localname (tramp-file-name-localname car))
+                  (m (tramp-find-method multi-method method user host))
+                  (tramp-current-user user) ; see `tramp-parse-passwd'
+                  all-user-hosts)
+
+             (unless (or multi-method ;; Not handled (yet).
+                         localname)   ;; Nothing to complete
+
+               (if (or user host)
+
+                   ;; Method dependent user / host combinations
+                   (progn
+                     (mapcar
+                      (lambda (x)
+                        (setq all-user-hosts
+                              (append all-user-hosts
+                                      (funcall (nth 0 x) (nth 1 x)))))
+                      (tramp-get-completion-function m))
+
+                     (setq result (append result
+                       (mapcar
+                        (lambda (x)
+                          (tramp-get-completion-user-host
+                           method user host (nth 0 x) (nth 1 x)))
+                        (delq nil all-user-hosts)))))
+
+                 ;; Possible methods
+                 (setq result
+                       (append result (tramp-get-completion-methods m)))))
+
+             (setq v (cdr v))))
+
+         ;; unify list, remove nil elements
+         (while result
+           (let ((car (car result)))
+             (when car (add-to-list
+                        'result1 (substring car (length directory))))
+             (setq result (cdr result))))
+
+         ;; Complete local parts
+         (append
+          result1
+          (condition-case nil
+              (if result1
+                  ;; "/ssh:" does not need to be expanded as hostname.
+                  (tramp-run-real-handler
+                   'file-name-all-completions (list filename directory))
+                ;; No method/user/host found to be expanded.
+                (tramp-completion-run-real-handler
+                 'file-name-all-completions (list filename directory)))
+            (error nil)))))
+    ;; unwindform
+    (setq tramp-completion-mode nil)))
 
 ;; Method, host name and user name completion for a file.
 
 ;; Method, host name and user name completion for a file.
-(defun tramp-completion-handle-file-name-completion (filename directory)
+;;;###autoload
+(defun tramp-completion-handle-file-name-completion
+  (filename directory &optional predicate)
   "Like `file-name-completion' for tramp files."
   "Like `file-name-completion' for tramp files."
-  (try-completion filename
-   (mapcar 'list (file-name-all-completions filename directory))))
+  (try-completion
+   filename
+   (mapcar 'list (file-name-all-completions filename directory))
+   (when predicate
+     (lambda (x) (funcall predicate (expand-file-name (car x) directory))))))
 
 ;; I misuse a little bit the tramp-file-name structure in order to handle
 ;; completion possibilities for partial methods / user names / host names.
 
 ;; I misuse a little bit the tramp-file-name structure in order to handle
 ;; completion possibilities for partial methods / user names / host names.
@@ -4626,8 +4768,7 @@ remote host and localname (filename on remote host)."
    (lambda (method)
      (and method
          (string-match (concat "^" (regexp-quote partial-method)) method)
    (lambda (method)
      (and method
          (string-match (concat "^" (regexp-quote partial-method)) method)
-         ;; we must remove leading "/".
-         (substring (tramp-make-tramp-file-name nil method nil nil nil) 1)))
+         (tramp-make-tramp-file-name nil method nil nil nil)))
    (delete "multi" (mapcar 'car tramp-methods))))
 
 ;; Compares partial user and host names with possible completions.
    (delete "multi" (mapcar 'car tramp-methods))))
 
 ;; Compares partial user and host names with possible completions.
@@ -4660,8 +4801,7 @@ PARTIAL-USER must match USER, PARTIAL-HOST must match HOST."
            host nil)))
 
   (unless (zerop (+ (length user) (length host)))
            host nil)))
 
   (unless (zerop (+ (length user) (length host)))
-    ;; we must remove leading "/".
-    (substring (tramp-make-tramp-file-name nil method user host nil) 1)))
+    (tramp-make-tramp-file-name nil method user host nil)))
 
 (defun tramp-parse-rhosts (filename)
   "Return a list of (user host) tuples allowed to access.
 
 (defun tramp-parse-rhosts (filename)
   "Return a list of (user host) tuples allowed to access.
@@ -4880,15 +5020,6 @@ User may be nil."
      (forward-line 1)
      result))
 
      (forward-line 1)
      result))
 
-(defun tramp-completion-handle-expand-file-name (name &optional dir)
-  "Like `expand-file-name' for tramp files."
-  (let ((fullname (concat (or dir default-directory) name)))
-    (if (tramp-completion-mode fullname)
-       (tramp-run-real-handler
-        'expand-file-name (list name dir))
-      (tramp-completion-run-real-handler
-       'expand-file-name (list name dir)))))
-
 ;;; Internal Functions:
 
 (defun tramp-maybe-send-perl-script (multi-method method user host script name)
 ;;; Internal Functions:
 
 (defun tramp-maybe-send-perl-script (multi-method method user host script name)
@@ -4923,6 +5054,9 @@ Function may have 0-3 parameters."
              auto-save-default)
     (auto-save-mode 1)))
 (add-hook 'find-file-hooks 'tramp-set-auto-save t)
              auto-save-default)
     (auto-save-mode 1)))
 (add-hook 'find-file-hooks 'tramp-set-auto-save t)
+(add-hook 'tramp-unload-hook
+         '(lambda ()
+            (remove-hook 'find-file-hooks 'tramp-set-auto-save)))
 
 (defun tramp-run-test (switch filename)
   "Run `test' on the remote system, given a SWITCH and a FILENAME.
 
 (defun tramp-run-test (switch filename)
   "Run `test' on the remote system, given a SWITCH and a FILENAME.
@@ -4971,15 +5105,26 @@ hosts, or files, disagree."
 (defun tramp-touch (file time)
   "Set the last-modified timestamp of the given file.
 TIME is an Emacs internal time value as returned by `current-time'."
 (defun tramp-touch (file time)
   "Set the last-modified timestamp of the given file.
 TIME is an Emacs internal time value as returned by `current-time'."
-  (let ((touch-time (format-time-string "%Y%m%d%H%M.%S" time)))
+  (let* ((utc
+         ;; With GNU Emacs, `format-time-string' has an optional
+         ;; parameter UNIVERSAL.  This is preferred.
+         (and (functionp 'subr-arity)
+              (= 3 (cdr (funcall (symbol-function 'subr-arity)
+                                 (symbol-function 'format-time-string))))))
+        (touch-time
+         (if utc
+             (format-time-string "%Y%m%d%H%M.%S" time t)
+           (format-time-string "%Y%m%d%H%M.%S" time))))
     (if (tramp-tramp-file-p file)
        (with-parsed-tramp-file-name file nil
          (let ((buf (tramp-get-buffer multi-method method user host)))
            (unless (zerop (tramp-send-command-and-check
                            multi-method method user host
     (if (tramp-tramp-file-p file)
        (with-parsed-tramp-file-name file nil
          (let ((buf (tramp-get-buffer multi-method method user host)))
            (unless (zerop (tramp-send-command-and-check
                            multi-method method user host
-                           (format "touch -t %s %s"
+                           (format "%s touch -t %s %s"
+                                   (if utc "TZ=UTC; export TZ;" "")
                                    touch-time
                                    touch-time
-                                   localname)))
+                                   (tramp-shell-quote-argument localname))
+                           t))
              (pop-to-buffer buf)
              (error "tramp-touch: touch failed, see buffer `%s' for details"
                     buf))))
              (pop-to-buffer buf)
              (error "tramp-touch: touch failed, see buffer `%s' for details"
                     buf))))
@@ -5288,6 +5433,11 @@ Returns nil if none was found, else the command is returned."
   (kill-process p)
   (throw 'tramp-action 'permission-denied))
 
   (kill-process p)
   (throw 'tramp-action 'permission-denied))
 
+(defun tramp-action-copy-failed (p multi-method method user host)
+  "Signal copy failed."
+  (kill-process p)
+  (error "%s" (match-string 1)))
+
 (defun tramp-action-yesno (p multi-method method user host)
   "Ask the user for confirmation using `yes-or-no-p'.
 Send \"yes\" to remote process on confirmation, abort otherwise.
 (defun tramp-action-yesno (p multi-method method user host)
   "Ask the user for confirmation using `yes-or-no-p'.
 Send \"yes\" to remote process on confirmation, abort otherwise.
@@ -5408,6 +5558,7 @@ The terminal type can be configured with `tramp-terminal-type'."
 
 (defun tramp-process-actions (p multi-method method user host actions)
   "Perform actions until success."
 
 (defun tramp-process-actions (p multi-method method user host actions)
   "Perform actions until success."
+  (tramp-message 10 "%s" (mapconcat 'identity (process-command p) " "))
   (let (exit)
     (while (not exit)
       (tramp-message 9 "Waiting for prompts from remote shell")
   (let (exit)
     (while (not exit)
       (tramp-message 9 "Waiting for prompts from remote shell")
@@ -5512,6 +5663,7 @@ Maybe the different regular expressions need to be tuned.
                   (or user (user-login-name)) host method)
     (let ((process-environment (copy-sequence process-environment)))
       (setenv "TERM" tramp-terminal-type)
                   (or user (user-login-name)) host method)
     (let ((process-environment (copy-sequence process-environment)))
       (setenv "TERM" tramp-terminal-type)
+      (setenv "PS1" "$ ")
       (let* ((default-directory (tramp-temporary-file-directory))
             ;; If we omit the conditional here, then we would use
             ;; `undecided-dos' in some cases.  With the conditional,
       (let* ((default-directory (tramp-temporary-file-directory))
             ;; If we omit the conditional here, then we would use
             ;; `undecided-dos' in some cases.  With the conditional,
@@ -5577,10 +5729,14 @@ arguments, and xx will be used as the host name to connect to.
                        multi-method
                        (tramp-find-method multi-method method user host)
                        user host 'tramp-login-program))
                        multi-method
                        (tramp-find-method multi-method method user host)
                        user host 'tramp-login-program))
-         (login-args (tramp-get-method-parameter
-                    multi-method
-                    (tramp-find-method multi-method method user host)
-                    user host 'tramp-login-args))
+         (login-args (mapcar
+                      (lambda (x)
+                        (format-spec
+                         x `((?t . ,(format "/tmp/%s" tramp-temp-name-prefix)))))
+                      (tramp-get-method-parameter
+                       multi-method
+                       (tramp-find-method multi-method method user host)
+                       user host 'tramp-login-args)))
          (real-host host))
       ;; The following should be changed.  We need a more general
       ;; mechanism to parse extra host args.
          (real-host host))
       ;; The following should be changed.  We need a more general
       ;; mechanism to parse extra host args.
@@ -5588,6 +5744,7 @@ arguments, and xx will be used as the host name to connect to.
        (setq login-args (cons "-p" (cons (match-string 2 host) login-args)))
        (setq real-host (match-string 1 host)))
       (setenv "TERM" tramp-terminal-type)
        (setq login-args (cons "-p" (cons (match-string 2 host) login-args)))
        (setq real-host (match-string 1 host)))
       (setenv "TERM" tramp-terminal-type)
+      (setenv "PS1" "$ ")
       (let* ((default-directory (tramp-temporary-file-directory))
             ;; If we omit the conditional, we would use
             ;; `undecided-dos' in some cases.  With the conditional,
       (let* ((default-directory (tramp-temporary-file-directory))
             ;; If we omit the conditional, we would use
             ;; `undecided-dos' in some cases.  With the conditional,
@@ -5639,6 +5796,7 @@ prompt than you do, so it is not at all unlikely that the variable
                   (or user "<root>") method)
     (let ((process-environment (copy-sequence process-environment)))
       (setenv "TERM" tramp-terminal-type)
                   (or user "<root>") method)
     (let ((process-environment (copy-sequence process-environment)))
       (setenv "TERM" tramp-terminal-type)
+      (setenv "PS1" "$ ")
       (let* ((default-directory (tramp-temporary-file-directory))
             ;; If we omit the conditional, we use `undecided-dos' in
             ;; some cases.  With the conditional, we use nil in these
       (let* ((default-directory (tramp-temporary-file-directory))
             ;; If we omit the conditional, we use `undecided-dos' in
             ;; some cases.  With the conditional, we use nil in these
@@ -5703,6 +5861,7 @@ log in as u2 to h2."
     (tramp-message 7 "Opening `%s' connection..." multi-method)
     (let ((process-environment (copy-sequence process-environment)))
       (setenv "TERM" tramp-terminal-type)
     (tramp-message 7 "Opening `%s' connection..." multi-method)
     (let ((process-environment (copy-sequence process-environment)))
       (setenv "TERM" tramp-terminal-type)
+      (setenv "PS1" "$ ")
       (let* ((default-directory (tramp-temporary-file-directory))
             ;; If we omit the conditional, we use `undecided-dos' in
             ;; some cases.  With the conditional, we use nil in these
       (let* ((default-directory (tramp-temporary-file-directory))
             ;; If we omit the conditional, we use `undecided-dos' in
             ;; some cases.  With the conditional, we use nil in these
@@ -6183,8 +6342,17 @@ locale to C and sets up the remote shell search path."
                                   "ln" tramp-remote-path nil)))
     (when ln
       (tramp-set-connection-property "ln" ln multi-method method user host)))
                                   "ln" tramp-remote-path nil)))
     (when ln
       (tramp-set-connection-property "ln" ln multi-method method user host)))
+  ;; Set uid and gid.
   (erase-buffer)
   (erase-buffer)
+  (tramp-send-command multi-method method user host "id -u; id -g")
+  (tramp-wait-for-output)
+  (goto-char (point-min))
+  (tramp-set-connection-property
+   "uid" (read (current-buffer)) multi-method method user host)
+  (tramp-set-connection-property
+   "gid" (read (current-buffer)) multi-method method user host)
   ;; Find the right encoding/decoding commands to use.
   ;; Find the right encoding/decoding commands to use.
+  (erase-buffer)
   (unless (tramp-method-out-of-band-p multi-method method user host)
     (tramp-find-inline-encoding multi-method method user host))
   ;; If encoding/decoding command are given, test to see if they work.
   (unless (tramp-method-out-of-band-p multi-method method user host)
     (tramp-find-inline-encoding multi-method method user host))
   ;; If encoding/decoding command are given, test to see if they work.
@@ -6393,7 +6561,8 @@ connection if a previous connection has died for some reason."
                 p (processp p) (memq (process-status p) '(run open)))
        (tramp-send-command
         multi-method method user host "echo are you awake" nil t)
                 p (processp p) (memq (process-status p) '(run open)))
        (tramp-send-command
         multi-method method user host "echo are you awake" nil t)
-       (unless (tramp-wait-for-output 10)
+       (unless (and (memq (process-status p) '(run open))
+                     (tramp-wait-for-output 10))
          (delete-process p)
          (setq p nil))
        (erase-buffer)))
          (delete-process p)
          (setq p nil))
        (erase-buffer)))
@@ -6677,9 +6846,14 @@ If `tramp-discard-garbage' is nil, just erase buffer."
   "Convert file-attributes ATTR generated by perl script or ls.
 Convert file mode bits to string and set virtual device number.
 Return ATTR."
   "Convert file-attributes ATTR generated by perl script or ls.
 Convert file mode bits to string and set virtual device number.
 Return ATTR."
+  ;; Convert file mode bits to string.
   (unless (stringp (nth 8 attr))
   (unless (stringp (nth 8 attr))
-    ;; Convert file mode bits to string.
     (setcar (nthcdr 8 attr) (tramp-file-mode-from-int (nth 8 attr))))
     (setcar (nthcdr 8 attr) (tramp-file-mode-from-int (nth 8 attr))))
+  ;; Set file's gid change bit.  Possible only when id-format is 'integer.
+  (when (numberp (nth 3 attr))
+    (setcar (nthcdr 9 attr)
+           (not (eql (nth 3 attr)
+                     (tramp-get-remote-gid multi-method method user host)))))
   ;; Set virtual device number.
   (setcar (nthcdr 11 attr)
           (tramp-get-device multi-method method user host))
   ;; Set virtual device number.
   (setcar (nthcdr 11 attr)
           (tramp-get-device multi-method method user host))
@@ -6816,8 +6990,8 @@ localname (file name on remote host)."
        item)
     (while choices
       (setq item (pop choices))
        item)
     (while choices
       (setq item (pop choices))
-      (when (and (string-match (nth 0 item) (or host ""))
-                (string-match (nth 1 item) (or user "")))
+      (when (and (string-match (or (nth 0 item) "") (or host ""))
+                (string-match (or (nth 1 item) "") (or user "")))
        (setq method (nth 2 item))
        (setq choices nil)))
     method))
        (setq method (nth 2 item))
        (setq choices nil)))
     method))
@@ -6937,6 +7111,12 @@ If both MULTI-METHOD and METHOD are nil, do a lookup in
 (defun tramp-get-remote-ln (multi-method method user host)
   (tramp-get-connection-property "ln" nil multi-method method user host))
 
 (defun tramp-get-remote-ln (multi-method method user host)
   (tramp-get-connection-property "ln" nil multi-method method user host))
 
+(defun tramp-get-remote-uid (multi-method method user host)
+  (tramp-get-connection-property "uid" nil multi-method method user host))
+
+(defun tramp-get-remote-gid (multi-method method user host)
+  (tramp-get-connection-property "gid" nil multi-method method user host))
+
 ;; Get a property of a TRAMP connection.
 (defun tramp-get-connection-property
   (property default multi-method method user host)
 ;; Get a property of a TRAMP connection.
 (defun tramp-get-connection-property
   (property default multi-method method user host)
@@ -6947,7 +7127,7 @@ If the value is not set for the connection, return `default'"
     (let (error)
       (condition-case nil
          (symbol-value (intern (concat "tramp-connection-property-" property)))
     (let (error)
       (condition-case nil
          (symbol-value (intern (concat "tramp-connection-property-" property)))
-       (error  default)))))
+       (error default)))))
 
 ;; Set a property of a TRAMP connection.
 (defun tramp-set-connection-property
 
 ;; Set a property of a TRAMP connection.
 (defun tramp-set-connection-property
@@ -7025,7 +7205,9 @@ as default."
     "Invoke `tramp-handle-make-auto-save-file-name' for tramp files."
     (if (and (buffer-file-name) (tramp-tramp-file-p (buffer-file-name)))
        (setq ad-return-value (tramp-handle-make-auto-save-file-name))
     "Invoke `tramp-handle-make-auto-save-file-name' for tramp files."
     (if (and (buffer-file-name) (tramp-tramp-file-p (buffer-file-name)))
        (setq ad-return-value (tramp-handle-make-auto-save-file-name))
-      ad-do-it)))
+      ad-do-it))
+  (add-hook 'tramp-unload-hook
+           '(lambda () (ad-unadvise 'make-auto-save-file-name))))
 
 ;; In Emacs < 22 and XEmacs < 21.5 autosaved remote files have
 ;; permission 0666 minus umask. This is a security threat.
 
 ;; In Emacs < 22 and XEmacs < 21.5 autosaved remote files have
 ;; permission 0666 minus umask. This is a security threat.
@@ -7049,7 +7231,10 @@ as default."
            (and (featurep 'xemacs)
                 (= emacs-major-version 21)
                 (> emacs-minor-version 4)))
            (and (featurep 'xemacs)
                 (= emacs-major-version 21)
                 (> emacs-minor-version 4)))
-  (add-hook 'auto-save-hook 'tramp-set-auto-save-file-modes))
+  (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))))
 
 (defun tramp-subst-strs-in-string (alist string)
   "Replace all occurrences of the string FROM with TO in STRING.
 
 (defun tramp-subst-strs-in-string (alist string)
   "Replace all occurrences of the string FROM with TO in STRING.
@@ -7118,10 +7303,7 @@ Invokes `password-read' if available, `read-passwd' else."
 
 (defun tramp-time-diff (t1 t2)
   "Return the difference between the two times, in seconds.
 
 (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).
-
-NOTE: This function will fail if the time difference is too large to
-fit in an integer."
+T1 and T2 are time values (as returned by `current-time' for example)."
   ;; Pacify byte-compiler with `symbol-function'.
   (cond ((and (fboundp 'subtract-time)
              (fboundp 'float-time))
   ;; Pacify byte-compiler with `symbol-function'.
   (cond ((and (fboundp 'subtract-time)
              (fboundp 'float-time))
@@ -7132,10 +7314,9 @@ fit in an integer."
          (funcall (symbol-function 'time-to-seconds)
                  (funcall (symbol-function 'subtract-time) t1 t2)))
         ((fboundp 'itimer-time-difference)
          (funcall (symbol-function 'time-to-seconds)
                  (funcall (symbol-function 'subtract-time) t1 t2)))
         ((fboundp 'itimer-time-difference)
-         (floor (funcall
-                (symbol-function 'itimer-time-difference)
-                (if (< (length t1) 3) (append t1 '(0)) t1)
-                (if (< (length t2) 3) (append t2 '(0)) t2))))
+        (funcall (symbol-function 'itimer-time-difference)
+                 (if (< (length t1) 3) (append t1 '(0)) t1)
+                 (if (< (length t2) 3) (append t2 '(0)) t2)))
         (t
          ;; snarfed from Emacs 21 time-date.el; combining
         ;; time-to-seconds and subtract-time
         (t
          ;; snarfed from Emacs 21 time-date.el; combining
         ;; time-to-seconds and subtract-time
@@ -7276,7 +7457,9 @@ Only works for Bourne-like shells."
              (setq ad-return-value (list name))))
        ;; If it is not a Tramp file, just run the original function.
        (let ((res ad-do-it))
              (setq ad-return-value (list name))))
        ;; If it is not a Tramp file, just run the original function.
        (let ((res ad-do-it))
-         (setq ad-return-value (or res (list name))))))))
+         (setq ad-return-value (or res (list name)))))))
+  (add-hook 'tramp-unload-hook
+           '(lambda () (ad-unadvise 'file-expand-wildcards))))
 
 ;; Tramp version is useful in a number of situations.
 
 
 ;; Tramp version is useful in a number of situations.
 
@@ -7501,6 +7684,26 @@ Therefore, the contents of files might be included in the debug buffer(s).")
 
 (defalias 'tramp-submit-bug 'tramp-bug)
 
 
 (defalias 'tramp-submit-bug 'tramp-bug)
 
+;; Checklist for `tramp-unload-hook'
+;; - Unload all `tramp-*' packages
+;; - Reset `file-name-handler-alist'
+;; - Cleanup hooks where Tramp functions are in
+;; - Cleanup advised functions
+;; - Cleanup autoloads
+;;;###autoload
+(defun tramp-unload-tramp ()
+  "Discard Tramp from loading remote files."
+  (interactive)
+  ;; When Tramp is not loaded yet, its autoloads are still active.
+  (tramp-unload-file-name-handlers)
+  ;; ange-ftp settings must be enabled.
+  (when (functionp 'tramp-ftp-enable-ange-ftp)
+    (funcall (symbol-function 'tramp-ftp-enable-ange-ftp)))
+  ;; `tramp-util' unloads also `tramp'.
+  (condition-case nil ;; maybe its not loaded yet.
+      (unload-feature (if (featurep 'tramp-util) 'tramp-util 'tramp) 'force)
+    (error nil)))
+
 (provide 'tramp)
 
 ;; Make sure that we get integration with the VC package.
 (provide 'tramp)
 
 ;; Make sure that we get integration with the VC package.
@@ -7508,7 +7711,12 @@ Therefore, the contents of files might be included in the debug buffer(s).")
 ;; This must come after (provide 'tramp) because tramp-vc.el
 ;; requires tramp.
 (eval-after-load "vc"
 ;; This must come after (provide 'tramp) because tramp-vc.el
 ;; requires tramp.
 (eval-after-load "vc"
-  '(require 'tramp-vc))
+  '(progn
+     (require 'tramp-vc)
+     (add-hook 'tramp-unload-hook
+              '(lambda ()
+                 (when (featurep 'tramp-vc)
+                   (unload-feature 'tramp-vc 'force))))))
 
 ;;; TODO:
 
 
 ;;; TODO: