]> code.delx.au - gnu-emacs/blobdiff - lisp/net/tramp.el
(tramp-unified-filenames): Improve previos doc fix.
[gnu-emacs] / lisp / net / tramp.el
index 17b91d92818134a13ee1533d7ec7e82aaf368121..54bb69464982a569645dba870609d8fbab0f8276 100644 (file)
@@ -2,7 +2,7 @@
 ;;; 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>
 
 ;; 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
 
 (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"))
 ;;;###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.
@@ -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"
-    '(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"
-    '(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
@@ -121,7 +142,12 @@ 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"
-    '(require 'tramp-smb)))
+    '(progn
+       (require 'tramp-smb)
+       (add-hook 'tramp-unload-hook
+                '(lambda ()
+                   (when (featurep 'tramp-smb)
+                     (unload-feature 'tramp-smb 'force)))))))
 
 (eval-when-compile
   (require 'cl)
@@ -650,7 +676,7 @@ various functions for details."
   (if (and (fboundp 'executable-find)
           (executable-find "plink"))
       "plink"
-    "ssh")
+    "scp")
   "*Default method to use for transferring files.
 See `tramp-methods' for possibilities.
 Also see `tramp-default-method-alist'."
@@ -810,8 +836,10 @@ The default value is to use the same value as `tramp-rsh-end-of-line'."
   :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.
@@ -844,7 +872,7 @@ which should work well in many cases."
   :type 'regexp)
 
 (defcustom tramp-password-prompt-regexp
-  "^.*\\([pP]assword\\|passphrase.*\\):\^@? *"
+  "^.*\\([pP]assword\\|passphrase\\).*:\^@? *"
   "*Regexp matching password-like prompts.
 The regexp should match at end of buffer.
 
@@ -1358,32 +1386,62 @@ autocorrect\" to the remote host."
   (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
 checked via the following code:
 
   (with-temp-buffer
-    (let ((bytes 1000)
-      (proc (start-process (buffer-name) (current-buffer) \"wc\" \"-c\")))
-      (process-send-string proc (make-string bytes ?x))
-      (process-send-eof proc)
-      (process-send-eof proc)
-      (accept-process-output proc 1)
-      (goto-char (point-min))
-      (re-search-forward \"\\\\w+\")
-      (message \"Bytes sent: %s\\tBytes received: %s\" bytes (match-string 0))))
-
-In the Emacs normally running Tramp, evaluate the above code.
-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.
-
-If your Emacs is buggy, the sent and received numbers will be
-different.  In that case, you'll want to set this variable to
-some number.  For those people who have needed it, the value 500
-seems to have worked well.  There is no way to predict what value
-you need; maybe you could just experiment a bit.
+    (let* ((user \"xxx\") (host \"yyy\")
+           (init 0) (step 50)
+           (sent init) (received init))
+      (while (= sent received)
+        (setq sent (+ sent step))
+        (erase-buffer)
+        (let ((proc (start-process (buffer-name) (current-buffer)
+                                   \"ssh\" \"-l\" user host \"wc\" \"-c\")))
+          (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))
+            (setq received (string-to-number (match-string 0)))
+            (delete-process proc)
+            (message \"Bytes sent: %s\\tBytes received: %s\" sent received)
+            (sit-for 0))))
+      (if (> sent (+ init step))
+          (message \"You should set `tramp-chunksize' to a maximum of %s\"
+                   (- sent step))
+        (message \"Test does not work\")
+        (display-buffer (current-buffer))
+        (sit-for 30))))
+
+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
+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).
+
+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.
+
+If your Emacs is buggy, the code stops and gives you an indication
+about the value `tramp-chunksize' should be set.  Maybe you could just
+experiment a bit, e.g. changing the values of `init' and `step'
+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
+\(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
 this variable to be set as well."
@@ -1415,7 +1473,7 @@ the visited file modtime.")
        ((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
@@ -1590,8 +1648,8 @@ printf(
 on the remote file system.")
 
 (defconst tramp-perl-directory-files-and-attributes "\
-chdir($ARGV[0]);
-opendir(DIR,\".\");
+chdir($ARGV[0]) or printf(\"\\\"Cannot change to $ARGV[0]: $''!''\\\"\\n\"), exit();
+opendir(DIR,\".\") or printf(\"\\\"Cannot open directory $ARGV[0]: $''!''\\\"\\n\"), exit();
 @list = readdir(DIR);
 closedir(DIR);
 $n = scalar(@list);
@@ -1679,7 +1737,7 @@ on the remote host.")
 (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 {
@@ -1721,7 +1779,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>.
-# Copyright (C) 2002 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2006 Free Software Foundation, Inc.
 use strict;
 
 my %%trans = do {
@@ -1763,8 +1821,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.")
 
-; 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
@@ -1869,17 +1925,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.")
 
-;; 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
-  '(
-    (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
@@ -1967,11 +2018,10 @@ 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)
-;; 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.
+(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.
@@ -1982,6 +2032,7 @@ The intent is to protect against `obsolete variable' warnings."
      (let ((,variable ,value))
        ,@body)))
 (put 'tramp-let-maybe 'lisp-indent-function 2)
+(put 'tramp-let-maybe 'edebug-form-spec t)
 
 ;;; Config Manipulation Functions:
 
@@ -2113,28 +2164,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."
-  ;; 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
-    ;; 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."
@@ -2340,8 +2374,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
-     ;; 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.
@@ -2371,11 +2405,14 @@ target of the symlink differ."
           (buffer-name)))
   (if time-list
       (tramp-run-real-handler 'set-visited-file-modtime (list time-list))
-    (let ((f (buffer-file-name)))
+    (let ((f (buffer-file-name))
+         coding-system-used)
       (with-parsed-tramp-file-name f nil
        (let* ((attr (file-attributes f))
               ;; '(-1 65535) means file doesn't exists yet.
               (modtime (or (nth 5 attr) '(-1 65535))))
+         (when (boundp 'last-coding-system-used)
+           (setq coding-system-used (symbol-value 'last-coding-system-used)))
          ;; We use '(0 0) as a don't-know value.  See also
          ;; `tramp-handle-file-attributes-with-ls'.
          (if (not (equal modtime '(0 0)))
@@ -2390,6 +2427,8 @@ target of the symlink differ."
              (setq attr (buffer-substring (point)
                                           (progn (end-of-line) (point)))))
            (setq tramp-buffer-file-attributes attr))
+         (when (boundp 'last-coding-system-used)
+           (set 'last-coding-system-used coding-system-used))
          nil)))))
 
 ;; CCC continue here
@@ -2592,9 +2631,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
-    (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.
 
@@ -2699,7 +2741,10 @@ of."
                                     (tramp-shell-quote-argument localname)
                                     (or id-format 'integer)))
         (tramp-wait-for-output)
-        (let* ((root (cons nil (read (current-buffer))))
+        (let* ((root (cons nil (let ((object (read (current-buffer))))
+                                 (when (stringp object)
+                                   (error object))
+                                 object)))
                (cell root))
           (while (cdr cell)
             (if (and match (not (string-match match (caadr cell))))
@@ -2859,7 +2904,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
-              (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
@@ -2932,10 +2977,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)
-              (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.
@@ -3449,6 +3494,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)))
+           ;; 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)
@@ -3461,17 +3517,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)))
+       ;; 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
-       ;; 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-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.
@@ -3496,6 +3559,10 @@ the result will be a local, non-Tramp, filename."
   "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
@@ -3504,7 +3571,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
-       (let ((asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
+       (let ((curbuf (current-buffer))
+             (asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
              status)
          (unless output-buffer
            (setq output-buffer
@@ -3604,7 +3672,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))
-           (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.
@@ -3619,11 +3689,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"))
-  (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.
 
@@ -3750,7 +3819,7 @@ This will break if COMMAND prints a newline, followed by the value of
                              'insert-file-contents)
                      'file-local-copy)))
               (file-local-copy filename)))
-           (result nil))
+           coding-system-used result)
        (when visit
          (setq buffer-file-name filename)
          (set-visited-file-modtime)
@@ -3759,10 +3828,15 @@ This will break if COMMAND prints a newline, followed by the value of
         multi-method method user host
         9 "Inserting local temp file `%s'..." local-copy)
        (setq result (insert-file-contents local-copy nil beg end replace))
+       ;; Now `last-coding-system-used' has right value.  Remember it.
+       (when (boundp 'last-coding-system-used)
+         (setq coding-system-used (symbol-value 'last-coding-system-used)))
        (tramp-message-for-buffer
         multi-method method user host
         9 "Inserting local temp file `%s'...done" local-copy)
        (delete-file local-copy)
+       (when (boundp 'last-coding-system-used)
+         (set 'last-coding-system-used coding-system-used))
        (list (expand-file-name filename)
              (second result))))))
 
@@ -3813,37 +3887,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."
-  (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
@@ -3876,6 +3963,13 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
          (loc-dec (tramp-get-local-decoding multi-method method user host))
          (trampbuf (get-buffer-create "*tramp output*"))
          (modes (file-modes filename))
+         ;; We use this to save the value of `last-coding-system-used'
+         ;; after writing the tmp file.  At the end of the function,
+         ;; we set `last-coding-system-used' to this saved value.
+         ;; This way, any intermediary coding systems used while
+         ;; talking to the remote shell or suchlike won't hose this
+         ;; variable.  This approach was snarfed from ange-ftp.el.
+         coding-system-used
          tmpfil)
       ;; Write region into a tmp file.  This isn't really needed if we
       ;; use an encoding function, but currently we use it always
@@ -3892,6 +3986,9 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
        (if confirm ; don't pass this arg unless defined for backward compat.
           (list start end tmpfil append 'no-message lockname confirm)
         (list start end tmpfil append 'no-message lockname)))
+      ;; Now, `last-coding-system-used' has the right value.  Remember it.
+      (when (boundp 'last-coding-system-used)
+       (setq coding-system-used (symbol-value 'last-coding-system-used)))
       ;; The permissions of the temporary file should be set.  If
       ;; filename does not exist (eq modes nil) it has been renamed to
       ;; the backup file.  This case `save-buffer' handles
@@ -3998,6 +4095,9 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
         ;; We must pass modtime explicitely, because filename can be different
         ;; from (buffer-file-name), f.e. if `file-precious-flag' is set.
         (nth 5 (file-attributes filename))))
+      ;; Make `last-coding-system-used' have the right value.
+      (when (boundp 'last-coding-system-used)
+       (set 'last-coding-system-used coding-system-used))
       (when (or (eq visit t)
                (eq visit nil)
                (stringp visit))
@@ -4034,7 +4134,8 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
 ;;         (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."
@@ -4047,13 +4148,14 @@ pass to the 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.
-(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."
@@ -4065,7 +4167,7 @@ pass to the 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
@@ -4162,12 +4264,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."
+;;  (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))
+          (completion (tramp-completion-mode 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
@@ -4215,38 +4330,56 @@ Fall back to normal file name handler if no Tramp handler exists."
       (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."
-;;   (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))
-      (tramp-completion-run-real-handler operation args))))
+      (tramp-completion-run-real-handler operation args)))))
 
 ;;;###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))))))
-(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:
@@ -4297,25 +4430,22 @@ necessary anymore."
                 (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
 
+(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
@@ -4331,6 +4461,7 @@ necessary anymore."
 (defun tramp-completion-mode (file)
   "Checks whether method / user name / host name completion is active."
   (cond
+   (tramp-completion-mode t)
    ((not tramp-unified-filenames) t)
    ((string-match "^/.*:.*:$" file) nil)
    ((string-match
@@ -4339,114 +4470,109 @@ necessary anymore."
      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 (integerp 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)
-            (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)))
 
-(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.
+;;;###autoload
 (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.
+;;;###autoload
 (defun tramp-completion-handle-file-name-completion (filename directory)
   "Like `file-name-completion' for tramp files."
   (try-completion filename
@@ -4573,8 +4699,7 @@ remote host and localname (filename on remote host)."
    (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.
@@ -4607,8 +4732,7 @@ PARTIAL-USER must match USER, PARTIAL-HOST must match 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.
@@ -4827,15 +4951,6 @@ User may be nil."
      (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)
@@ -4870,6 +4985,9 @@ Function may have 0-3 parameters."
              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.
@@ -4918,15 +5036,16 @@ 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'."
-  (let ((touch-time (format-time-string "%Y%m%d%H%M.%S" time)))
+  (let ((touch-time (format-time-string "%Y%m%d%H%M.%S" time t)))
     (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 "TZ=UTC; export TZ; touch -t %s %s"
                                    touch-time
-                                   localname)))
+                                   (tramp-shell-quote-argument localname))
+                           t))
              (pop-to-buffer buf)
              (error "tramp-touch: touch failed, see buffer `%s' for details"
                     buf))))
@@ -5291,6 +5410,9 @@ The terminal type can be configured with `tramp-terminal-type'."
               (tramp-message 10 "'set mode' error ignored.")
               (tramp-message 9 "Process has finished.")
               (throw 'tramp-action 'ok))
+          (goto-char (point-min))
+          (when (re-search-forward "^.cp.?: \\(.+: Permission denied.?\\)$" nil t)
+            (error "Remote host: %s" (match-string 1)))
           (tramp-message 9 "Process has died.")
           (throw 'tramp-action 'process-died)))
        (t nil)))
@@ -5459,6 +5581,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)
+      (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,
@@ -5535,6 +5658,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)
+      (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,
@@ -5586,6 +5710,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)
+      (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
@@ -5650,6 +5775,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)
+      (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
@@ -6130,8 +6256,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)))
+  ;; Set uid and gid.
   (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.
+  (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.
@@ -6340,7 +6475,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)
-       (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)))
@@ -6624,9 +6760,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 mode bits to string.
   (unless (stringp (nth 8 attr))
-    ;; Convert file mode bits to string.
     (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))
@@ -6884,6 +7025,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-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)
@@ -6894,7 +7041,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)))
-       (error  default)))))
+       (error default)))))
 
 ;; Set a property of a TRAMP connection.
 (defun tramp-set-connection-property
@@ -6972,7 +7119,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))
-      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.
@@ -6990,13 +7139,16 @@ as default."
       ;; 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) #o600)))))
+                     (or (file-modes bfn) (tramp-octal-to-decimal "0600"))))))
 
 (unless (or (> emacs-major-version 21)
            (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.
@@ -7065,10 +7217,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).
-
-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))
@@ -7079,10 +7228,9 @@ fit in an integer."
          (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
@@ -7223,7 +7371,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 (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.
 
@@ -7448,6 +7598,26 @@ Therefore, the contents of files might be included in the debug buffer(s).")
 
 (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.
@@ -7455,7 +7625,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"
-  '(require 'tramp-vc))
+  '(progn
+     (require 'tramp-vc)
+     (add-hook 'tramp-unload-hook
+              '(lambda ()
+                 (when (featurep 'tramp-vc)
+                   (unload-feature 'tramp-vc 'force))))))
 
 ;;; TODO: