Add SELinux support.
[bpt/emacs.git] / lisp / net / tramp.el
index e227de5..07759e8 100644 (file)
@@ -1,7 +1,7 @@
 ;;; tramp.el --- Transparent Remote Access, Multiple Protocol
 
 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+;;   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; (copyright statements below in code to be updated with the above notice)
 
@@ -36,9 +36,9 @@
 ;; Notes:
 ;; -----
 ;;
-;; This package only works for Emacs 21.1 and higher, and for XEmacs 21.4
+;; This package only works for Emacs 22.1 and higher, and for XEmacs 21.4
 ;; and higher.  For XEmacs 21, you need the package `fsf-compat' for
-;; the `with-timeout' macro.)
+;; the `with-timeout' macro.
 ;;
 ;; Also see the todo list at the bottom of this file.
 ;;
@@ -79,7 +79,7 @@
            (when (featurep 'tramp-compat)
              (unload-feature 'tramp-compat 'force))))
 
-(require 'format-spec)                  ; from Gnus 5.8, also in tar ball
+(require 'format-spec)
 ;; As long as password.el is not part of (X)Emacs, it shouldn't
 ;; be mandatory
 (if (featurep 'xemacs)
 (defgroup tramp nil
   "Edit remote files with a combination of rsh and rcp or similar programs."
   :group 'files
+  :group 'comm
   :version "22.1")
 
 ;; Maybe we need once a real Tramp mode, with key bindings etc.
@@ -297,6 +298,21 @@ files conditionalize this setup based on the TERM environment variable."
   :group 'tramp
   :type 'string)
 
+;; ksh on OpenBSD 4.5 requires, that PS1 contains a `#' character for
+;; root users.  It uses the `$' character for other users.  In order
+;; to guarantee a proper prompt, we use "#$" for the prompt.
+
+(defvar tramp-end-of-output
+  (format
+   "///%s#$"
+   (md5 (concat (prin1-to-string process-environment) (current-time-string))))
+  "String used to recognize end of output.
+The '$' character at the end is quoted; the string cannot be
+detected as prompt when being sent on echoing hosts, therefore.")
+
+(defconst tramp-initial-end-of-output "#$ "
+  "Prompt when establishing a connection.")
+
 (defvar tramp-methods
   `(("rcp"   (tramp-login-program        "rsh")
              (tramp-login-args           (("%h") ("-l" "%u")))
@@ -386,6 +402,7 @@ files conditionalize this setup based on the TERM environment variable."
             (tramp-copy-program         "rsync")
             (tramp-copy-args            (("-e" "ssh") ("-t" "%k") ("-r")))
             (tramp-copy-keep-date       t)
+            (tramp-copy-keep-tmpfile    t)
             (tramp-copy-recursive       t)
             (tramp-password-end-of-line nil))
     ("rsyncc"
@@ -403,6 +420,7 @@ files conditionalize this setup based on the TERM environment variable."
                                             " -o ControlPath=%t.%%r@%%h:%%p"
                                             " -o ControlMaster=auto"))))
             (tramp-copy-keep-date       t)
+            (tramp-copy-keep-tmpfile    t)
             (tramp-copy-recursive       t)
             (tramp-password-end-of-line nil))
     ("remcp" (tramp-login-program        "remsh")
@@ -583,8 +601,9 @@ files conditionalize this setup based on the TERM environment variable."
             ;; `tramp-compute-multi-hops'.
             (tramp-login-args           (("-load") ("%h") ("-t")
                                          (,(format
-                                            "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=$ '"
-                                            tramp-terminal-type))
+                                            "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
+                                            tramp-terminal-type
+                                            tramp-initial-end-of-output))
                                          ("/bin/sh")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         nil)
@@ -654,6 +673,11 @@ pair of the form (KEY VALUE).  The following KEYs are defined:
   * `tramp-copy-keep-date'
     This specifies whether the copying program when the preserves the
     timestamp of the original file.
+  * `tramp-copy-keep-tmpfile'
+    This specifies whether a temporary local file shall be kept
+    for optimization reasons (useful for \"rsync\" methods).
+  * `tramp-copy-recursive'
+    Whether the operation copies directories recursively.
   * `tramp-default-port'
     The default port of a method is needed in case of gateway connections.
     Additionally, it is used as indication which method is prepared for
@@ -847,9 +871,9 @@ interpreted as a regular expression which always matches."
 
 (defvar tramp-completion-function-alist nil
   "*Alist of methods for remote files.
-This is a list of entries of the form (NAME PAIR1 PAIR2 ...).
+This is a list of entries of the form \(NAME PAIR1 PAIR2 ...\).
 Each NAME stands for a remote access method.  Each PAIR is of the form
-\(FUNCTION FILE).  FUNCTION is responsible to extract user names and host
+\(FUNCTION FILE\).  FUNCTION is responsible to extract user names and host
 names from FILE for completion.  The following predefined FUNCTIONs exists:
 
  * `tramp-parse-rhosts'      for \"~/.rhosts\" like files,
@@ -925,7 +949,12 @@ the info pages.")
 (defconst tramp-echo-mark-marker "_echo"
   "String marker to surround echoed commands.")
 
-(defconst tramp-echo-mark "_echo\b\b\b\b\b"
+(defconst tramp-echo-mark-marker-length (length tramp-echo-mark-marker)
+  "String length of `tramp-echo-mark-marker'.")
+
+(defconst tramp-echo-mark
+  (concat tramp-echo-mark-marker
+         (make-string tramp-echo-mark-marker-length ?\b))
   "String mark to be transmitted around shell commands.
 Used to separate their echo from the output they produce.  This
 will only be used if we cannot disable remote echo via stty.
@@ -935,7 +964,9 @@ producing some echo which can later be detected by
 followed by an equal number of backspaces to erase them will
 usually suffice.")
 
-(defconst tramp-echoed-echo-mark-regexp "_echo\\(\b\\( \b\\)?\\)\\{5\\}"
+(defconst tramp-echoed-echo-mark-regexp
+  (format "%s\\(\b\\( \b\\)?\\)\\{%d\\}"
+         tramp-echo-mark-marker tramp-echo-mark-marker-length)
   "Regexp which matches `tramp-echo-mark' as it gets echoed by
 the remote shell.")
 
@@ -994,7 +1025,7 @@ as given in your `~/.profile'."
 
 (defcustom tramp-remote-process-environment
   `("HISTFILE=$HOME/.tramp_history" "HISTSIZE=1" "LC_ALL=C"
-    ,(concat "TERM=" tramp-terminal-type)
+    ,(format "TERM=%s" tramp-terminal-type)
     "EMACS=t" ;; Deprecated.
     ,(format "INSIDE_EMACS=%s,tramp:%s" emacs-version tramp-version)
     "CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH="
@@ -1023,7 +1054,7 @@ Sometimes the prompt is reported to look like \"login as:\"."
 (defcustom tramp-shell-prompt-pattern
   ;; Allow a prompt to start right after a ^M since it indeed would be
   ;; displayed at the beginning of the line (and Zsh uses it).
-  "\\(?:^\\|\r\\)[^#$%>\n]*[#$%>] *\\(\e\\[[0-9;]*[a-zA-Z] *\\)*"
+  "\\(?:^\\|\r\\)[^#$%>\n]*#?[#$%>] *\\(\e\\[[0-9;]*[a-zA-Z] *\\)*"
   "Regexp to match prompts from remote shell.
 Normally, Tramp expects you to configure `shell-prompt-pattern'
 correctly, but sometimes it happens that you are connecting to a
@@ -1031,7 +1062,10 @@ remote host which sends a different kind of shell prompt.  Therefore,
 Tramp recognizes things matched by `shell-prompt-pattern' as prompt,
 and also things matched by this variable.  The default value of this
 variable is similar to the default value of `shell-prompt-pattern',
-which should work well in many cases."
+which should work well in many cases.
+
+This regexp must match both `tramp-initial-end-of-output' and
+`tramp-end-of-output'."
   :group 'tramp
   :type 'regexp)
 
@@ -1052,6 +1086,7 @@ The `sudo' program appears to insert a `^@' character into the prompt."
                        "Login Incorrect"
                        "Connection refused"
                        "Connection closed"
+                       "Timeout, server not responding."
                        "Sorry, try again."
                        "Name or service not known"
                        "Host key verification failed."
@@ -1146,6 +1181,11 @@ part, though."
   "Buffer name for a temporary buffer.
 It shall be used in combination with `generate-new-buffer-name'.")
 
+(defvar tramp-temp-buffer-file-name nil
+  "File name of a persistent local temporary file.
+Useful for \"rsync\" like methods.")
+(make-variable-buffer-local 'tramp-temp-buffer-file-name)
+
 (defcustom tramp-sh-extra-args '(("/bash\\'" . "-norc -noprofile"))
   "*Alist specifying extra arguments to pass to the remote shell.
 Entries are (REGEXP . ARGS) where REGEXP is a regular expression
@@ -1389,14 +1429,14 @@ See `tramp-file-name-structure' for more explanations.")
        (t (error "Wrong `tramp-syntax' defined")))
   "*Regular expression matching file names handled by Tramp.
 This regexp should match Tramp file names but no other file names.
-\(When tramp.el is loaded, this regular expression is prepended to
+When tramp.el is loaded, this regular expression is prepended to
 `file-name-handler-alist', and that is searched sequentially.  Thus,
 if the Tramp entry appears rather early in the `file-name-handler-alist'
 and is a bit too general, then some files might be considered Tramp
 files which are not really Tramp files.
 
 Please note that the entry in `file-name-handler-alist' is made when
-this file (tramp.el) is loaded.  This means that this variable must be set
+this file \(tramp.el\) is loaded.  This means that this variable must be set
 before loading tramp.el.  Alternatively, `file-name-handler-alist' can be
 updated after changing this variable.
 
@@ -1526,18 +1566,18 @@ checked via the following code:
 
 In the Emacs normally running Tramp, evaluate the above code
 \(replace \"xxx\" and \"yyy\" by the remote user and host name,
-respectively).  You can do this, for example, by pasting it into
+respectively\).  You can do this, for example, by pasting it into
 the `*scratch*' buffer and then hitting C-j with the cursor after the
 last closing parenthesis.  Note that it works only if you have configured
-\"ssh\" to run without password query, see ssh-agent(1).
+\"ssh\" to run without password query, see ssh-agent\(1\).
 
 You will see the number of bytes sent successfully to the remote host.
 If that number exceeds 1000, you can stop the execution by hitting
 C-g, because your Emacs is likely clean.
 
 When it is necessary to set `tramp-chunksize', you might consider to
-use an out-of-the-band method (like \"scp\") instead of an internal one
-\(like \"ssh\"), because setting `tramp-chunksize' to non-nil decreases
+use an out-of-the-band method \(like \"scp\"\) instead of an internal one
+\(like \"ssh\"\), because setting `tramp-chunksize' to non-nil decreases
 performance.
 
 If your Emacs is buggy, the code stops and gives you an indication
@@ -1575,14 +1615,6 @@ means to use always cached values for the directory contents."
 
 ;;; Internal Variables:
 
-(defvar tramp-end-of-output
-  (format
-   "///%s$"
-   (md5 (concat (prin1-to-string process-environment) (current-time-string))))
-  "String used to recognize end of output.
-The '$' character at the end is quoted; the string cannot be
-detected as prompt when being sent on echoing hosts, therefore.")
-
 (defvar tramp-current-method nil
   "Connection method for this *tramp* buffer.")
 
@@ -1601,6 +1633,75 @@ Many systems support `uudecode -o /dev/stdout' or `uudecode -o -'
 for this or `uudecode -p', but some systems don't, and for them
 we have this shell function.")
 
+(defconst tramp-perl-file-truename
+  "%s -e '
+use File::Spec;
+use Cwd \"realpath\";
+
+sub recursive {
+    my ($volume, @dirs) = @_;
+    my $real = realpath(File::Spec->catpath(
+                   $volume, File::Spec->catdir(@dirs), \"\"));
+    if ($real) {
+        my ($vol, $dir) = File::Spec->splitpath($real, 1);
+        return ($vol, File::Spec->splitdir($dir));
+    }
+    else {
+        my $last = pop(@dirs);
+        ($volume, @dirs) = recursive($volume, @dirs);
+        push(@dirs, $last);
+        return ($volume, @dirs);
+    }
+}
+
+$result = realpath($ARGV[0]);
+if (!$result) {
+    my ($vol, $dir) = File::Spec->splitpath($ARGV[0], 1);
+    ($vol, @dirs) = recursive($vol, File::Spec->splitdir($dir));
+
+    $result = File::Spec->catpath($vol, File::Spec->catdir(@dirs), \"\");
+}
+
+if ($ARGV[0] =~ /\\/$/) {
+    $result = $result . \"/\";
+}
+
+print \"\\\"$result\\\"\\n\";
+' \"$1\" 2>/dev/null"
+  "Perl script to produce output suitable for use with `file-truename'
+on the remote file system.
+Escape sequence %s is replaced with name of Perl binary.
+This string is passed to `format', so percent characters need to be doubled.")
+
+(defconst tramp-perl-file-name-all-completions
+  "%s -e 'sub case {
+ my $str = shift;
+ if ($ARGV[2]) {
+  return lc($str);
+ }
+ else {
+  return $str;
+ }
+}
+opendir(d, $ARGV[0]) || die(\"$ARGV[0]: $!\\nfail\\n\");
+@files = readdir(d); closedir(d);
+foreach $f (@files) {
+ if (case(substr($f, 0, length($ARGV[1]))) eq case($ARGV[1])) {
+  if (-d \"$ARGV[0]/$f\") {
+   print \"$f/\\n\";
+  }
+  else {
+   print \"$f\\n\";
+  }
+ }
+}
+print \"ok\\n\"
+' \"$1\" \"$2\" \"$3\" 2>/dev/null"
+  "Perl script to produce output suitable for use with
+`file-name-all-completions' on the remote file system.  Escape
+sequence %s is replaced with name of Perl binary.  This string is
+passed to `format', so percent characters need to be doubled.")
+
 ;; Perl script to implement `file-attributes' in a Lisp `read'able
 ;; output.  If you are hacking on this, note that you get *no* output
 ;; unless this spits out a complete line, including the '\n' at the
@@ -1744,7 +1845,7 @@ on the remote host.")
 (defconst tramp-perl-encode
   "%s -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
 #   Free Software Foundation, Inc.
 use strict;
 
@@ -1786,7 +1887,7 @@ This string is passed to `format', so percent characters need to be doubled.")
 (defconst tramp-perl-decode
   "%s -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
 #   Free Software Foundation, Inc.
 use strict;
 
@@ -1942,7 +2043,7 @@ normal Emacs functions.")
 ;; Handlers for foreign methods, like FTP or SMB, shall be plugged here.
 (defvar tramp-foreign-file-name-handler-alist
   ;; (identity . tramp-sh-file-name-handler) should always be the last
-  ;; entry, since `identity' always matches.
+  ;; entry, because `identity' always matches.
   '((identity . tramp-sh-file-name-handler))
   "Alist of elements (FUNCTION . HANDLER) for foreign methods handled specially.
 If (FUNCTION FILENAME) returns non-nil, then all I/O on that file is done by
@@ -2069,7 +2170,9 @@ an input event arrives.  The other arguments are passed to `tramp-error'."
   (save-window-excursion
     (unwind-protect
        (apply 'tramp-error vec-or-proc signal fmt-string args)
-      (when (and vec-or-proc (not (zerop tramp-verbose)))
+      (when (and vec-or-proc
+                (not (zerop tramp-verbose))
+                (not (tramp-completion-mode-p)))
        (let ((enable-recursive-minibuffers t))
          (pop-to-buffer
           (or (and (bufferp buffer) buffer)
@@ -2295,7 +2398,40 @@ been set up by `rfn-eshadow-setup-minibuffer'."
 
 (when (boundp 'rfn-eshadow-update-overlay-hook)
   (add-hook 'rfn-eshadow-update-overlay-hook
-           'tramp-rfn-eshadow-update-overlay))
+           'tramp-rfn-eshadow-update-overlay)
+  (add-hook 'tramp-unload-hook
+           (lambda ()
+             (remove-hook 'rfn-eshadow-update-overlay-hook
+                          'tramp-rfn-eshadow-update-overlay))))
+
+
+;;; Integration of eshell.el:
+
+(eval-when-compile
+  (defvar eshell-path-env))
+
+;; eshell.el keeps the path in `eshell-path-env'.  We must change it
+;; when `default-directory' points to another host.
+(defun tramp-eshell-directory-change ()
+  "Set `eshell-path-env' to $PATH of the host related to `default-directory'."
+  (setq eshell-path-env
+       (if (file-remote-p default-directory)
+           (with-parsed-tramp-file-name default-directory nil
+             (mapconcat
+              'identity
+              (tramp-get-remote-path v)
+              ":"))
+         (getenv "PATH"))))
+
+(eval-after-load "esh-util"
+  '(progn
+     (tramp-eshell-directory-change)
+     (add-hook 'eshell-directory-change-hook
+              'tramp-eshell-directory-change)
+     (add-hook 'tramp-unload-hook
+              (lambda ()
+                (remove-hook 'eshell-directory-change-hook
+                             'tramp-eshell-directory-change)))))
 
 
 ;;; File Name Handler Functions:
@@ -2344,7 +2480,14 @@ target of the symlink differ."
       ;; that FILENAME belongs to.
       (zerop
        (tramp-send-command-and-check
-       l (format "cd %s && %s -sf %s %s" cwd ln filename l-localname) t)))))
+       l
+       (format
+        "cd %s && %s -sf %s %s"
+        (tramp-shell-quote-argument cwd)
+        ln
+        (tramp-shell-quote-argument filename)
+        (tramp-shell-quote-argument l-localname))
+       t)))))
 
 (defun tramp-handle-load (file &optional noerror nomessage nosuffix must-suffix)
   "Like `load' for Tramp files."
@@ -2414,78 +2557,105 @@ target of the symlink differ."
   "Like `file-truename' for Tramp files."
   (with-parsed-tramp-file-name (expand-file-name filename) nil
     (with-file-property v localname "file-truename"
-      (let* ((directory-sep-char ?/) ; for XEmacs
-            (steps (tramp-compat-split-string localname "/"))
-            (localnamedir (tramp-run-real-handler
-                           'file-name-as-directory (list localname)))
-            (is-dir (string= localname localnamedir))
-            (thisstep nil)
-            (numchase 0)
-            ;; Don't make the following value larger than necessary.
-            ;; People expect an error message in a timely fashion when
-            ;; something is wrong; otherwise they might think that Emacs
-            ;; is hung.  Of course, correctness has to come first.
-            (numchase-limit 20)
-            (result nil)                       ;result steps in reverse order
-            symlink-target)
+      (let ((result nil))                      ; result steps in reverse order
        (tramp-message v 4 "Finding true name for `%s'" filename)
-       (while (and steps (< numchase numchase-limit))
-         (setq thisstep (pop steps))
-         (tramp-message
-          v 5 "Check %s"
-          (mapconcat 'identity
-                     (append '("") (reverse result) (list thisstep))
+       (cond
+        ;; Use GNU readlink --canonicalize-missing where available.
+        ((tramp-get-remote-readlink v)
+         (setq result
+               (tramp-send-command-and-read
+                v
+                (format "echo \"\\\"`%s --canonicalize-missing %s`\\\"\""
+                        (tramp-get-remote-readlink v)
+                        (tramp-shell-quote-argument localname)))))
+
+        ;; Use Perl implementation.
+        ((and (tramp-get-remote-perl v)
+              (tramp-get-connection-property v "perl-file-spec" nil)
+              (tramp-get-connection-property v "perl-cwd-realpath" nil))
+         (tramp-maybe-send-script
+          v tramp-perl-file-truename "tramp_perl_file_truename")
+         (setq result
+               (tramp-send-command-and-read
+                v
+                (format "tramp_perl_file_truename %s"
+                        (tramp-shell-quote-argument localname)))))
+
+        ;; Do it yourself.  We bind `directory-sep-char' here for
+        ;; XEmacs on Windows, which would otherwise use backslash.
+        (t (let* ((directory-sep-char ?/)
+                  (steps (tramp-compat-split-string localname "/"))
+                  (localnamedir (tramp-run-real-handler
+                                 'file-name-as-directory (list localname)))
+                  (is-dir (string= localname localnamedir))
+                  (thisstep nil)
+                  (numchase 0)
+                  ;; Don't make the following value larger than
+                  ;; necessary.  People expect an error message in a
+                  ;; timely fashion when something is wrong;
+                  ;; otherwise they might think that Emacs is hung.
+                  ;; Of course, correctness has to come first.
+                  (numchase-limit 20)
+                  symlink-target)
+             (while (and steps (< numchase numchase-limit))
+               (setq thisstep (pop steps))
+               (tramp-message
+                v 5 "Check %s"
+                (mapconcat 'identity
+                           (append '("") (reverse result) (list thisstep))
+                           "/"))
+               (setq symlink-target
+                     (nth 0 (file-attributes
+                             (tramp-make-tramp-file-name
+                              method user host
+                              (mapconcat 'identity
+                                         (append '("")
+                                                 (reverse result)
+                                                 (list thisstep))
+                                         "/")))))
+               (cond ((string= "." thisstep)
+                      (tramp-message v 5 "Ignoring step `.'"))
+                     ((string= ".." thisstep)
+                      (tramp-message v 5 "Processing step `..'")
+                      (pop result))
+                     ((stringp symlink-target)
+                      ;; It's a symlink, follow it.
+                      (tramp-message v 5 "Follow symlink to %s" symlink-target)
+                      (setq numchase (1+ numchase))
+                      (when (file-name-absolute-p symlink-target)
+                        (setq result nil))
+                      ;; If the symlink was absolute, we'll get a string like
+                      ;; "/user@host:/some/target"; extract the
+                      ;; "/some/target" part from it.
+                      (when (tramp-tramp-file-p symlink-target)
+                        (unless (tramp-equal-remote filename symlink-target)
+                          (tramp-error
+                           v 'file-error
+                           "Symlink target `%s' on wrong host" symlink-target))
+                        (setq symlink-target localname))
+                      (setq steps
+                            (append (tramp-compat-split-string
+                                     symlink-target "/")
+                                    steps)))
+                     (t
+                      ;; It's a file.
+                      (setq result (cons thisstep result)))))
+             (when (>= numchase numchase-limit)
+               (tramp-error
+                v 'file-error
+                "Maximum number (%d) of symlinks exceeded" numchase-limit))
+             (setq result (reverse result))
+             ;; Combine list to form string.
+             (setq result
+                   (if result
+                       (mapconcat 'identity (cons "" result) "/")
                      "/"))
-         (setq symlink-target
-               (nth 0 (file-attributes
-                       (tramp-make-tramp-file-name
-                        method user host
-                        (mapconcat 'identity
-                                   (append '("")
-                                           (reverse result)
-                                           (list thisstep))
-                                   "/")))))
-         (cond ((string= "." thisstep)
-                (tramp-message v 5 "Ignoring step `.'"))
-               ((string= ".." thisstep)
-                (tramp-message v 5 "Processing step `..'")
-                (pop result))
-               ((stringp symlink-target)
-                ;; It's a symlink, follow it.
-                (tramp-message v 5 "Follow symlink to %s" symlink-target)
-                (setq numchase (1+ numchase))
-                (when (file-name-absolute-p symlink-target)
-                  (setq result nil))
-                ;; If the symlink was absolute, we'll get a string like
-                ;; "/user@host:/some/target"; extract the
-                ;; "/some/target" part from it.
-                (when (tramp-tramp-file-p symlink-target)
-                  (unless (tramp-equal-remote filename symlink-target)
-                    (tramp-error
-                     v 'file-error
-                     "Symlink target `%s' on wrong host" symlink-target))
-                  (setq symlink-target localname))
-                (setq steps
-                      (append (tramp-compat-split-string symlink-target "/")
-                              steps)))
-               (t
-                ;; It's a file.
-                (setq result (cons thisstep result)))))
-       (when (>= numchase numchase-limit)
-         (tramp-error
-          v 'file-error
-          "Maximum number (%d) of symlinks exceeded" numchase-limit))
-       (setq result (reverse result))
-       ;; Combine list to form string.
-       (setq result
-             (if result
-                 (mapconcat 'identity (cons "" result) "/")
-               "/"))
-       (when (and is-dir (or (string= "" result)
-                             (not (string= (substring result -1) "/"))))
-         (setq result (concat result "/")))
-       (tramp-message v 4 "True name of `%s' is `%s'" filename result)
-       (tramp-make-tramp-file-name method user host result)))))
+             (when (and is-dir (or (string= "" result)
+                                   (not (string= (substring result -1) "/"))))
+               (setq result (concat result "/"))))))
+
+        (tramp-message v 4 "True name of `%s' is `%s'" filename result)
+        (tramp-make-tramp-file-name method user host result)))))
 
 ;; Basic functions.
 
@@ -2493,12 +2663,16 @@ target of the symlink differ."
   "Like `file-exists-p' for Tramp files."
   (with-parsed-tramp-file-name filename nil
     (with-file-property v localname "file-exists-p"
-      (zerop (tramp-send-command-and-check
-             v
-             (format
-              "%s %s"
-              (tramp-get-file-exists-command v)
-              (tramp-shell-quote-argument localname)))))))
+      (or (not (null (tramp-get-file-property
+                      v localname "file-attributes-integer" nil)))
+          (not (null (tramp-get-file-property
+                      v localname "file-attributes-string" nil)))
+          (zerop (tramp-send-command-and-check
+                  v
+                  (format
+                   "%s %s"
+                   (tramp-get-file-exists-command v)
+                   (tramp-shell-quote-argument localname))))))))
 
 ;; Inodes don't exist for some file systems.  Therefore we must
 ;; generate virtual ones.  Used in `find-buffer-visiting'.  The method
@@ -2827,13 +3001,19 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
   "Like `file-executable-p' for Tramp files."
   (with-parsed-tramp-file-name filename nil
     (with-file-property v localname "file-executable-p"
-      (zerop (tramp-run-test "-x" filename)))))
+      ;; Examine `file-attributes' cache to see if request can be
+      ;; satisfied without remote operation.
+      (or (tramp-check-cached-permissions v ?x)
+          (zerop (tramp-run-test "-x" filename))))))
 
 (defun tramp-handle-file-readable-p (filename)
   "Like `file-readable-p' for Tramp files."
   (with-parsed-tramp-file-name filename nil
     (with-file-property v localname "file-readable-p"
-      (zerop (tramp-run-test "-r" filename)))))
+      ;; Examine `file-attributes' cache to see if request can be
+      ;; satisfied without remote operation.
+      (or (tramp-check-cached-permissions v ?r)
+          (zerop (tramp-run-test "-r" filename))))))
 
 ;; When the remote shell is started, it looks for a shell which groks
 ;; tilde expansion.  Here, we assume that all shells which grok tilde
@@ -2923,8 +3103,10 @@ value of `default-file-modes', without execute permissions."
   (with-parsed-tramp-file-name filename nil
     (with-file-property v localname "file-writable-p"
       (if (file-exists-p filename)
-         ;; Existing files must be writable.
-         (zerop (tramp-run-test "-w" filename))
+         ;; Examine `file-attributes' cache to see if request can be
+         ;; satisfied without remote operation.
+          (or (tramp-check-cached-permissions v ?w)
+              (zerop (tramp-run-test "-w" filename)))
        ;; If file doesn't exist, check if directory is writable.
        (and (zerop (tramp-run-test
                     "-d" (file-name-directory filename)))
@@ -2963,7 +3145,7 @@ value of `default-file-modes', without execute permissions."
   "Like `directory-files' for Tramp files."
   ;; FILES-ONLY is valid for XEmacs only.
   (when (file-directory-p directory)
-    (setq directory (expand-file-name directory))
+    (setq directory (file-name-as-directory (expand-file-name directory)))
     (let ((temp (nreverse (file-name-all-completions "" directory)))
          result item)
 
@@ -2971,13 +3153,13 @@ value of `default-file-modes', without execute permissions."
        (setq item (directory-file-name (pop temp)))
        (when (and (or (null match) (string-match match item))
                   (or (null files-only)
-                      ;; files only
+                      ;; Files only.
                       (and (equal files-only t) (file-regular-p item))
-                      ;; directories only
+                      ;; Directories only.
                       (file-directory-p item)))
-         (push (if full (expand-file-name item directory) item)
+         (push (if full (concat directory item) item)
                result)))
-      result)))
+      (if nosort result (sort result 'string<)))))
 
 (defun tramp-handle-directory-files-and-attributes
   (directory &optional full match nosort id-format)
@@ -2986,7 +3168,7 @@ value of `default-file-modes', without execute permissions."
   (when (file-directory-p directory)
     (setq directory (expand-file-name directory))
     (let* ((temp
-           (tramp-compat-copy-tree
+           (copy-tree
             (with-parsed-tramp-file-name directory nil
               (with-file-property
                   v localname
@@ -3058,52 +3240,155 @@ value of `default-file-modes', without execute permissions."
   "Like `file-name-all-completions' for Tramp files."
   (unless (save-match-data (string-match "/" filename))
     (with-parsed-tramp-file-name (expand-file-name directory) nil
-      ;; Flush the directory cache.  There could be changed directory
-      ;; contents.
-      (when (and (integerp tramp-completion-reread-directory-timeout)
-                (> (tramp-time-diff
-                    (current-time)
-                    (tramp-get-file-property
-                     v localname "last-completion" '(0 0 0)))
-                   tramp-completion-reread-directory-timeout))
-       (tramp-flush-file-property v localname))
 
       (all-completions
        filename
        (mapcar
        'list
-       (with-file-property v localname "file-name-all-completions"
-         (let (result)
-          (tramp-barf-unless-okay
-           v
-           (format "cd %s" (tramp-shell-quote-argument localname))
-           "tramp-handle-file-name-all-completions: Couldn't `cd %s'"
-           (tramp-shell-quote-argument localname))
-
-          ;; Get a list of directories and files, including reliably
-          ;; tagging the directories with a trailing '/'.  Because I
-          ;; rock.  --daniel@danann.net
-          (tramp-send-command
-           v
-           (format (concat "%s -a 2>/dev/null | while read f; do "
-                           "if %s -d \"$f\" 2>/dev/null; "
-                           "then echo \"$f/\"; else echo \"$f\"; fi; done")
-                   (tramp-get-ls-command v)
-                   (tramp-get-test-command v)))
-
-          ;; Now grab the output.
-          (with-current-buffer (tramp-get-buffer v)
-            (goto-char (point-max))
-            (while (zerop (forward-line -1))
-              (push (buffer-substring
-                     (point) (tramp-compat-line-end-position))
-                    result)))
-
-          (tramp-set-file-property
-           v localname "last-completion" (current-time))
-          result)))))))
-
-;; The following isn't needed for Emacs 20 but for 19.34?
+        (or
+         ;; Try cache first
+         (and
+          ;; Ignore if expired
+          (or (not (integerp tramp-completion-reread-directory-timeout))
+              (<= (tramp-time-diff
+                   (current-time)
+                   (tramp-get-file-property
+                    v localname "last-completion" '(0 0 0)))
+                  tramp-completion-reread-directory-timeout))
+
+          ;; Try cache entries for filename, filename with last
+          ;; character removed, filename with last two characters
+          ;; removed, ..., and finally the empty string - all
+          ;; concatenated to the local directory name
+
+          ;; This is inefficient for very long filenames, pity
+          ;; `reduce' is not available...
+          (car
+           (apply
+            'append
+            (mapcar
+             (lambda (x)
+               (let ((cache-hit
+                      (tramp-get-file-property
+                       v
+                       (concat localname (substring filename 0 x))
+                       "file-name-all-completions"
+                       nil)))
+                 (when cache-hit (list cache-hit))))
+             (tramp-compat-number-sequence (length filename) 0 -1)))))
+
+         ;; Cache expired or no matching cache entry found so we need
+         ;; to perform a remote operation
+         (let (result)
+           ;; Get a list of directories and files, including reliably
+           ;; tagging the directories with a trailing '/'.  Because I
+           ;; rock.  --daniel@danann.net
+
+           ;; Changed to perform `cd' in the same remote op and only
+           ;; get entries starting with `filename'. Capture any `cd'
+           ;; error messages.  Ensure any `cd' and `echo' aliases are
+           ;; ignored.
+           (tramp-send-command
+            v
+            (if (tramp-get-remote-perl v)
+                (progn
+                  (tramp-maybe-send-script
+                   v tramp-perl-file-name-all-completions
+                   "tramp_perl_file_name_all_completions")
+                  (format "tramp_perl_file_name_all_completions %s %s %d"
+                          (tramp-shell-quote-argument localname)
+                          (tramp-shell-quote-argument filename)
+                          (if (symbol-value
+                              ;; `read-file-name-completion-ignore-case'
+                              ;; is introduced with Emacs 22.1.
+                              (if (boundp
+                                   'read-file-name-completion-ignore-case)
+                                  'read-file-name-completion-ignore-case
+                                'completion-ignore-case))
+                             1 0)))
+
+              (format (concat
+                       "(\\cd %s 2>&1 && (%s %s -a 2>/dev/null"
+                       ;; `ls' with wildcard might fail with `Argument
+                       ;; list too long' error in some corner cases; if
+                       ;; `ls' fails after `cd' succeeded, chances are
+                       ;; that's the case, so let's retry without
+                       ;; wildcard.  This will return "too many" entries
+                       ;; but that isn't harmful.
+                       " || %s -a 2>/dev/null)"
+                       " | while read f; do"
+                       " if %s -d \"$f\" 2>/dev/null;"
+                       " then \\echo \"$f/\"; else \\echo \"$f\"; fi; done"
+                       " && \\echo ok) || \\echo fail")
+                      (tramp-shell-quote-argument localname)
+                      (tramp-get-ls-command v)
+                      ;; When `filename' is empty, just `ls' without
+                      ;; filename argument is more efficient than `ls *'
+                      ;; for very large directories and might avoid the
+                      ;; `Argument list too long' error.
+                      ;;
+                      ;; With and only with wildcard, we need to add
+                      ;; `-d' to prevent `ls' from descending into
+                      ;; sub-directories.
+                      (if (zerop (length filename))
+                          "."
+                        (concat (tramp-shell-quote-argument filename) "* -d"))
+                      (tramp-get-ls-command v)
+                      (tramp-get-test-command v))))
+
+           ;; Now grab the output.
+           (with-current-buffer (tramp-get-buffer v)
+             (goto-char (point-max))
+
+             ;; Check result code, found in last line of output
+             (forward-line -1)
+             (if (looking-at "^fail$")
+                 (progn
+                   ;; Grab error message from line before last line
+                   ;; (it was put there by `cd 2>&1')
+                   (forward-line -1)
+                   (tramp-error
+                    v 'file-error
+                    "tramp-handle-file-name-all-completions: %s"
+                    (buffer-substring
+                     (point) (tramp-compat-line-end-position))))
+               ;; For peace of mind, if buffer doesn't end in `fail'
+               ;; then it should end in `ok'.  If neither are in the
+               ;; buffer something went seriously wrong on the remote
+               ;; side.
+               (unless (looking-at "^ok$")
+                 (tramp-error
+                  v 'file-error
+                  "\
+tramp-handle-file-name-all-completions: internal error accessing `%s': `%s'"
+                  (tramp-shell-quote-argument localname) (buffer-string))))
+
+             (while (zerop (forward-line -1))
+               (push (buffer-substring
+                      (point) (tramp-compat-line-end-position))
+                     result)))
+
+           ;; Because the remote op went through OK we know the
+           ;; directory we `cd'-ed to exists
+           (tramp-set-file-property
+            v localname "file-exists-p" t)
+
+           ;; Because the remote op went through OK we know every
+           ;; file listed by `ls' exists.
+           (mapc (lambda (entry)
+                  (tramp-set-file-property
+                   v (concat localname entry) "file-exists-p" t))
+                result)
+
+           (tramp-set-file-property
+            v localname "last-completion" (current-time))
+
+           ;; Store result in the cache
+           (tramp-set-file-property
+            v (concat localname filename)
+            "file-name-all-completions"
+            result))))))))
+
 (defun tramp-handle-file-name-completion
   (filename directory &optional predicate)
   "Like `file-name-completion' for Tramp files."
@@ -3142,6 +3427,7 @@ value of `default-file-modes', without execute permissions."
          (tramp-error
           v2 'file-error
           "add-name-to-file: file %s already exists" newname))
+       (tramp-flush-file-property v2 (file-name-directory v2-localname))
        (tramp-flush-file-property v2 v2-localname)
        (tramp-barf-unless-okay
         v1
@@ -3181,8 +3467,9 @@ value of `default-file-modes', without execute permissions."
               ;; When DIRNAME and NEWNAME are remote, they must have
               ;; the same method.
               (or (null t1) (null t2)
-                  (string-equal (file-remote-p dirname 'method)
-                                (file-remote-p newname 'method))))
+                  (string-equal
+                   (tramp-file-name-method (tramp-dissect-file-name dirname))
+                   (tramp-file-name-method (tramp-dissect-file-name newname)))))
          ;; scp or rsync DTRT.
          (progn
            (setq dirname (directory-file-name (expand-file-name dirname))
@@ -3199,7 +3486,13 @@ value of `default-file-modes', without execute permissions."
             'copy dirname newname keep-date))
        ;; We must do it file-wise.
        (tramp-run-real-handler
-        'copy-directory (list dirname newname keep-date parents))))))
+        'copy-directory (list dirname newname keep-date parents)))
+
+      ;; When newname did exist, we have wrong cached values.
+      (when t2
+       (with-parsed-tramp-file-name newname nil
+         (tramp-flush-file-property v (file-name-directory localname))
+         (tramp-flush-file-property v localname))))))
 
 (defun tramp-handle-rename-file
   (filename newname &optional ok-if-already-exists)
@@ -3233,7 +3526,8 @@ and `rename'.  FILENAME and NEWNAME must be absolute file names."
   (unless (memq op '(copy rename))
     (error "Unknown operation `%s', must be `copy' or `rename'" op))
   (let ((t1 (tramp-tramp-file-p filename))
-       (t2 (tramp-tramp-file-p newname)))
+       (t2 (tramp-tramp-file-p newname))
+       pr tm)
 
     (when (and (not ok-if-already-exists) (file-exists-p newname))
       (with-parsed-tramp-file-name (if t1 filename newname) nil
@@ -3243,7 +3537,16 @@ and `rename'.  FILENAME and NEWNAME must be absolute file names."
     (with-parsed-tramp-file-name (if t1 filename newname) nil
       (tramp-message v 0 "Transferring %s to %s..." filename newname))
 
-    (prog1
+    ;; We start a pulsing progress reporter.  Introduced in Emacs 24.1.
+    (when (> (nth 7 (file-attributes filename)) tramp-copy-size-limit)
+      (condition-case nil
+         (setq pr (funcall
+                   'make-progress-reporter
+                   (format "Transferring %s to %s..." filename newname))
+               tm (run-at-time 0 0.1 'progress-reporter-update pr))
+       (error nil)))
+
+    (unwind-protect
        (cond
         ;; Both are Tramp files.
         ((and t1 t2)
@@ -3304,13 +3607,17 @@ and `rename'.  FILENAME and NEWNAME must be absolute file names."
       ;; In case of `rename', we must flush the cache of the source file.
       (when (and t1 (eq op 'rename))
        (with-parsed-tramp-file-name filename nil
+         (tramp-flush-file-property v (file-name-directory localname))
          (tramp-flush-file-property v localname)))
 
       ;; When newname did exist, we have wrong cached values.
       (when t2
        (with-parsed-tramp-file-name newname nil
+         (tramp-flush-file-property v (file-name-directory localname))
          (tramp-flush-file-property v localname)))
 
+      ;; Stop progress reporter.
+      (if tm (cancel-timer tm))
       (with-parsed-tramp-file-name (if t1 filename newname) nil
        (tramp-message v 0 "Transferring %s to %s...done" filename newname)))))
 
@@ -3361,19 +3668,25 @@ the uid and gid from FILENAME."
                            "Unknown operation `%s', must be `copy' or `rename'"
                            op))))
             (localname1
-             (if t1 (tramp-handle-file-remote-p filename 'localname) filename))
+             (if t1
+                 (tramp-file-name-handler 'file-remote-p filename 'localname)
+               filename))
             (localname2
-             (if t2 (tramp-handle-file-remote-p newname 'localname) newname))
-            (prefix (file-remote-p (if t1 filename newname))))
+             (if t2
+                 (tramp-file-name-handler 'file-remote-p newname 'localname)
+               newname))
+            (prefix (file-remote-p (if t1 filename newname)))
+             cmd-result)
 
        (cond
         ;; Both files are on a remote host, with same user.
         ((and t1 t2)
-         (tramp-send-command
-          v
-          (format "%s %s %s" cmd
-                  (tramp-shell-quote-argument localname1)
-                  (tramp-shell-quote-argument localname2)))
+          (setq cmd-result
+                (tramp-send-command-and-check
+                 v
+                 (format "%s %s %s" cmd
+                         (tramp-shell-quote-argument localname1)
+                         (tramp-shell-quote-argument localname2))))
          (with-current-buffer (tramp-get-buffer v)
            (goto-char (point-min))
            (unless
@@ -3382,7 +3695,7 @@ the uid and gid from FILENAME."
                      ;; Mask cp -f error.
                      (re-search-forward
                       tramp-operation-not-permitted-regexp nil t))
-                (zerop (tramp-send-command-and-check v nil)))
+                (zerop cmd-result))
              (tramp-error-with-buffer
               nil v 'file-error
               "Copying directly failed, see buffer `%s' for details."
@@ -3508,7 +3821,12 @@ The method used must be an out-of-band method."
 
          ;; Both are Tramp files.  We shall optimize it, when the
          ;; methods for filename and newname are the same.
-         (let ((tmpfile (tramp-compat-make-temp-file localname)))
+         (let* ((dir-flag (file-directory-p filename))
+                (tmpfile (tramp-compat-make-temp-file localname dir-flag)))
+           (if dir-flag
+               (setq tmpfile
+                     (expand-file-name
+                      (file-name-nondirectory newname) tmpfile)))
            (unwind-protect
                (progn
                  (tramp-do-copy-or-rename-file-out-of-band
@@ -3517,7 +3835,10 @@ The method used must be an out-of-band method."
                   'rename tmpfile newname keep-date))
              ;; Save exit.
              (condition-case nil
-                 (delete-file tmpfile)
+                 (if dir-flag
+                     (tramp-compat-delete-directory
+                      (expand-file-name ".." tmpfile) 'recursive)
+                   (delete-file tmpfile))
                (error))))
 
        ;; Expand hops.  Might be necessary for gateway methods.
@@ -3542,10 +3863,11 @@ The method used must be an out-of-band method."
              port (or (and port (number-to-string port)) ""))
 
        ;; Compose copy command.
-       (setq spec `((?h . ,host) (?u . ,user) (?p . ,port)
-                    (?t . ,(tramp-get-connection-property
-                            (tramp-get-connection-process v) "temp-file" ""))
-                    (?k . ,(if keep-date " " "")))
+       (setq spec (format-spec-make
+                   ?h host ?u user ?p port
+                   ?t (tramp-get-connection-property
+                       (tramp-get-connection-process v) "temp-file" "")
+                   ?k (if keep-date " " ""))
              copy-program (tramp-get-method-parameter
                            method 'tramp-copy-program)
              copy-keep-date (tramp-get-method-parameter
@@ -3578,6 +3900,12 @@ The method used must be an out-of-band method."
          (tramp-error
           v 'file-error "Cannot find copy program: %s" copy-program))
 
+       ;; Set variables for computing the prompt for reading
+       ;; password.
+       (setq tramp-current-method (tramp-file-name-method v)
+             tramp-current-user   (tramp-file-name-user v)
+             tramp-current-host   (tramp-file-name-host v))
+
        (unwind-protect
            (with-temp-buffer
              ;; The default directory must be remote.
@@ -3622,11 +3950,14 @@ The method used must be an out-of-band method."
 
        ;; Set the mode.
        (unless (and keep-date copy-keep-date)
-         (set-file-modes newname (tramp-default-file-modes filename))))
+         (ignore-errors
+           (set-file-modes newname (tramp-default-file-modes filename)))))
 
       ;; If the operation was `rename', delete the original file.
       (unless (eq op 'copy)
-       (delete-file filename)))))
+       (if (file-regular-p filename)
+           (delete-file filename)
+         (tramp-compat-delete-directory filename 'recursive))))))
 
 (defun tramp-handle-make-directory (dir &optional parents)
   "Like `make-directory' for Tramp files."
@@ -3645,6 +3976,7 @@ The method used must be an out-of-band method."
   "Like `delete-directory' for Tramp files."
   (setq directory (expand-file-name directory))
   (with-parsed-tramp-file-name directory nil
+    (tramp-flush-file-property v (file-name-directory localname))
     (tramp-flush-directory-property v localname)
     (unless (zerop (tramp-send-command-and-check
                    v
@@ -3658,6 +3990,7 @@ The method used must be an out-of-band method."
   "Like `delete-file' for Tramp files."
   (setq filename (expand-file-name filename))
   (with-parsed-tramp-file-name filename nil
+    (tramp-flush-file-property v (file-name-directory localname))
     (tramp-flush-file-property v localname)
     (unless (zerop (tramp-send-command-and-check
                    v
@@ -3687,6 +4020,7 @@ This is like `dired-recursive-delete-directory' for Tramp files."
     ;; This might take a while, allow it plenty of time.
     (tramp-wait-for-output (tramp-get-connection-process v) 120)
     ;; Make sure that it worked...
+    (tramp-flush-file-property v (file-name-directory localname))
     (tramp-flush-directory-property v localname)
     (and (file-exists-p filename)
         (tramp-error
@@ -3725,7 +4059,8 @@ This is like `dired-recursive-delete-directory' for Tramp files."
               ;; We found an uncompression rule.
               (tramp-message v 0 "Uncompressing %s..." file)
               (when (zerop (tramp-send-command-and-check
-                            v (concat (nth 2 suffix) " " localname)))
+                            v (concat (nth 2 suffix) " "
+                                      (tramp-shell-quote-argument localname))))
                 (tramp-message v 0 "Uncompressing %s...done" file)
                 ;; `dired-remove-file' is not defined in XEmacs
                 (funcall (symbol-function 'dired-remove-file) file)
@@ -3736,7 +4071,8 @@ This is like `dired-recursive-delete-directory' for Tramp files."
               ;; Try gzip.
               (tramp-message v 0 "Compressing %s..." file)
               (when (zerop (tramp-send-command-and-check
-                            v (concat "gzip -f " localname)))
+                            v (concat "gzip -f "
+                                      (tramp-shell-quote-argument localname))))
                 (tramp-message v 0 "Compressing %s...done" file)
                 ;; `dired-remove-file' is not defined in XEmacs
                 (funcall (symbol-function 'dired-remove-file) file)
@@ -3746,9 +4082,11 @@ This is like `dired-recursive-delete-directory' for Tramp files."
                        (concat file ".z"))
                       (t nil)))))))))
 
-(defun tramp-handle-dired-uncache (dir)
+(defun tramp-handle-dired-uncache (dir &optional dir-p)
   "Like `dired-uncache' for Tramp files."
-  (with-parsed-tramp-file-name dir nil
+  ;; DIR-P is valid for XEmacs only.
+  (with-parsed-tramp-file-name
+      (if (or dir-p (file-directory-p dir)) dir (file-name-directory dir)) nil
     (tramp-flush-file-property v localname)))
 
 ;; Pacify byte-compiler.  The function is needed on XEmacs only.  I'm
@@ -3773,30 +4111,31 @@ This is like `dired-recursive-delete-directory' for Tramp files."
             (not (symbol-value 'ls-lisp-use-insert-directory-program)))
        (tramp-run-real-handler
         'insert-directory (list filename switches wildcard full-directory-p))
-      (when (and (string-match "^--dired\\s-+" switches)
+      (when (stringp switches)
+        (setq switches (split-string switches)))
+      (when (and (member "--dired" switches)
                 (not (tramp-get-ls-command-with-dired v)))
-       (setq switches (replace-match "" nil t switches)))
-      (tramp-message
-       v 4 "Inserting directory `ls %s %s', wildcard %s, fulldir %s"
-       switches filename (if wildcard "yes" "no")
-       (if full-directory-p "yes" "no"))
+       (setq switches (delete "--dired" switches)))
       (when wildcard
         (setq wildcard (tramp-run-real-handler
                        'file-name-nondirectory (list localname)))
         (setq localname (tramp-run-real-handler
                         'file-name-directory (list localname))))
-      (when (listp switches)
-        (setq switches (mapconcat 'identity switches " ")))
       (unless full-directory-p
-        (setq switches (concat "-d " switches)))
+        (setq switches (add-to-list 'switches "-d" 'append)))
+      (setq switches (mapconcat 'tramp-shell-quote-argument switches " "))
       (when wildcard
-        (setq switches (concat switches " " wildcard)))
+       (setq switches (concat switches " " wildcard)))
+      (tramp-message
+       v 4 "Inserting directory `ls %s %s', wildcard %s, fulldir %s"
+       switches filename (if wildcard "yes" "no")
+       (if full-directory-p "yes" "no"))
       ;; If `full-directory-p', we just say `ls -l FILENAME'.
       ;; Else we chdir to the parent directory, then say `ls -ld BASENAME'.
       (if full-directory-p
          (tramp-send-command
           v
-          (format "%s %s %s"
+          (format "%s %s %s 2>/dev/null"
                   (tramp-get-ls-command v)
                   switches
                   (if wildcard
@@ -3833,6 +4172,8 @@ This is like `dired-recursive-delete-directory' for Tramp files."
 
        ;; Check for "--dired" output.
        (forward-line -2)
+       (when (looking-at "//SUBDIRED//")
+         (forward-line -1))
        (when (looking-at "//DIRED//")
          (let ((end (tramp-compat-line-end-position))
                (linebeg (point)))
@@ -3845,13 +4186,26 @@ This is like `dired-recursive-delete-directory' for Tramp files."
                    (end (+ beg (read (current-buffer)))))
                (if (memq (char-after end) '(?\n ?\ ))
                    ;; End is followed by \n or by " -> ".
-                   (put-text-property start end 'dired-filename t)))))
-         ;; Remove trailing lines.
-         (goto-char (tramp-compat-line-beginning-position))
-         (while (looking-at "//")
-           (forward-line 1)
-           (delete-region (match-beginning 0) (point)))))
-      (goto-char (point-max)))))
+                   (put-text-property start end 'dired-filename t))))))
+       ;; Remove trailing lines.
+       (goto-char (tramp-compat-line-beginning-position))
+       (while (looking-at "//")
+         (forward-line 1)
+         (delete-region (match-beginning 0) (point)))
+
+       ;; The inserted file could be from somewhere else.
+       (when (and (not wildcard) (not full-directory-p))
+         (goto-char (point-max))
+         (when (file-symlink-p filename)
+           (goto-char (search-backward "->" beg 'noerror)))
+         (search-backward
+          (if (zerop (length (file-name-nondirectory filename)))
+              "."
+            (file-name-nondirectory filename))
+          beg 'noerror)
+         (replace-match (file-relative-name filename) t))
+
+       (goto-char (point-max))))))
 
 (defun tramp-handle-unhandled-file-name-directory (filename)
   "Like `unhandled-file-name-directory' for Tramp files."
@@ -3894,11 +4248,13 @@ the result will be a local, non-Tramp, filename."
                     (string-match "\\`su\\(do\\)?\\'" method))
            (setq uname (concat uname user)))
          (setq uname
-           (with-connection-property v uname
-             (tramp-send-command v (format "cd %s; pwd" uname))
-             (with-current-buffer (tramp-get-buffer v)
-               (goto-char (point-min))
-               (buffer-substring (point) (tramp-compat-line-end-position)))))
+               (with-connection-property v uname
+                 (tramp-send-command
+                  v (format "cd %s; pwd" (tramp-shell-quote-argument uname)))
+                 (with-current-buffer (tramp-get-buffer v)
+                   (goto-char (point-min))
+                   (buffer-substring
+                    (point) (tramp-compat-line-end-position)))))
          (setq localname (concat uname fname))))
       ;; There might be a double slash, for example when "~/"
       ;; expands to "/".  Remove this.
@@ -3922,9 +4278,11 @@ the result will be a local, non-Tramp, filename."
   "Replace environment variables in FILENAME.
 Return the string with the replaced variables."
   (save-match-data
-    (let ((idx (string-match "$\\w+" filename)))
+    (let ((idx (string-match "$\\(\\w+\\)" filename)))
       ;; `$' is coded as `$$'.
-      (when (and idx (or (zerop idx) (not (eq ?$ (aref filename (1- idx))))))
+      (when (and idx
+                (or (zerop idx) (not (eq ?$ (aref filename (1- idx)))))
+                (getenv (match-string 1 filename)))
        (setq filename
              (replace-match
               (substitute-in-file-name (match-string 0 filename))
@@ -3981,7 +4339,13 @@ beginning of local filename are not substituted."
               (delete-region (point-min) (point))
               (insert (substitute-in-file-name s))
               (setq ad-return-value last-command-char))
-          ad-do-it))))
+          ad-do-it)))
+     (eval
+      `(add-hook
+       'tramp-unload-hook
+       (lambda ()
+         (ad-remove-advice ',x 'around ',(intern (format "tramp-advice-%s" x)))
+         (ad-activate ',x)))))
 
    '(minibuffer-electric-separator
      minibuffer-electric-tilde)))
@@ -4110,20 +4474,21 @@ beginning of local filename are not substituted."
        (setq outbuf (current-buffer))))
       (when stderr (setq command (format "%s 2>%s" command stderr)))
 
-      ;; Goto working directory.
-      (tramp-send-command
-       v (format "cd %s" (tramp-shell-quote-argument localname)))
       ;; Send the command.  It might not return in time, so we protect it.
       (condition-case nil
          (unwind-protect
-             (tramp-send-command v command)
+              (setq ret
+                    (tramp-send-command-and-check
+                     v (format "\\cd %s; %s"
+                               (tramp-shell-quote-argument localname)
+                               command)
+                    nil t))
            ;; We should show the output anyway.
            (when outbuf
-             (let ((output-string
-                    (with-current-buffer (tramp-get-connection-buffer v)
-                      (buffer-substring (point-min) (point-max)))))
-               (with-current-buffer outbuf
-                 (insert output-string)))
+             (with-current-buffer outbuf
+                (insert
+                 (with-current-buffer (tramp-get-connection-buffer v)
+                   (buffer-string))))
              (when display (display-buffer outbuf))))
        ;; When the user did interrupt, we should do it also.  We use
        ;; return code -1 as marker.
@@ -4135,8 +4500,6 @@ beginning of local filename are not substituted."
         (kill-buffer (tramp-get-connection-buffer v))
         (setq ret 1)))
 
-      ;; Check return code.
-      (unless ret (setq ret (tramp-send-command-and-check v nil)))
       ;; Provide error file.
       (when tmpstderr (rename-file tmpstderr (cadr destination) t))
 
@@ -4349,17 +4712,21 @@ Lisp error raised when PROGRAM is nil is trapped also, returning 1."
 
 (defun tramp-handle-file-remote-p (filename &optional identification connected)
   "Like `file-remote-p' for Tramp files."
-  (when (tramp-tramp-file-p filename)
-    (with-parsed-tramp-file-name filename nil
-      (and (or (not connected)
-              (let ((p (tramp-get-connection-process v)))
-                (and p (processp p) (memq (process-status p) '(run open)))))
-          (cond
-           ((eq identification 'method) method)
-           ((eq identification 'user) user)
-           ((eq identification 'host) host)
-           ((eq identification 'localname) localname)
-           (t (tramp-make-tramp-file-name method user host "")))))))
+  (let ((tramp-verbose 3))
+    (when (tramp-tramp-file-p filename)
+      (let* ((v (tramp-dissect-file-name filename))
+            (p (tramp-get-connection-process v))
+            (c (and p (processp p) (memq (process-status p) '(run open)))))
+       ;; We expand the file name only, if there is already a connection.
+       (with-parsed-tramp-file-name
+           (if c (expand-file-name filename) filename) nil
+         (and (or (not connected) c)
+              (cond
+               ((eq identification 'method) method)
+               ((eq identification 'user) user)
+               ((eq identification 'host) host)
+               ((eq identification 'localname) localname)
+               (t (tramp-make-tramp-file-name method user host "")))))))))
 
 (defun tramp-find-file-name-coding-system-alist (filename tmpname)
   "Like `find-operation-coding-system' for Tramp filenames.
@@ -4429,11 +4796,29 @@ coding system might not be determined.  This function repairs it."
                           (when (eq inhibit-file-name-operation
                                     'insert-file-contents)
                             'file-local-copy)))
-                     (file-local-copy
-                      (if (stringp remote-copy)
-                          (tramp-make-tramp-file-name
-                           method user host remote-copy)
-                        filename))))
+                     (cond
+                      ((stringp remote-copy)
+                       (file-local-copy
+                        (tramp-make-tramp-file-name
+                         method user host remote-copy)))
+                      ((stringp tramp-temp-buffer-file-name)
+                       (copy-file filename tramp-temp-buffer-file-name 'ok)
+                       tramp-temp-buffer-file-name)
+                      (t (file-local-copy filename)))))
+
+             ;; When the file is not readable for the owner, it
+             ;; cannot be inserted, even it is redable for the group
+             ;; or for everybody.
+             (set-file-modes local-copy (tramp-octal-to-decimal "0600"))
+
+             (when (and (null remote-copy)
+                        (tramp-get-method-parameter
+                         method 'tramp-copy-keep-tmpfile))
+               ;; We keep the local file for performance reasons,
+               ;; useful for "rsync".
+               (setq tramp-temp-buffer-file-name local-copy)
+               (put 'tramp-temp-buffer-file-name 'permanent-local t))
+
              (tramp-message
               v 4 "Inserting local temp file `%s'..." local-copy)
 
@@ -4463,7 +4848,8 @@ coding system might not be determined.  This function repairs it."
            (setq buffer-read-only (not (file-writable-p filename)))
            (set-visited-file-modtime)
            (set-buffer-modified-p nil))
-         (when (stringp local-copy)
+         (when (and (stringp local-copy)
+                    (or remote-copy (null tramp-temp-buffer-file-name)))
            (delete-file local-copy))
          (when (stringp remote-copy)
            (delete-file
@@ -4500,9 +4886,9 @@ coding system might not be determined.  This function repairs it."
   "Like `find-backup-file-name' for Tramp files."
   (with-parsed-tramp-file-name filename nil
     ;; We set both variables. It doesn't matter whether it is
-    ;; Emacs or XEmacs
+    ;; Emacs or XEmacs.
     (let ((backup-directory-alist
-          ;; Emacs case
+          ;; Emacs case.
           (when (boundp 'backup-directory-alist)
             (if (symbol-value 'tramp-backup-directory-alist)
                 (mapcar
@@ -4518,7 +4904,7 @@ coding system might not be determined.  This function repairs it."
               (symbol-value 'backup-directory-alist))))
 
          (bkup-backup-directory-info
-          ;; XEmacs case
+          ;; XEmacs case.
           (when (boundp 'bkup-backup-directory-info)
             (if (symbol-value 'tramp-bkup-backup-directory-info)
                 (mapcar
@@ -4583,15 +4969,12 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
 (defvar tramp-handle-write-region-hook nil
   "Normal hook to be run at the end of `tramp-handle-write-region'.")
 
-;; CCC grok APPEND, LOCKNAME
+;; CCC grok LOCKNAME
 (defun tramp-handle-write-region
   (start end filename &optional append visit lockname confirm)
   "Like `write-region' for Tramp files."
   (setq filename (expand-file-name filename))
   (with-parsed-tramp-file-name filename nil
-    (unless (null append)
-      (tramp-error
-       v 'file-error "Cannot append to file using Tramp (`%s')" filename))
     ;; Following part commented out because we don't know what to do about
     ;; file locking, and it does not appear to be a problem to ignore it.
     ;; Ange-ftp ignores it, too.
@@ -4621,11 +5004,9 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
                  (or (file-directory-p localname)
                      (file-writable-p localname)))))
          ;; Short track: if we are on the local host, we can run directly.
-         (progn
-           (tramp-run-real-handler
-            'write-region
-            (list start end localname append 'no-message lockname confirm))
-           (tramp-flush-file-property v localname))
+         (tramp-run-real-handler
+          'write-region
+          (list start end localname append 'no-message lockname confirm))
 
        (let ((rem-dec (tramp-get-remote-coding v "remote-decoding"))
              (loc-enc (tramp-get-local-coding v "local-encoding"))
@@ -4643,7 +5024,12 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
              ;; needed if we use an encoding function, but currently
              ;; we use it always because this makes the logic
              ;; simpler.
-             (tmpfile (tramp-compat-make-temp-file filename)))
+             (tmpfile (or tramp-temp-buffer-file-name
+                          (tramp-compat-make-temp-file filename))))
+
+         ;; If `append' is non-nil, we copy the file locally, and let
+         ;; the native `write-region' implementation do the job.
+         (when append (copy-file filename tmpfile 'ok))
 
          ;; We say `no-message' here because we don't want the
          ;; visited file modtime data to be clobbered from the temp
@@ -4657,6 +5043,7 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
                 'write-region
                 (list start end tmpfile append 'no-message lockname confirm))
              ((error quit)
+              (setq tramp-temp-buffer-file-name nil)
               (delete-file tmpfile)
               (signal (car err) (cdr err))))
 
@@ -4669,7 +5056,10 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
          ;; filename does not exist (eq modes nil) it has been
          ;; renamed to the backup file.  This case `save-buffer'
          ;; handles permissions.
-         (when modes (set-file-modes tmpfile modes))
+         ;; Ensure, that it is still readable.
+         (when modes
+           (set-file-modes
+            tmpfile (logior (or modes 0) (tramp-octal-to-decimal "0400"))))
 
          ;; This is a bit lengthy due to the different methods
          ;; possible for file transfer.  First, we check whether the
@@ -4679,15 +5069,30 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
          ;; encoding function, then that is used for encoding the
          ;; contents of the tmp file.
          (cond
-          ;; `rename-file' handles direct copy and out-of-band methods.
+          ;; `copy-file' handles direct copy and out-of-band methods.
           ((or (tramp-local-host-p v)
                (tramp-method-out-of-band-p
-                v (- (or end (point-max)) (or start (point-min)))))
-           (condition-case err
-               (rename-file tmpfile filename t)
-             ((error quit)
-              (delete-file tmpfile)
-              (signal (car err) (cdr err)))))
+                v (nth 7 (file-attributes tmpfile))))
+           (if (and (not (stringp start))
+                    (= (or end (point-max)) (point-max))
+                    (= (or start (point-min)) (point-min))
+                    (tramp-get-method-parameter
+                     method 'tramp-copy-keep-tmpfile))
+               (progn
+                 (setq tramp-temp-buffer-file-name tmpfile)
+                 (condition-case err
+                     ;; We keep the local file for performance
+                     ;; reasons, useful for "rsync".
+                     (copy-file tmpfile filename t)
+                   ((error quit)
+                    (setq tramp-temp-buffer-file-name nil)
+                    (delete-file tmpfile)
+                    (signal (car err) (cdr err)))))
+             (setq tramp-temp-buffer-file-name nil)
+             ;; Don't rename, in order to keep context in SELinux.
+             (unwind-protect
+                 (copy-file tmpfile filename t)
+               (delete-file tmpfile))))
 
           ;; Use inline file transfer.
           (rem-dec
@@ -4769,8 +5174,7 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
                              " decode using `%s' failed")
                      filename rem-dec)))
                  (tramp-message
-                  v 5 "Decoding region into remote file %s...done" filename)
-                 (tramp-flush-file-property v localname))
+                  v 5 "Decoding region into remote file %s...done" filename))
 
              ;; Save exit.
              (delete-file tmpfile)))
@@ -4787,19 +5191,27 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
          (when coding-system-used
            (set 'last-coding-system-used coding-system-used))))
 
+      (tramp-flush-file-property v (file-name-directory localname))
+      (tramp-flush-file-property v localname)
+
       ;; We must protect `last-coding-system-used', now we have set it
       ;; to its correct value.
-      (let (last-coding-system-used)
+      (let (last-coding-system-used (need-chown t))
        ;; Set file modification time.
        (when (or (eq visit t) (stringp visit))
-         (set-visited-file-modtime
-          ;; 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))))
+          (let ((file-attr (file-attributes filename)))
+            (set-visited-file-modtime
+             ;; 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-attr))
+            (when (and (eq (nth 2 file-attr) uid)
+                       (eq (nth 3 file-attr) gid))
+              (setq need-chown nil))))
 
        ;; Set the ownership.
-       (tramp-set-file-uid-gid filename uid gid)
+        (when need-chown
+          (tramp-set-file-uid-gid filename uid gid))
        (when (or (eq visit t) (null visit) (stringp visit))
          (tramp-message v 0 "Wrote %s" filename))
        (run-hooks 'tramp-handle-write-region-hook)))))
@@ -4906,7 +5318,7 @@ pass to the OPERATION."
   "Return file name related to OPERATION file primitive.
 ARGS are the arguments OPERATION has been called with."
   (cond
-   ; FILE resp DIRECTORY
+   ;; FILE resp DIRECTORY.
    ((member operation
            (list 'access-file 'byte-compiler-base-file-name 'delete-directory
                  'delete-file 'diff-latest-backup-file 'directory-file-name
@@ -4914,7 +5326,7 @@ ARGS are the arguments OPERATION has been called with."
                  'dired-compress-file 'dired-uncache
                  'file-accessible-directory-p 'file-attributes
                  'file-directory-p 'file-executable-p 'file-exists-p
-                 'file-local-copy 'file-remote-p 'file-modes
+                 'file-local-copy 'file-remote-p 'file-modes 'file-selinux-context
                  'file-name-as-directory 'file-name-directory
                  'file-name-nondirectory 'file-name-sans-versions
                  'file-ownership-preserved-p 'file-readable-p
@@ -4924,9 +5336,9 @@ ARGS are the arguments OPERATION has been called with."
                  'load 'make-directory 'make-directory-internal
                  'set-file-modes 'substitute-in-file-name
                  'unhandled-file-name-directory 'vc-registered
-                 ; Emacs 22 only
+                 ;; Emacs 22+ only.
                  'set-file-times
-                 ; XEmacs only
+                 ;; XEmacs only.
                  'abbreviate-file-name 'create-file-buffer
                  'dired-file-modtime 'dired-make-compressed-filename
                  'dired-recursive-delete-directory 'dired-set-file-modtime
@@ -4936,14 +5348,14 @@ ARGS are the arguments OPERATION has been called with."
     (if (file-name-absolute-p (nth 0 args))
        (nth 0 args)
       (expand-file-name (nth 0 args))))
-   ; FILE DIRECTORY resp FILE1 FILE2
+   ;; FILE DIRECTORY resp FILE1 FILE2.
    ((member operation
            (list 'add-name-to-file 'copy-file 'expand-file-name
                  'file-name-all-completions 'file-name-completion
                  'file-newer-than-file-p 'make-symbolic-link 'rename-file
-                 ; Emacs 23 only
+                 ;; Emacs 23+ only.
                  'copy-directory
-                 ; XEmacs only
+                 ;; XEmacs only.
                  'dired-make-relative-symlink
                  'vm-imap-move-mail 'vm-pop-move-mail 'vm-spool-move-mail))
     (save-match-data
@@ -4951,39 +5363,39 @@ ARGS are the arguments OPERATION has been called with."
        ((string-match tramp-file-name-regexp (nth 0 args)) (nth 0 args))
        ((string-match tramp-file-name-regexp (nth 1 args)) (nth 1 args))
        (t (buffer-file-name (current-buffer))))))
-   ; START END FILE
+   ;; START END FILE.
    ((eq operation 'write-region)
     (nth 2 args))
-   ; BUF
+   ;; BUFFER.
    ((member operation
            (list 'set-visited-file-modtime 'verify-visited-file-modtime
-                  ; since Emacs 22 only
+                  ;; Emacs 22+ only.
                  'make-auto-save-file-name
-                 ; XEmacs only
+                 ;; XEmacs only.
                  'backup-buffer))
     (buffer-file-name
      (if (bufferp (nth 0 args)) (nth 0 args) (current-buffer))))
-   ; COMMAND
+   ;; COMMAND.
    ((member operation
-           (list ; not in Emacs 23
+           (list ;; not in Emacs 23+.
                  'dired-call-process
-                  ; Emacs only
+                  ;; Emacs only.
                  'shell-command
-                  ; since Emacs 22 only
+                  ;; Emacs 22+ only.
                   'process-file
-                  ; since Emacs 23 only
+                  ;; Emacs 23+ only.
                   'start-file-process
-                 ; XEmacs only
+                 ;; XEmacs only.
                  'dired-print-file 'dired-shell-call-process
-                 ; nowhere yet
+                 ;; nowhere yet.
                  'executable-find 'start-process 'call-process))
     default-directory)
-   ; unknown file primitive
+   ;; Unknown file primitive.
    (t (error "unknown file I/O primitive: %s" operation))))
 
 (defun tramp-find-foreign-file-name-handler (filename)
   "Return foreign file name handler if exists."
-  (when (and (stringp filename) (tramp-tramp-file-p filename))
+  (when (tramp-tramp-file-p filename)
     (let ((v (tramp-dissect-file-name filename t))
          (handler tramp-foreign-file-name-handler-alist)
          elt res)
@@ -5015,19 +5427,28 @@ Falls back to normal file name handler if no Tramp file name handler exists."
               (completion (tramp-completion-mode-p))
               (foreign (tramp-find-foreign-file-name-handler filename)))
          (with-parsed-tramp-file-name filename nil
-           (cond
-            ;; When we are in completion mode, some operations
-            ;; shouldn't be handled by backend.
-            ((and completion (zerop (length localname))
-                  (memq operation '(file-exists-p file-directory-p)))
-             t)
-            ((and completion (zerop (length localname))
-                  (memq operation '(file-name-as-directory)))
-             filename)
-            ;; Call the backend function.
-            (foreign (apply foreign operation args))
-            ;; Nothing to do for us.
-            (t (tramp-run-real-handler operation args))))))
+           ;; Call the backend function.
+           (if foreign
+               (condition-case err
+                   (apply foreign operation args)
+                 (error
+                  (cond
+                   ;; When we are in completion mode, some failed
+                   ;; operations shall return at least a default
+                   ;; value in order to give the user a chance to
+                   ;; correct the file name in the minibuffer.
+                   ((and completion (zerop (length localname))
+                         (memq operation '(file-exists-p file-directory-p)))
+                    t)
+                   ((and completion (zerop (length localname))
+                         (memq operation
+                               '(expand-file-name file-name-as-directory)))
+                    filename)
+                   ;; Propagate the error.
+                   (t (signal (car err) (cdr err))))))
+             ;; Nothing to do for us.
+             (tramp-run-real-handler operation args)))))
+
     ;; When `tramp-mode' is not enabled, we don't do anything.
     (tramp-run-real-handler operation args)))
 
@@ -5117,7 +5538,9 @@ Falls back to normal file name handler if no Tramp file name handler exists."
          ;; disable this part of the completion, unless the user implicitly
          ;; indicated his interest in using a fancier completion system.
          (or (eq tramp-syntax 'sep)
-             (featurep 'tramp) ; If it's loaded, we may as well use it.
+             (featurep 'tramp) ;; If it's loaded, we may as well use
+            ;; it.  `partial-completion-mode' does not exist in
+            ;; XEmacs.  It is obsoleted with Emacs 24.1.
              (and (boundp 'partial-completion-mode) partial-completion-mode)
              ;; FIXME: These may have been loaded even if the user never
              ;; intended to use them.
@@ -5139,6 +5562,7 @@ Falls back to normal file name handler if no Tramp file name handler exists."
   ;; Add the handlers.
   (add-to-list 'file-name-handler-alist
               (cons tramp-file-name-regexp 'tramp-file-name-handler))
+  (put 'tramp-file-name-handler 'safe-magic t)
   (add-to-list 'file-name-handler-alist
               (cons tramp-completion-file-name-regexp
                     'tramp-completion-file-name-handler))
@@ -5192,7 +5616,8 @@ should never be set globally, the intention is to let-bind it.")
 (defun tramp-completion-mode-p ()
   "Checks whether method / user name / host name completion is active."
   (or
-   ;; Signal from outside.
+   ;; Signal from outside.  `non-essential' has been introduced in Emacs 24.
+   (and (boundp 'non-essential) (symbol-value 'non-essential))
    tramp-completion-mode
    ;; Emacs.
    (equal last-input-event 'tab)
@@ -5814,6 +6239,19 @@ hosts, or files, disagree."
        (format "*tramp/%s %s@%s*" method user host)
       (format "*tramp/%s %s*" method host))))
 
+(defun tramp-delete-temp-file-function ()
+  "Remove temporary files related to current buffer."
+  (when (stringp tramp-temp-buffer-file-name)
+    (condition-case nil
+       (delete-file tramp-temp-buffer-file-name)
+      (error nil))))
+
+(add-hook 'kill-buffer-hook 'tramp-delete-temp-file-function)
+(add-hook 'tramp-cache-unload-hook
+         (lambda ()
+           (remove-hook 'kill-buffer-hook
+                        'tramp-delete-temp-file-function)))
+
 (defun tramp-get-buffer (vec)
   "Get the connection buffer to be used for VEC."
   (or (get-buffer (tramp-buffer-name vec))
@@ -5854,22 +6292,24 @@ from the default one."
        (format "*debug tramp/%s %s@%s*" method user host)
       (format "*debug tramp/%s %s*" method host))))
 
+(defconst tramp-debug-outline-regexp
+  "[0-9]+:[0-9]+:[0-9]+\\.[0-9]+ [a-z0-9-]+ (\\([0-9]+\\)) #")
+
 (defun tramp-get-debug-buffer (vec)
   "Get the debug buffer for VEC."
   (with-current-buffer
       (get-buffer-create (tramp-debug-buffer-name vec))
     (when (bobp)
       (setq buffer-undo-list t)
-      ;; Activate outline-mode.  This runs `text-mode-hook' and
+      ;; Activate `outline-mode'.  This runs `text-mode-hook' and
       ;; `outline-mode-hook'.  We must prevent that local processes
-      ;; die.  Yes: I've seen `flyspell-mode', which starts "ispell"
-      ;; ...
-      (let ((default-directory (tramp-compat-temporary-file-directory)))
+      ;; die.  Yes: I've seen `flyspell-mode', which starts "ispell".
+      ;; Furthermore, `outline-regexp' must have the correct value
+      ;; already, because it is used by `font-lock-compile-keywords'.
+      (let ((default-directory (tramp-compat-temporary-file-directory))
+           (outline-regexp tramp-debug-outline-regexp))
        (outline-mode))
-      (set (make-local-variable 'outline-regexp)
-          "[0-9]+:[0-9]+:[0-9]+\\.[0-9]+ [a-z0-9-]+ (\\([0-9]+\\)) #")
-;      (set (make-local-variable 'outline-regexp)
-;         "[a-z.-]+:[0-9]+: [a-z0-9-]+ (\\([0-9]+\\)) #")
+      (set (make-local-variable 'outline-regexp) tramp-debug-outline-regexp)
       (set (make-local-variable 'outline-level) 'tramp-outline-level))
     (current-buffer)))
 
@@ -5892,7 +6332,7 @@ only in DIRLIST.
 Returns the absolute file name of PROGNAME, if found, and nil otherwise.
 
 This function expects to be in the right *tramp* buffer."
-  (with-current-buffer (tramp-get-buffer vec)
+  (with-current-buffer (tramp-get-connection-buffer vec)
     (let (result)
       ;; Check whether the executable is in $PATH. "which(1)" does not
       ;; report always a correct error code; therefore we check the
@@ -5900,11 +6340,11 @@ This function expects to be in the right *tramp* buffer."
       (unless ignore-path
        (tramp-send-command vec (format "which \\%s | wc -w" progname))
        (goto-char (point-min))
-       (if (looking-at "^1$")
+       (if (looking-at "^\\s-*1$")
            (setq result (concat "\\" progname))))
       (unless result
        (when ignore-tilde
-         ;; Remove all ~/foo directories from dirlist.  In Emacs 20,
+         ;; Remove all ~/foo directories from dirlist.  In XEmacs,
          ;; `remove' is in CL, and we want to avoid CL dependencies.
          (let (newdl d)
            (while dirlist
@@ -6001,12 +6441,15 @@ file exists and nonzero exit status otherwise."
       (with-current-buffer (tramp-get-buffer vec)
        (tramp-send-command vec "echo ~root" t)
        (cond
-        ((string-match "^~root$" (buffer-string))
+        ((or (string-match "^~root$" (buffer-string))
+             ;; The default shell (ksh93) of OpenSolaris is buggy.
+             (string-equal (tramp-get-connection-property vec "uname" "")
+                           "SunOS 5.11"))
          (setq shell
                (or (tramp-find-executable
-                    vec "bash" (tramp-get-remote-path vec) t)
+                    vec "bash" (tramp-get-remote-path vec) t t)
                    (tramp-find-executable
-                    vec "ksh" (tramp-get-remote-path vec) t)))
+                    vec "ksh" (tramp-get-remote-path vec) t t)))
          (unless shell
            (tramp-error
             vec 'file-error
@@ -6021,7 +6464,7 @@ file exists and nonzero exit status otherwise."
            (when extra-args (setq shell (concat shell " " extra-args))))
          (tramp-message
           vec 5 "Starting remote shell `%s' for tilde expansion..." shell)
-         (let ((tramp-end-of-output "$ "))
+         (let ((tramp-end-of-output tramp-initial-end-of-output))
            (tramp-send-command
             vec
             (format "PROMPT_COMMAND='' PS1=%s PS2='' PS3='' exec %s"
@@ -6168,7 +6611,7 @@ The terminal type can be configured with `tramp-terminal-type'."
 (defun tramp-process-actions (proc vec actions &optional timeout)
   "Perform actions until success or TIMEOUT."
   ;; Enable auth-source and password-cache.
-  (tramp-set-connection-property proc "first-password-request" t)
+  (tramp-set-connection-property vec "first-password-request" t)
   (let (exit)
     (while (not exit)
       (tramp-message proc 3 "Waiting for prompts from remote shell")
@@ -6218,11 +6661,18 @@ Erase echoed commands if exists."
          ;; Discard echo from remote output.
          (tramp-set-connection-property proc "check-remote-echo" nil)
          (tramp-message proc 5 "echo-mark found")
-         (forward-line)
+         (forward-line 1)
          (delete-region begin (point))
          (goto-char (point-min)))))
 
-    (when (not (tramp-get-connection-property proc "check-remote-echo" nil))
+    (when (or (not (tramp-get-connection-property proc "check-remote-echo" nil))
+             ;; Sometimes, the echo string is suppressed on the remote side.
+             (not (string-equal
+                   (substring-no-properties
+                    tramp-echo-mark-marker
+                    0 (min tramp-echo-mark-marker-length (1- (point-max))))
+                   (buffer-substring-no-properties
+                    1 (min (1+ tramp-echo-mark-marker-length) (point-max))))))
       ;; No echo to be handled, now we can look for the regexp.
       (goto-char (point-min))
       (re-search-forward regexp nil t))))
@@ -6292,7 +6742,7 @@ seconds.  If not, it produces an error message with the given ERROR-ARGS."
   "Set up an interactive shell.
 Mainly sets the prompt and the echo correctly.  PROC is the shell
 process to set up.  VEC specifies the connection."
-  (let ((tramp-end-of-output "$ "))
+  (let ((tramp-end-of-output tramp-initial-end-of-output))
     ;; It is useful to set the prompt in the following command because
     ;; some people have a setting for $PS1 which /bin/sh doesn't know
     ;; about and thus /bin/sh will display a strange prompt.  For
@@ -6371,6 +6821,9 @@ process to set up.  VEC specifies the connection."
        ;; because we're running on a non-MULE Emacs.  Let's try
        ;; stty, instead.
        (tramp-send-command vec "stty -onlcr" t))))
+  ;; Dump stty settings in the traces.
+  (when (>= tramp-verbose 10)
+    (tramp-send-command vec "stty -a" t))
   (tramp-send-command vec "set +o vi +o emacs" t)
 
   ;; Check whether the output of "uname -sr" has been changed.  If
@@ -6425,9 +6878,11 @@ process to set up.  VEC specifies the connection."
   ;; "test foo; echo $?" to check if various conditions hold, and
   ;; there are buggy /bin/sh implementations which don't execute the
   ;; "echo $?"  part if the "test" part has an error.  In particular,
-  ;; the Solaris /bin/sh is a problem.  I'm betting that all systems
-  ;; with buggy /bin/sh implementations will have a working bash or
-  ;; ksh.  Whee...
+  ;; the OpenSolaris /bin/sh is a problem.  There are also other
+  ;; problems with /bin/sh of OpenSolaris, like redirection of stderr
+  ;; in in function declarations, or changing HISTFILE in place.
+  ;; Therefore, OpenSolaris' /bin/sh is replaced by bash, when
+  ;; detected.
   (tramp-find-shell vec)
 
   ;; Disable unexpected output.
@@ -6436,19 +6891,14 @@ process to set up.  VEC specifies the connection."
   ;; Set the environment.
   (tramp-message vec 5 "Setting default environment")
 
-  ;; On OpenSolaris, there is a bug when HISTFILE is changed in place
-  ;; <http://bugs.opensolaris.org/view_bug.do?bug_id=6834184>.  We
-  ;; apply the workaround.
-  (if (string-equal (tramp-get-connection-property vec "uname" "") "SunOS 5.11")
-      (tramp-send-command vec "unset HISTFILE"))
-
   (let ((env (copy-sequence tramp-remote-process-environment))
        unset item)
     (while env
       (setq item (tramp-compat-split-string (car env) "="))
-      (if (and (stringp (cadr item)) (not (string-equal (cadr item) "")))
+      (setcdr item (mapconcat 'identity (cdr item) "="))
+      (if (and (stringp (cdr item)) (not (string-equal (cdr item) "")))
          (tramp-send-command
-          vec (format "%s=%s; export %s" (car item) (cadr item) (car item)) t)
+          vec (format "%s=%s; export %s" (car item) (cdr item) (car item)) t)
        (push (car item) unset))
       (setq env (cdr env)))
     (when unset
@@ -6482,7 +6932,7 @@ process to set up.  VEC specifies the connection."
   "List of local coding commands for inline transfer.
 Each item is a list that looks like this:
 
-\(FORMAT ENCODING DECODING)
+\(FORMAT ENCODING DECODING\)
 
 FORMAT is  symbol describing the encoding/decoding format.  It can be
 `b64' for base64 encoding, `uu' for uu encoding, or `pack' for simple packing.
@@ -6515,7 +6965,7 @@ with the encoded or decoded results, respectively.")
   "List of remote coding commands for inline transfer.
 Each item is a list that looks like this:
 
-\(FORMAT ENCODING DECODING)
+\(FORMAT ENCODING DECODING\)
 
 FORMAT is  symbol describing the encoding/decoding format.  It can be
 `b64' for base64 encoding, `uu' for uu encoding, or `pack' for simple packing.
@@ -6529,7 +6979,7 @@ input.
 
 If they are variables, this variable is a string containing a Perl
 implementation for this functionality.  This Perl program will be transferred
-to the remote host, and it is avalible as shell function with the same name.")
+to the remote host, and it is available as shell function with the same name.")
 
 (defun tramp-find-inline-encoding (vec)
   "Find an inline transfer encoding that works.
@@ -6604,7 +7054,8 @@ Goes through the list `tramp-local-coding-commands' and
                  (unless (zerop (tramp-send-command-and-check
                                  vec
                                  (format "echo %s | %s | %s"
-                                         magic rem-enc rem-dec) t))
+                                         magic rem-enc rem-dec)
+                                 t))
                    (throw 'wont-work-remote nil))
 
                  (with-current-buffer (tramp-get-buffer vec)
@@ -6619,7 +7070,8 @@ Goes through the list `tramp-local-coding-commands' and
 
       ;; Did we find something?
       (unless found
-       (tramp-message vec 2 "Couldn't find an inline transfer encoding"))
+       (tramp-error
+        vec 'file-error "Couldn't find an inline transfer encoding"))
 
       ;; Set connection properties.
       (tramp-message vec 5 "Using local encoding `%s'" loc-enc)
@@ -6674,8 +7126,9 @@ Gateway hops are already opened."
          (setq proxy
                (format-spec
                 proxy
-                `((?u . ,(or (tramp-file-name-user (car target-alist)) ""))
-                  (?h . ,(or (tramp-file-name-host (car target-alist)) "")))))
+                (format-spec-make
+                 ?u (or (tramp-file-name-user (car target-alist)) "")
+                 ?h (or (tramp-file-name-host (car target-alist)) ""))))
          (with-parsed-tramp-file-name proxy l
            ;; Add the hop.
            (add-to-list 'target-alist l)
@@ -6817,7 +7270,7 @@ connection if a previous connection has died for some reason."
        (setenv "TERM" tramp-terminal-type)
        (setenv "LC_ALL" "C")
        (setenv "PROMPT_COMMAND")
-       (setenv "PS1" "$ ")
+       (setenv "PS1" tramp-initial-end-of-output)
        (let* ((target-alist (tramp-compute-multi-hops vec))
               (process-connection-type tramp-process-connection-type)
               (process-adaptive-read-buffering nil)
@@ -6893,10 +7346,12 @@ connection if a previous connection has died for some reason."
               l-host (or l-host "")
               l-user (or l-user "")
               l-port (or l-port "")
-              spec `((?h . ,l-host) (?u . ,l-user) (?p . ,l-port)
-                     (?t . ,tmpfile))
+              spec (format-spec-make ?h l-host ?u l-user ?p l-port ?t tmpfile)
               command
               (concat
+               ;; We do not want to see the trailing local prompt in
+               ;; `start-file-process'.
+               (unless (memq system-type '(windows-nt)) "exec ")
                command " "
                (mapconcat
                 (lambda (x)
@@ -6906,7 +7361,7 @@ connection if a previous connection has died for some reason."
                ;; Local shell could be a Windows COMSPEC.  It doesn't
                ;; know the ";" syntax, but we must exit always for
                ;; `start-file-process'.  "exec" does not work either.
-               " && exit || exit"))
+               (if (memq system-type '(windows-nt)) " && exit || exit")))
 
              ;; Send the command.
              (tramp-message vec 3 "Sending command `%s'" command)
@@ -6936,11 +7391,14 @@ function waits for output unless NOOUTPUT is set."
     (unless nooutput (tramp-wait-for-output p))))
 
 (defun tramp-wait-for-output (proc &optional timeout)
-  "Wait for output from remote rsh command."
+  "Wait for output from remote command."
+  (unless (buffer-live-p (process-buffer proc))
+    (delete-process proc)
+    (tramp-error proc 'file-error "Process `%s' not available, try again" proc))
   (with-current-buffer (process-buffer proc)
-    (let* (;; Initially, `tramp-end-of-output' is "$ ".  There might
+    (let* (;; Initially, `tramp-end-of-output' is "#$ ".  There might
           ;; be leading escape sequences, which must be ignored.
-          (regexp (format "[^$\n]*%s\r?$" (regexp-quote tramp-end-of-output)))
+          (regexp (format "[^#$\n]*%s\r?$" (regexp-quote tramp-end-of-output)))
           ;; Sometimes, the commands do not return a newline but a
           ;; null byte before the shell prompt, for example "git
           ;; ls-files -c -z ...".
@@ -6948,6 +7406,14 @@ function waits for output unless NOOUTPUT is set."
           (found (tramp-wait-for-regexp proc timeout regexp1)))
       (if found
          (let (buffer-read-only)
+           ;; A simple-minded busybox has sent " ^H" sequences.
+           ;; Delete them.
+           (goto-char (point-min))
+           (when (re-search-forward
+                  "^\\(.\b\\)+$" (tramp-compat-line-end-position) t)
+             (forward-line 1)
+             (delete-region (point-min) (point)))
+           ;; Delete the prompt.
            (goto-char (point-max))
            (re-search-backward regexp nil t)
            (delete-region (point) (point-max)))
@@ -6962,20 +7428,22 @@ function waits for output unless NOOUTPUT is set."
       ;; Return value is whether end-of-output sentinel was found.
       found)))
 
-(defun tramp-send-command-and-check (vec command &optional subshell)
+(defun tramp-send-command-and-check
+  (vec command &optional subshell dont-suppress-err)
   "Run COMMAND and check its exit status.
 Sends `echo $?' along with the COMMAND for checking the exit status.  If
 COMMAND is nil, just sends `echo $?'.  Returns the exit status found.
 
-If the optional argument SUBSHELL is non-nil, the command is executed in
-a subshell, ie surrounded by parentheses."
+If the optional argument SUBSHELL is non-nil, the command is
+executed in a subshell, ie surrounded by parentheses.  If
+DONT-SUPPRESS-ERR is non-nil, stderr won't be sent to /dev/null."
   (tramp-send-command
    vec
    (concat (if subshell "( " "")
           command
-          (if command " 2>/dev/null; " "")
+          (if command (if dont-suppress-err "; " " 2>/dev/null; ") "")
           "echo tramp_exit_status $?"
-          (if subshell " )" " ")))
+          (if subshell " )" "")))
   (with-current-buffer (tramp-get-connection-buffer vec)
     (goto-char (point-max))
     (unless (re-search-backward "tramp_exit_status [0-9]+" nil t)
@@ -7184,6 +7652,49 @@ Return ATTR."
             (tramp-get-device vec))
     attr))
 
+(defun tramp-check-cached-permissions (vec access)
+  "Check `file-attributes' caches for VEC.
+Return t if according to the cache access type ACCESS is known to
+be granted."
+  (let ((result nil)
+        (offset (cond
+                 ((eq ?r access) 1)
+                 ((eq ?w access) 2)
+                 ((eq ?x access) 3))))
+    (dolist (suffix '("string" "integer") result)
+      (setq
+       result
+       (or
+        result
+        (let ((file-attr
+               (tramp-get-file-property
+                vec (tramp-file-name-localname vec)
+                (concat "file-attributes-" suffix) nil))
+              (remote-uid
+               (tramp-get-connection-property
+                vec (concat "uid-" suffix) nil))
+              (remote-gid
+               (tramp-get-connection-property
+                vec (concat "gid-" suffix) nil)))
+          (and
+           file-attr
+           (or
+            ;; Not a symlink
+            (eq t (car file-attr))
+            (null (car file-attr)))
+           (or
+            ;; World accessible.
+            (eq access (aref (nth 8 file-attr) (+ offset 6)))
+            ;; User accessible and owned by user.
+            (and
+             (eq access (aref (nth 8 file-attr) offset))
+             (equal remote-uid (nth 2 file-attr)))
+            ;; Group accessible and owned by user's
+            ;; principal group.
+            (and
+             (eq access (aref (nth 8 file-attr) (+ offset 3)))
+             (equal remote-gid (nth 3 file-attr)))))))))))
+
 (defun tramp-get-inode (vec)
   "Returns the virtual inode number.
 If it doesn't exist, generate a new one."
@@ -7331,9 +7842,9 @@ Not actually used.  Use `(format \"%o\" i)' instead?"
           (string-to-number (match-string 2 host))))))
 
 (defun tramp-tramp-file-p (name)
-  "Return t if NAME is a Tramp file."
+  "Return t if NAME is a string with Tramp file name syntax."
   (save-match-data
-    (string-match tramp-file-name-regexp name)))
+    (and (stringp name) (string-match tramp-file-name-regexp name))))
 
 (defun tramp-find-method (method user host)
   "Return the right method string to use.
@@ -7507,7 +8018,7 @@ necessary only.  This function will be used in file name completion."
          (tramp-get-connection-process vec)
        vec)
       "remote-path"
-    (let* ((remote-path (tramp-compat-copy-tree tramp-remote-path))
+    (let* ((remote-path (copy-tree tramp-remote-path))
           (elt1 (memq 'tramp-default-remote-path remote-path))
           (elt2 (memq 'tramp-own-remote-path remote-path))
           (default-remote-path
@@ -7592,9 +8103,14 @@ necessary only.  This function will be used in file name completion."
         (let ((dl (tramp-get-remote-path vec))
               result)
           (while (and dl (setq result (tramp-find-executable vec cmd dl t t)))
-            ;; Check parameter.
+            ;; Check parameters.  On busybox, "ls" output coloring is
+            ;; enabled by default sometimes.  So we try to disable it
+            ;; when possible.  $LS_COLORING is not supported there.
             (when (zerop (tramp-send-command-and-check
                           vec (format "%s -lnd /" result)))
+              (when (zerop (tramp-send-command-and-check
+                            vec (format "%s --color=never /" result)))
+                (setq result (concat result " --color=never")))
               (throw 'ls-found result))
             (setq dl (cdr dl))))))
      (tramp-error vec 'file-error "Couldn't find a proper `ls' command"))))
@@ -7647,8 +8163,21 @@ necessary only.  This function will be used in file name completion."
 (defun tramp-get-remote-perl (vec)
   (with-connection-property vec "perl"
     (tramp-message vec 5 "Finding a suitable `perl' command")
-    (or (tramp-find-executable vec "perl5" (tramp-get-remote-path vec))
-       (tramp-find-executable vec "perl" (tramp-get-remote-path vec)))))
+    (let ((result
+          (or (tramp-find-executable vec "perl5" (tramp-get-remote-path vec))
+              (tramp-find-executable
+               vec "perl" (tramp-get-remote-path vec)))))
+      ;; We must check also for some Perl modules.
+      (when result
+       (with-connection-property vec "perl-file-spec"
+         (zerop
+          (tramp-send-command-and-check
+           vec (format "%s -e 'use File::Spec;'" result))))
+       (with-connection-property vec "perl-cwd-realpath"
+         (zerop
+          (tramp-send-command-and-check
+           vec (format "%s -e 'use Cwd \"realpath\";'" result)))))
+      result)))
 
 (defun tramp-get-remote-stat (vec)
   (with-connection-property vec "stat"
@@ -7672,6 +8201,21 @@ necessary only.  This function will be used in file name completion."
          (setq result nil)))
       result)))
 
+(defun tramp-get-remote-readlink (vec)
+  (with-connection-property vec "readlink"
+    (tramp-message vec 5 "Finding a suitable `readlink' command")
+    (let ((result (tramp-find-executable
+                  vec "readlink" (tramp-get-remote-path vec))))
+      (when (and result
+                ;; We don't want to display an error message.
+                (with-temp-message (or (current-message) "")
+                  (condition-case nil
+                      (zerop
+                       (tramp-send-command-and-check
+                        vec (format "%s --canonicalize-missing /" result)))
+                    (error nil))))
+       result))))
+
 (defun tramp-get-remote-id (vec)
   (with-connection-property vec "id"
     (tramp-message vec 5 "Finding POSIX `id' command")
@@ -7773,23 +8317,27 @@ If the `tramp-methods' entry does not exist, return NIL."
   (defadvice make-auto-save-file-name
     (around tramp-advice-make-auto-save-file-name () activate)
     "Invoke `tramp-handle-make-auto-save-file-name' for Tramp files."
-    (if (and (buffer-file-name) (tramp-tramp-file-p (buffer-file-name)))
+    (if (tramp-tramp-file-p (buffer-file-name))
        ;; We cannot call `tramp-handle-make-auto-save-file-name'
        ;; directly, because this would bypass the locking mechanism.
        (setq ad-return-value
              (tramp-file-name-handler 'make-auto-save-file-name))
       ad-do-it))
-  (add-hook 'tramp-unload-hook
-           (lambda () (ad-unadvise 'make-auto-save-file-name))))
+  (add-hook
+   'tramp-unload-hook
+   (lambda ()
+     (ad-remove-advice
+      'make-auto-save-file-name
+      'around 'tramp-advice-make-auto-save-file-name)
+     (ad-activate 'make-auto-save-file-name))))
 
-;; In Emacs < 22 and XEmacs < 21.5 autosaved remote files have
-;; permission 0666 minus umask. This is a security threat.
+;; In XEmacs < 21.5, autosaved remote files have permission 0666 minus
+;; umask. This is a security threat.
 
 (defun tramp-set-auto-save-file-modes ()
   "Set permissions of autosaved remote files to the original permissions."
   (let ((bfn (buffer-file-name)))
-    (when (and (stringp bfn)
-              (tramp-tramp-file-p bfn)
+    (when (and (tramp-tramp-file-p bfn)
               (buffer-modified-p)
               (stringp buffer-auto-save-file-name)
               (not (equal bfn buffer-auto-save-file-name)))
@@ -7801,10 +8349,9 @@ If the `tramp-methods' entry does not exist, return NIL."
       (set-file-modes buffer-auto-save-file-name
                      (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)))
+(unless (and (featurep 'xemacs)
+            (= emacs-major-version 21)
+            (> emacs-minor-version 4))
   (add-hook 'auto-save-hook 'tramp-set-auto-save-file-modes)
   (add-hook 'tramp-unload-hook
            (lambda ()
@@ -7839,26 +8386,27 @@ Invokes `password-read' if available, `read-passwd' else."
              (with-current-buffer (process-buffer proc)
                (tramp-check-for-regexp proc tramp-password-prompt-regexp)
                (format "%s for %s " (capitalize (match-string 1)) key)))))
-    (prog1
-       (or
-        ;; See if auth-sources contains something useful, if it's bound.
-        (and (boundp 'auth-sources)
-             (tramp-get-connection-property proc "first-password-request" nil)
-             ;; Try with Tramp's current method.
-             (funcall (symbol-function 'auth-source-user-or-password)
-                      "password" tramp-current-host tramp-current-method))
-        ;; Try the password cache.
-        (when (functionp 'password-read)
-          (unless (tramp-get-connection-property
-                   proc "first-password-request" nil)
-            (funcall (symbol-function 'password-cache-remove) key))
-          (let ((password
-                 (funcall (symbol-function 'password-read) pw-prompt key)))
-            (funcall (symbol-function 'password-cache-add) key password)
-            password))
-        ;; Else, get the password interactively.
-        (read-passwd pw-prompt))
-      (tramp-set-connection-property proc "first-password-request" nil))))
+    (with-parsed-tramp-file-name key nil
+      (prog1
+         (or
+          ;; See if auth-sources contains something useful, if it's bound.
+          (and (boundp 'auth-sources)
+               (tramp-get-connection-property v "first-password-request" nil)
+               ;; Try with Tramp's current method.
+               (funcall (symbol-function 'auth-source-user-or-password)
+                        "password" tramp-current-host tramp-current-method))
+          ;; Try the password cache.
+          (when (functionp 'password-read)
+            (unless (tramp-get-connection-property
+                     v "first-password-request" nil)
+              (funcall (symbol-function 'password-cache-remove) key))
+            (let ((password
+                   (funcall (symbol-function 'password-read) pw-prompt key)))
+              (funcall (symbol-function 'password-cache-add) key password)
+              password))
+          ;; Else, get the password interactively.
+          (read-passwd pw-prompt))
+       (tramp-set-connection-property v "first-password-request" nil)))))
 
 (defun tramp-clear-passwd (vec)
   "Clear password cache for connection related to VEC."
@@ -7993,32 +8541,6 @@ Only works for Bourne-like shells."
                                      t t result)))
        result))))
 
-;; We currently (sometimes) use "[" and "]" in the filename format.
-;; This means that Emacs wants to expand wildcards if
-;; `find-file-wildcards' is non-nil, and then barfs because no
-;; expansion could be found.  We detect this situation and do
-;; something really awful: we have `file-expand-wildcards' return the
-;; original filename if it can't expand anything.  Let's just hope
-;; that this doesn't break anything else.
-;; CCC: This check is now also really awful; we should search all
-;; of the filename format, not just the prefix.
-(when (string-match "\\[" tramp-prefix-format)
-  (defadvice file-expand-wildcards
-    (around tramp-advice-file-expand-wildcards activate)
-    (let ((name (ad-get-arg 0)))
-      (if (tramp-tramp-file-p name)
-         ;; If it's a Tramp file, dissect it and look if wildcards
-         ;; need to be expanded at all.
-         (if (string-match
-              "[[*?]"
-              (tramp-file-name-localname (tramp-dissect-file-name name)))
-             (setq ad-return-value (or ad-do-it (list name)))
-           (setq ad-return-value (list name)))
-       ;; If it is not a Tramp file, just run the original function.
-       (setq ad-return-value (or ad-do-it (list name))))))
-  (add-hook 'tramp-unload-hook
-           (lambda () (ad-unadvise 'file-expand-wildcards))))
-
 ;; Checklist for `tramp-unload-hook'
 ;; - Unload all `tramp-*' packages
 ;; - Reset `file-name-handler-alist'
@@ -8064,21 +8586,15 @@ Only works for Bourne-like shells."
 ;; * Don't use globbing for directories with many files, as this is
 ;;   likely to produce long command lines, and some shells choke on
 ;;   long command lines.
-;; * `vc-directory' does not work.  It never displays any files, even
-;;   if it does show files when run locally.
 ;; * How to deal with MULE in `insert-file-contents' and `write-region'?
-;; * Grok `append' parameter for `write-region'.
 ;; * Test remote ksh or bash for tilde expansion in `tramp-find-shell'?
 ;; * abbreviate-file-name
 ;; * Better error checking.  At least whenever we see something
 ;;   strange when doing zerop, we should kill the process and start
 ;;   again.  (Greg Stark)
-;; * Provide a local cache of old versions of remote files for the rsync
-;;   transfer method to use.  (Greg Stark)
 ;; * Remove unneeded parameters from methods.
 ;; * Make it work for different encodings, and for different file name
 ;;   encodings, too.  (Daniel Pittman)
-;; * Progress reports while copying files.  (Michael Kifer)
 ;; * Don't search for perl5 and perl.  Instead, only search for perl and
 ;;   then look if it's the right version (with `perl -v').
 ;; * When editing a remote CVS controlled file as a different user, VC
@@ -8111,33 +8627,45 @@ Only works for Bourne-like shells."
 ;;   equivalent of the emacsclient -eval option in order to make this
 ;;   reasonably unproblematic.  And maybe trampclient should have some
 ;;   way of passing credentials, like by using an SSL socket or
-;;   something. (David Kastrup)
+;;   something.  (David Kastrup)
 ;; * Reconnect directly to a compliant shell without first going
-;;   through the user's default shell. (Pete Forman)
+;;   through the user's default shell.  (Pete Forman)
 ;; * Make `tramp-default-user' obsolete.
-;; * Tramp shall reconnect automatically to its ssh connection when it
-;;   detects that the process "has died". (David Reitter)
 ;; * How can I interrupt the remote process with a signal
-;;   (interrupt-process seems not to work)? (Markus Triska)
+;;   (interrupt-process seems not to work)?  (Markus Triska)
 ;; * Avoid the local shell entirely for starting remote processes.  If
 ;;   so, I think even a signal, when delivered directly to the local
 ;;   SSH instance, would correctly be propagated to the remote process
 ;;   automatically; possibly SSH would have to be started with
-;;   "-t". (Markus Triska)
+;;   "-t".  (Markus Triska)
 ;; * It makes me wonder if tramp couldn't fall back to ssh when scp
-;;   isn't on the remote host. (Mark A. Hershberger)
-;; * Use lsh instead of ssh. (Alfred M. Szmidt)
+;;   isn't on the remote host.  (Mark A. Hershberger)
+;; * Use lsh instead of ssh.  (Alfred M. Szmidt)
 ;; * Implement a general server-local-variable mechanism, as there are
 ;;   probably other variables that need different values for different
 ;;   servers too.  The user could then configure a variable (such as
 ;;   tramp-server-local-variable-alist) to define any such variables
 ;;   that they need to, which would then be let bound as appropriate
-;;   in tramp functions. (Jason Rumney)
+;;   in tramp functions.  (Jason Rumney)
 ;; * Optimize out-of-band copying, when both methods are scp-like (not
 ;;   rsync).
 ;; * Keep a second connection open for out-of-band methods like scp or
 ;;   rsync.
-;; * Support ptys in `tramp-handle-start-file-process'.
+;; * Support ptys in `tramp-handle-start-file-process'.  (Bug#4604)
+;; * IMHO, it's a drawback that currently Tramp doesn't support
+;;   Unicode in Dired file names by default.  Is it possible to
+;;   improve Tramp to set LC_ALL to "C" only for commands where Tramp
+;;   expects English?  Or just to set LC_MESSAGES to "C" if Tramp
+;;   expects only English messages?  (Juri Linkov)
+;; * Make shadowfile.el grok Tramp filenames.  (Bug#4526, Bug#4846)
+;; * Do not handle files with drive letter as remote.  (Bug#5447)
+;; * Load Tramp subpackages only when needed.  (Bug#1529, Bug#5448, Bug#5705)
+;; * Try telnet+curl as new method.  It might be useful for busybox,
+;;   without built-in uuencode/uudecode.
+;; * Let `shell-dynamic-complete-*' and `comint-dynamic-complete' work
+;;   on remote hosts.
+;; * Use secrets.el for password handling.
+;; * Load ~/.emacs_SHELLNAME on the remote host for `shell'.
 
 ;; Functions for file-name-handler-alist:
 ;; diff-latest-backup-file -- in diff.el