]> code.delx.au - gnu-emacs/blobdiff - lisp/net/tramp.el
Revert 2010-09-13T10:14:52Z!bob@gnu.org by Bob Chassel.
[gnu-emacs] / lisp / net / tramp.el
index 1c9a7015bf2b9e4111ea8bee2fa52d25a4c36fa5..cddfd44c13b4385f8c074499b2695a84538d7a02 100644 (file)
@@ -8,6 +8,7 @@
 ;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
 ;;         Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
+;; Package: tramp
 
 ;; This file is part of GNU Emacs.
 
 (when (and load-in-progress (null (current-message)))
   (message "Loading tramp..."))
 
-;; The Tramp version number and bug report address, as prepared by configure.
-(require 'trampver)
-(add-hook 'tramp-unload-hook
-         (lambda ()
-           (when (featurep 'trampver)
-             (unload-feature 'trampver 'force))))
-
 (require 'tramp-compat)
-(add-hook 'tramp-unload-hook
-         (lambda ()
-           (when (featurep 'tramp-compat)
-             (unload-feature 'tramp-compat 'force))))
 
 (require 'format-spec)
 ;; As long as password.el is not part of (X)Emacs, it shouldn't
       (load "auth-source" 'noerror)
     (require 'auth-source nil 'noerror)))
 
-;; Requiring 'tramp-cache results in an endless loop.
-(autoload 'tramp-get-file-property "tramp-cache")
-(autoload 'tramp-set-file-property "tramp-cache")
-(autoload 'tramp-flush-file-property "tramp-cache")
-(autoload 'tramp-flush-directory-property "tramp-cache")
-(autoload 'tramp-get-connection-property "tramp-cache")
-(autoload 'tramp-set-connection-property "tramp-cache")
-(autoload 'tramp-flush-connection-property "tramp-cache")
-(autoload 'tramp-parse-connection-properties "tramp-cache")
-(add-hook 'tramp-unload-hook
-         (lambda ()
-           (when (featurep 'tramp-cache)
-             (unload-feature 'tramp-cache 'force))))
-
-(autoload 'tramp-uuencode-region "tramp-uu"
-  "Implementation of `uuencode' in Lisp.")
-(add-hook 'tramp-unload-hook
-         (lambda ()
-           (when (featurep 'tramp-uu)
-             (unload-feature 'tramp-uu 'force))))
-
 (autoload 'uudecode-decode-region "uudecode")
 
-;; The following Tramp packages must be loaded after tramp.el, because
-;; they require it as well.
-(eval-after-load "tramp"
-  '(dolist
-       (feature
-       (list
-
-        ;; Tramp interactive commands.
-        'tramp-cmds
-
-        ;; Load foreign FTP method.
-        (if (featurep 'xemacs) 'tramp-efs 'tramp-ftp)
-
-        ;; tramp-smb uses "smbclient" from Samba.  Not available
-        ;; under Cygwin and Windows, because they don't offer
-        ;; "smbclient".  And even not necessary there, because Emacs
-        ;; supports UNC file names like "//host/share/localname".
-        (unless (memq system-type '(cygwin windows-nt)) 'tramp-smb)
-
-        ;; Load foreign FISH method.
-        'tramp-fish
-
-        ;; tramp-gvfs needs D-Bus messages.  Available since Emacs 23
-        ;; on some system types.  We don't call `dbus-ping', because
-        ;; this would load dbus.el.
-        (when (and (featurep 'dbusbind)
-                   (condition-case nil
-                       (tramp-compat-funcall 'dbus-get-unique-name :session)
-                     (error nil))
-                   (tramp-compat-process-running-p "gvfs-fuse-daemon"))
-          'tramp-gvfs)
-
-        ;; Load gateways.  It needs `make-network-process' from Emacs 22.
-        (when (functionp 'make-network-process) 'tramp-gw)
-
-        ;; tramp-imap needs both epa (from Emacs 23.1) and imap-hash
-        ;; (from Emacs 23.2).
-        (when (and (locate-library "epa") (locate-library "imap-hash"))
-          'tramp-imap)))
-
-     (when feature
-       ;; We have used just some basic tests, whether a package shall
-       ;; be added.  There might still be other errors during loading,
-       ;; which we will catch here.
-       (catch 'tramp-loading
-        (require feature)
-        (add-hook 'tramp-unload-hook
-                  `(lambda ()
-                     (when (featurep (quote ,feature))
-                       (unload-feature (quote ,feature) 'force)))))
-       (unless (featurep feature)
-        (message "Loading %s failed, ignoring this package" feature)))))
-
 ;;; User Customizable Internal Variables:
 
 (defgroup tramp nil
@@ -200,6 +116,7 @@ Any level x includes messages for all levels 1 .. x-1.  The levels are
  6  sent and received strings
  7  file caching
  8  connection properties
+ 9  test commands
 10  traces (huge)."
   :group 'tramp
   :type 'integer)
@@ -299,6 +216,7 @@ If it is nil, inline out-of-the-band copy will be used without a check."
   :group 'tramp
   :type '(choice (const nil) integer))
 
+;;;###tramp-autoload
 (defcustom tramp-terminal-type "dumb"
   "*Value of TERM environment variable for logging in to remote host.
 Because Tramp wants to parse the output of the remote shell, it is easily
@@ -319,9 +237,11 @@ files conditionalize this setup based on the TERM environment variable."
 The '$' character at the end is quoted; the string cannot be
 detected as prompt when being sent on echoing hosts, therefore.")
 
+;;;###tramp-autoload
 (defconst tramp-initial-end-of-output "#$ "
   "Prompt when establishing a connection.")
 
+;;;###tramp-autoload
 (defvar tramp-methods
   `(("rcp"   (tramp-login-program        "rsh")
              (tramp-login-args           (("%h") ("-l" "%u")))
@@ -332,8 +252,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-copy-recursive       t)
             (tramp-password-end-of-line nil))
     ("scp"   (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-e" "none")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "scp")
@@ -348,8 +268,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                          ("-o" "StrictHostKeyChecking=no")))
             (tramp-default-port         22))
     ("scp1"  (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-1" "-e" "none")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-1") ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "scp")
@@ -364,8 +284,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                          ("-o" "StrictHostKeyChecking=no")))
             (tramp-default-port         22))
     ("scp2"  (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-2" "-e" "none")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-2") ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "scp")
@@ -400,8 +320,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-copy-recursive       t)
             (tramp-password-end-of-line nil))
     ("sftp"  (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-e" "none")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "sftp")
@@ -409,8 +329,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-copy-keep-date       nil)
             (tramp-password-end-of-line nil))
     ("rsync" (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-e" "none")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "rsync")
@@ -421,10 +341,10 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-password-end-of-line nil))
     ("rsyncc"
              (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
                                          ("-o" "ControlPath=%t.%%r@%%h:%%p")
                                          ("-o" "ControlMaster=yes")
-                                         ("-e" "none")))
+                                         ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "rsync")
@@ -453,8 +373,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-copy-keep-date       nil)
             (tramp-password-end-of-line nil))
     ("ssh"   (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-e" "none")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         nil)
@@ -467,8 +387,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                          ("-o" "StrictHostKeyChecking=no")))
             (tramp-default-port         22))
     ("ssh1"  (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-1" "-e" "none")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-1") ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         nil)
@@ -481,8 +401,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                          ("-o" "StrictHostKeyChecking=no")))
             (tramp-default-port         22))
     ("ssh2"  (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-2" "-e" "none")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-2") ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         nil)
@@ -545,10 +465,10 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-copy-keep-date       nil)
             (tramp-password-end-of-line nil))
     ("scpc"  (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
                                          ("-o" "ControlPath=%t.%%r@%%h:%%p")
                                          ("-o" "ControlMaster=yes")
-                                         ("-e" "none")))
+                                         ("-e" "none") ("%h")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "scp")
@@ -563,8 +483,9 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                          ("-o" "StrictHostKeyChecking=no")))
             (tramp-default-port         22))
     ("scpx"  (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-e" "none" "-t" "-t" "/bin/sh")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-e" "none") ("-t" "-t")
+                                         ("%h") ("/bin/sh")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "scp")
@@ -577,8 +498,9 @@ detected as prompt when being sent on echoing hosts, therefore.")
                                          ("-o" "StrictHostKeyChecking=no")))
             (tramp-default-port         22))
     ("sshx"  (tramp-login-program        "ssh")
-             (tramp-login-args           (("%h") ("-l" "%u") ("-p" "%p")
-                                         ("-e" "none" "-t" "-t" "/bin/sh")))
+             (tramp-login-args           (("-l" "%u") ("-p" "%p")
+                                         ("-e" "none") ("-t" "-t")
+                                         ("%h") ("/bin/sh")))
             (tramp-async-args           (("-q")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         nil)
@@ -599,8 +521,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-copy-keep-date       nil)
             (tramp-password-end-of-line nil))
     ("plink" (tramp-login-program        "plink")
-            (tramp-login-args           (("%h") ("-l" "%u") ("-P" "%p")
-                                         ("-ssh")))
+            (tramp-login-args           (("-l" "%u") ("-P" "%p")
+                                         ("-ssh") ("%h")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         nil)
             (tramp-copy-args            nil)
@@ -609,8 +531,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-default-port         22))
     ("plink1"
             (tramp-login-program        "plink")
-            (tramp-login-args           (("%h") ("-l" "%u") ("-P" "%p")
-                                         ("-1" "-ssh")))
+            (tramp-login-args           (("-l" "%u") ("-P" "%p")
+                                         ("-1" "-ssh") ("%h")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         nil)
             (tramp-copy-args            nil)
@@ -633,8 +555,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-copy-keep-date       nil)
             (tramp-password-end-of-line nil))
     ("pscp"  (tramp-login-program        "plink")
-            (tramp-login-args           (("%h") ("-l" "%u") ("-P" "%p")
-                                         ("-ssh")))
+            (tramp-login-args           (("-l" "%u") ("-P" "%p")
+                                         ("-ssh") ("%h")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "pscp")
             (tramp-copy-args            (("-P" "%p") ("-scp") ("-p" "%k")))
@@ -642,8 +564,8 @@ detected as prompt when being sent on echoing hosts, therefore.")
             (tramp-password-end-of-line "xy") ;see docstring for "xy"
             (tramp-default-port         22))
     ("psftp" (tramp-login-program        "plink")
-            (tramp-login-args           (("%h") ("-l" "%u") ("-P" "%p")
-                                         ("-ssh")))
+            (tramp-login-args           (("-l" "%u") ("-P" "%p")
+                                         ("-ssh") ("%h")))
             (tramp-remote-sh            "/bin/sh")
             (tramp-copy-program         "pscp")
             (tramp-copy-args            (("-P" "%p") ("-sftp") ("-p" "%k")))
@@ -1444,10 +1366,14 @@ See also `tramp-file-name-regexp'.")
 
 ;;;###autoload
 (defconst tramp-file-name-regexp-unified
-  "\\`/\\([^[/:]+\\|[^/]+]\\):"
+  (if (memq system-type '(cygwin windows-nt))
+      "\\`/\\([^[/:]\\{2,\\}\\|[^/]\\{2,\\}]\\):"
+    "\\`/\\([^[/:]+\\|[^/]+]\\):")
   "Value for `tramp-file-name-regexp' for unified remoting.
 Emacs (not XEmacs) uses a unified filename syntax for Ange-FTP and
-Tramp.  See `tramp-file-name-structure' for more explanations.")
+Tramp.  See `tramp-file-name-structure' for more explanations.
+
+On W32 systems, the volume letter must be ignored.")
 
 ;;;###autoload
 (defconst tramp-file-name-regexp-separate
@@ -1494,10 +1420,14 @@ volume letter, which will be removed by `tramp-drop-volume-letter'.")
 
 ;;;###autoload
 (defconst tramp-completion-file-name-regexp-unified
-  (concat tramp-root-regexp "[^/]*\\'")
+  (if (memq system-type '(cygwin windows-nt))
+      (concat tramp-root-regexp "[^/]\\{2,\\}\\'")
+    (concat tramp-root-regexp "[^/]*\\'"))
   "Value for `tramp-completion-file-name-regexp' for unified remoting.
 GNU Emacs uses a unified filename syntax for Tramp and Ange-FTP.
-See `tramp-file-name-structure' for more explanations.")
+See `tramp-file-name-structure' for more explanations.
+
+On W32 systems, the volume letter must be ignored.")
 
 ;;;###autoload
 (defconst tramp-completion-file-name-regexp-separate
@@ -1972,13 +1902,13 @@ This string is passed to `format', so percent characters need to be doubled.")
 
 (defconst tramp-vc-registered-read-file-names
   "echo \"(\"
-for file in \"$@\"; do
-    if %s $file; then
+while read file; do
+    if %s \"$file\"; then
        echo \"(\\\"$file\\\" \\\"file-exists-p\\\" t)\"
     else
        echo \"(\\\"$file\\\" \\\"file-exists-p\\\" nil)\"
     fi
-    if %s $file; then
+    if %s \"$file\"; then
        echo \"(\\\"$file\\\" \\\"file-readable-p\\\" t)\"
     else
        echo \"(\\\"$file\\\" \\\"file-readable-p\\\" nil)\"
@@ -1987,7 +1917,9 @@ done
 echo \")\""
   "Script to check existence of VC related files.
 It must be send formatted with two strings; the tests for file
-existence, and file readability.")
+existence, and file readability.  Input shall be read via
+here-document, otherwise the command could exceed maximum length
+of command line.")
 
 (defconst tramp-file-mode-type-map
   '((0  . "-")  ; Normal file (SVID-v2 and XPG2)
@@ -2084,6 +2016,7 @@ mentioned here will be handled by `tramp-file-name-handler-alist' or the
 normal Emacs functions.")
 
 ;; Handlers for foreign methods, like FTP or SMB, shall be plugged here.
+;;;###tramp-autoload
 (defvar tramp-foreign-file-name-handler-alist
   ;; (identity . tramp-sh-file-name-handler) should always be the last
   ;; entry, because `identity' always matches.
@@ -2094,207 +2027,425 @@ calling HANDLER.")
 
 ;;; Internal functions which must come first:
 
-(defsubst tramp-debug-message (vec fmt-string &rest args)
-  "Append message to debug buffer.
-Message is formatted with FMT-STRING as control string and the remaining
-ARGS to actually emit the message (if applicable)."
-  (when (get-buffer (tramp-buffer-name vec))
-    (with-current-buffer (tramp-get-debug-buffer vec)
-      (goto-char (point-max))
-      ;; Headline.
-      (when (bobp)
-       (insert
-        (format
-         ";; %sEmacs: %s Tramp: %s -*- mode: outline; -*-"
-         (if (featurep 'sxemacs) "SX" (if (featurep 'xemacs) "X" "GNU "))
-         emacs-version tramp-version)))
-      (unless (bolp)
-       (insert "\n"))
-      ;; Timestamp.
-      (let ((now (current-time)))
-        (insert (format-time-string "%T." now))
-        (insert (format "%06d " (nth 2 now))))
-      ;; Calling function.
-      (let ((btn 1) btf fn)
-       (while (not fn)
-         (setq btf (nth 1 (backtrace-frame btn)))
-         (if (not btf)
-             (setq fn "")
-           (when (symbolp btf)
-             (setq fn (symbol-name btf))
-             (unless (and (string-match "^tramp" fn)
-                          (not (string-match
-                                "^tramp\\(-debug\\)?\\(-message\\|-error\\|-compat-funcall\\)$"
-                                fn)))
-               (setq fn nil)))
-           (setq btn (1+ btn))))
-       ;; The following code inserts filename and line number.
-       ;; Should be deactivated by default, because it is time
-       ;; consuming.
-;      (let ((ffn (find-function-noselect (intern fn))))
-;        (insert
-;         (format
-;          "%s:%d: "
-;          (file-name-nondirectory (buffer-file-name (car ffn)))
-;          (with-current-buffer (car ffn)
-;            (1+ (count-lines (point-min) (cdr ffn)))))))
-       (insert (format "%s " fn)))
-      ;; The message.
-      (insert (apply 'format fmt-string args)))))
-
-(defvar tramp-message-show-message t
-  "Show Tramp message in the minibuffer.
-This variable is used to disable messages from `tramp-error'.
-The messages are visible anyway, because an error is raised.")
-
-(defsubst tramp-message (vec-or-proc level fmt-string &rest args)
-  "Emit a message depending on verbosity level.
-VEC-OR-PROC identifies the Tramp buffer to use.  It can be either a
-vector or a process.  LEVEL says to be quiet if `tramp-verbose' is
-less than LEVEL.  The message is emitted only if `tramp-verbose' is
-greater than or equal to LEVEL.
 
-The message is also logged into the debug buffer when `tramp-verbose'
-is greater than or equal 4.
+;; ------------------------------------------------------------
+;; -- Tramp file names --
+;; ------------------------------------------------------------
+;; Conversion functions between external representation and
+;; internal data structure.  Convenience functions for internal
+;; data structure.
 
-Calls functions `message' and `tramp-debug-message' with FMT-STRING as
-control string and the remaining ARGS to actually emit the message (if
-applicable)."
-  (condition-case nil
-      (when (<= level tramp-verbose)
-       ;; Match data must be preserved!
-       (save-match-data
-         ;; Display only when there is a minimum level.
-         (when (and tramp-message-show-message (<= level 3))
-           (apply 'message
-                  (concat
-                   (cond
-                    ((= level 0) "")
-                    ((= level 1) "")
-                    ((= level 2) "Warning: ")
-                    (t           "Tramp: "))
-                   fmt-string)
-                  args))
-         ;; Log only when there is a minimum level.
-         (when (>= tramp-verbose 4)
-           (when (and vec-or-proc
-                      (processp vec-or-proc)
-                      (buffer-name (process-buffer vec-or-proc)))
-             (with-current-buffer (process-buffer vec-or-proc)
-               ;; Translate proc to vec.
-               (setq vec-or-proc (tramp-dissect-file-name default-directory))))
-           (when (and vec-or-proc (vectorp vec-or-proc))
-             (apply 'tramp-debug-message
-                    vec-or-proc
-                    (concat (format "(%d) # " level) fmt-string)
-                    args)))))
-    ;; Suppress all errors.
-    (error nil)))
+(defun tramp-file-name-p (vec)
+  "Check, whether VEC is a Tramp object."
+  (and (vectorp vec) (= 4 (length vec))))
 
-(defsubst tramp-error (vec-or-proc signal fmt-string &rest args)
-  "Emit an error.
-VEC-OR-PROC identifies the connection to use, SIGNAL is the
-signal identifier to be raised, remaining args passed to
-`tramp-message'.  Finally, signal SIGNAL is raised."
-  (let (tramp-message-show-message)
-    (tramp-message
-     vec-or-proc 1 "%s"
-     (error-message-string
-      (list signal
-           (get signal 'error-message)
-           (apply 'format fmt-string args))))
-    (signal signal (list (apply 'format fmt-string args)))))
+(defun tramp-file-name-method (vec)
+  "Return method component of VEC."
+  (and (tramp-file-name-p vec) (aref vec 0)))
 
-(defsubst tramp-error-with-buffer
-  (buffer vec-or-proc signal fmt-string &rest args)
-  "Emit an error, and show BUFFER.
-If BUFFER is nil, show the connection buffer.  Wait for 30\", or until
-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))
-                (not (tramp-completion-mode-p)))
-       (let ((enable-recursive-minibuffers t))
-         (pop-to-buffer
-          (or (and (bufferp buffer) buffer)
-              (and (processp vec-or-proc) (process-buffer vec-or-proc))
-              (tramp-get-buffer vec-or-proc)))
-         (sit-for 30))))))
+(defun tramp-file-name-user (vec)
+  "Return user component of VEC."
+  (and (tramp-file-name-p vec) (aref vec 1)))
 
-(defmacro with-parsed-tramp-file-name (filename var &rest body)
-  "Parse a Tramp filename and make components available in the body.
+(defun tramp-file-name-host (vec)
+  "Return host component of VEC."
+  (and (tramp-file-name-p vec) (aref vec 2)))
 
-First arg FILENAME is evaluated and dissected into its components.
-Second arg VAR is a symbol.  It is used as a variable name to hold
-the filename structure.  It is also used as a prefix for the variables
-holding the components.  For example, if VAR is the symbol `foo', then
-`foo' will be bound to the whole structure, `foo-method' will be bound to
-the method component, and so on for `foo-user', `foo-host', `foo-localname'.
+(defun tramp-file-name-localname (vec)
+  "Return localname component of VEC."
+  (and (tramp-file-name-p vec) (aref vec 3)))
 
-Remaining args are Lisp expressions to be evaluated (inside an implicit
-`progn').
+;; The user part of a Tramp file name vector can be of kind
+;; "user%domain".  Sometimes, we must extract these parts.
+(defun tramp-file-name-real-user (vec)
+  "Return the user name of VEC without domain."
+  (save-match-data
+    (let ((user (tramp-file-name-user vec)))
+      (if (and (stringp user)
+              (string-match tramp-user-with-domain-regexp user))
+         (match-string 1 user)
+       user))))
 
-If VAR is nil, then we bind `v' to the structure and `method', `user',
-`host', `localname' to the components."
-  `(let* ((,(or var 'v) (tramp-dissect-file-name ,filename))
-         (,(if var (intern (concat (symbol-name var) "-method")) 'method)
-          (tramp-file-name-method ,(or var 'v)))
-         (,(if var (intern (concat (symbol-name var) "-user")) 'user)
-          (tramp-file-name-user ,(or var 'v)))
-         (,(if var (intern (concat (symbol-name var) "-host")) 'host)
-          (tramp-file-name-host ,(or var 'v)))
-         (,(if var (intern (concat (symbol-name var) "-localname")) 'localname)
-          (tramp-file-name-localname ,(or var 'v))))
-     ,@body))
+(defun tramp-file-name-domain (vec)
+  "Return the domain name of VEC."
+  (save-match-data
+    (let ((user (tramp-file-name-user vec)))
+      (and (stringp user)
+          (string-match tramp-user-with-domain-regexp user)
+          (match-string 2 user)))))
 
-(put 'with-parsed-tramp-file-name 'lisp-indent-function 2)
-(put 'with-parsed-tramp-file-name 'edebug-form-spec '(form symbolp body))
-(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-parsed-tramp-file-name\\>"))
+;; The host part of a Tramp file name vector can be of kind
+;; "host#port".  Sometimes, we must extract these parts.
+(defun tramp-file-name-real-host (vec)
+  "Return the host name of VEC without port."
+  (save-match-data
+    (let ((host (tramp-file-name-host vec)))
+      (if (and (stringp host)
+              (string-match tramp-host-with-port-regexp host))
+         (match-string 1 host)
+       host))))
 
-(defmacro with-file-property (vec file property &rest body)
-  "Check in Tramp cache for PROPERTY, otherwise execute BODY and set cache.
-FILE must be a local file name on a connection identified via VEC."
-  `(if (file-name-absolute-p ,file)
-      (let ((value (tramp-get-file-property ,vec ,file ,property 'undef)))
-       (when (eq value 'undef)
-         ;; We cannot pass @body as parameter to
-         ;; `tramp-set-file-property' because it mangles our
-         ;; debug messages.
-         (setq value (progn ,@body))
-         (tramp-set-file-property ,vec ,file ,property value))
-       value)
-     ,@body))
+(defun tramp-file-name-port (vec)
+  "Return the port number of VEC."
+  (save-match-data
+    (let ((host (tramp-file-name-host vec)))
+      (and (stringp host)
+          (string-match tramp-host-with-port-regexp host)
+          (string-to-number (match-string 2 host))))))
 
-(put 'with-file-property 'lisp-indent-function 3)
-(put 'with-file-property 'edebug-form-spec t)
-(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-file-property\\>"))
-
-(defmacro with-connection-property (key property &rest body)
-  "Check in Tramp for property PROPERTY, otherwise executes BODY and set."
-  `(let ((value (tramp-get-connection-property ,key ,property 'undef)))
-    (when (eq value 'undef)
-      ;; We cannot pass ,@body as parameter to
-      ;; `tramp-set-connection-property' because it mangles our debug
-      ;; messages.
-      (setq value (progn ,@body))
-      (tramp-set-connection-property ,key ,property value))
-    value))
-
-(put 'with-connection-property 'lisp-indent-function 2)
-(put 'with-connection-property 'edebug-form-spec t)
-(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-connection-property\\>"))
+;;;###tramp-autoload
+(defun tramp-tramp-file-p (name)
+  "Return t if NAME is a string with Tramp file name syntax."
+  (save-match-data
+    (and (stringp name) (string-match tramp-file-name-regexp name))))
 
-(defun tramp-progress-reporter-update (reporter &optional value)
-  (let* ((parameters (cdr reporter))
-        (message (aref parameters 3)))
-    (when (string-match message (or (current-message) ""))
-      (funcall 'progress-reporter-update reporter value))))
+(defun tramp-find-method (method user host)
+  "Return the right method string to use.
+This is METHOD, if non-nil. Otherwise, do a lookup in
+`tramp-default-method-alist'."
+  (or method
+      (let ((choices tramp-default-method-alist)
+           lmethod item)
+       (while choices
+         (setq item (pop choices))
+         (when (and (string-match (or (nth 0 item) "") (or host ""))
+                    (string-match (or (nth 1 item) "") (or user "")))
+           (setq lmethod (nth 2 item))
+           (setq choices nil)))
+       lmethod)
+      tramp-default-method))
 
-(defmacro with-progress-reporter (vec level message &rest body)
-  "Executes BODY, spinning a progress reporter with MESSAGE.
-If LEVEL does not fit for visible messages, or if this is a
+(defun tramp-find-user (method user host)
+  "Return the right user string to use.
+This is USER, if non-nil. Otherwise, do a lookup in
+`tramp-default-user-alist'."
+  (or user
+      (let ((choices tramp-default-user-alist)
+           luser item)
+       (while choices
+         (setq item (pop choices))
+         (when (and (string-match (or (nth 0 item) "") (or method ""))
+                    (string-match (or (nth 1 item) "") (or host "")))
+           (setq luser (nth 2 item))
+           (setq choices nil)))
+       luser)
+      tramp-default-user))
+
+(defun tramp-find-host (method user host)
+  "Return the right host string to use.
+This is HOST, if non-nil. Otherwise, it is `tramp-default-host'."
+  (or (and (> (length host) 0) host)
+      tramp-default-host))
+
+(defun tramp-dissect-file-name (name &optional nodefault)
+  "Return a `tramp-file-name' structure.
+The structure consists of remote method, remote user, remote host
+and localname (file name on remote host).  If NODEFAULT is
+non-nil, the file name parts are not expanded to their default
+values."
+  (save-match-data
+    (let ((match (string-match (nth 0 tramp-file-name-structure) name)))
+      (unless match (error "Not a Tramp file name: %s" name))
+      (let ((method    (match-string (nth 1 tramp-file-name-structure) name))
+           (user      (match-string (nth 2 tramp-file-name-structure) name))
+           (host      (match-string (nth 3 tramp-file-name-structure) name))
+           (localname (match-string (nth 4 tramp-file-name-structure) name)))
+       (when (member method '("multi" "multiu"))
+         (error
+          "`%s' method is no longer supported, see (info \"(tramp)Multi-hops\")"
+          method))
+       (when host
+         (when (string-match tramp-prefix-ipv6-regexp host)
+           (setq host (replace-match "" nil t host)))
+         (when (string-match tramp-postfix-ipv6-regexp host)
+           (setq host (replace-match "" nil t host))))
+       (if nodefault
+           (vector method user host localname)
+         (vector
+          (tramp-find-method method user host)
+          (tramp-find-user   method user host)
+          (tramp-find-host   method user host)
+          localname))))))
+
+(defun tramp-buffer-name (vec)
+  "A name for the connection buffer VEC."
+  ;; We must use `tramp-file-name-real-host', because for gateway
+  ;; methods the default port will be expanded later on, which would
+  ;; tamper the name.
+  (let ((method (tramp-file-name-method vec))
+       (user   (tramp-file-name-user vec))
+       (host   (tramp-file-name-real-host vec)))
+    (if (not (zerop (length user)))
+       (format "*tramp/%s %s@%s*" method user host)
+      (format "*tramp/%s %s*" method host))))
+
+(defun tramp-make-tramp-file-name (method user host localname)
+  "Constructs a Tramp file name from METHOD, USER, HOST and LOCALNAME."
+  (concat tramp-prefix-format
+         (when (not (zerop (length method)))
+           (concat method tramp-postfix-method-format))
+         (when (not (zerop (length user)))
+           (concat user tramp-postfix-user-format))
+         (when host
+           (if (string-match tramp-ipv6-regexp host)
+               (concat tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
+             host))
+         tramp-postfix-host-format
+         (when localname localname)))
+
+(defun tramp-completion-make-tramp-file-name (method user host localname)
+  "Constructs a Tramp file name from METHOD, USER, HOST and LOCALNAME.
+It must not be a complete Tramp file name, but as long as there are
+necessary only.  This function will be used in file name completion."
+  (concat tramp-prefix-format
+         (when (not (zerop (length method)))
+           (concat method tramp-postfix-method-format))
+         (when (not (zerop (length user)))
+           (concat user tramp-postfix-user-format))
+         (when (not (zerop (length host)))
+           (concat
+            (if (string-match tramp-ipv6-regexp host)
+                (concat tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
+              host)
+            tramp-postfix-host-format))
+         (when localname localname)))
+
+(defun tramp-get-buffer (vec)
+  "Get the connection buffer to be used for VEC."
+  (or (get-buffer (tramp-buffer-name vec))
+      (with-current-buffer (get-buffer-create (tramp-buffer-name vec))
+       (setq buffer-undo-list t)
+       (setq default-directory
+             (tramp-make-tramp-file-name
+              (tramp-file-name-method vec)
+              (tramp-file-name-user vec)
+              (tramp-file-name-host vec)
+              "/"))
+       (current-buffer))))
+
+(defun tramp-get-connection-buffer (vec)
+  "Get the connection buffer to be used for VEC.
+In case a second asynchronous communication has been started, it is different
+from `tramp-get-buffer'."
+  (or (tramp-get-connection-property vec "process-buffer" nil)
+      (tramp-get-buffer vec)))
+
+(defun tramp-get-connection-process (vec)
+  "Get the connection process to be used for VEC.
+In case a second asynchronous communication has been started, it is different
+from the default one."
+  (get-process
+   (or (tramp-get-connection-property vec "process-name" nil)
+       (tramp-buffer-name vec))))
+
+(defun tramp-debug-buffer-name (vec)
+  "A name for the debug buffer for VEC."
+  ;; We must use `tramp-file-name-real-host', because for gateway
+  ;; methods the default port will be expanded later on, which would
+  ;; tamper the name.
+  (let ((method (tramp-file-name-method vec))
+       (user   (tramp-file-name-user vec))
+       (host   (tramp-file-name-real-host vec)))
+    (if (not (zerop (length user)))
+       (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
+      ;; `outline-mode-hook'.  We must prevent that local processes
+      ;; 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) tramp-debug-outline-regexp)
+      (set (make-local-variable 'outline-level) 'tramp-outline-level))
+    (current-buffer)))
+
+(defun tramp-outline-level ()
+  "Return the depth to which a statement is nested in the outline.
+Point must be at the beginning of a header line.
+
+The outline level is equal to the verbosity of the Tramp message."
+  (1+ (string-to-number (match-string 1))))
+
+(defsubst tramp-debug-message (vec fmt-string &rest args)
+  "Append message to debug buffer.
+Message is formatted with FMT-STRING as control string and the remaining
+ARGS to actually emit the message (if applicable)."
+  (when (get-buffer (tramp-buffer-name vec))
+    (with-current-buffer (tramp-get-debug-buffer vec)
+      (goto-char (point-max))
+      ;; Headline.
+      (when (bobp)
+       (insert
+        (format
+         ";; %sEmacs: %s Tramp: %s -*- mode: outline; -*-"
+         (if (featurep 'sxemacs) "SX" (if (featurep 'xemacs) "X" "GNU "))
+         emacs-version tramp-version)))
+      (unless (bolp)
+       (insert "\n"))
+      ;; Timestamp.
+      (let ((now (current-time)))
+        (insert (format-time-string "%T." now))
+        (insert (format "%06d " (nth 2 now))))
+      ;; Calling function.
+      (let ((btn 1) btf fn)
+       (while (not fn)
+         (setq btf (nth 1 (backtrace-frame btn)))
+         (if (not btf)
+             (setq fn "")
+           (when (symbolp btf)
+             (setq fn (symbol-name btf))
+             (unless (and (string-match "^tramp" fn)
+                          (not (string-match
+                                "^tramp\\(-debug\\)?\\(-message\\|-error\\|-compat-funcall\\)$"
+                                fn)))
+               (setq fn nil)))
+           (setq btn (1+ btn))))
+       ;; The following code inserts filename and line number.
+       ;; Should be deactivated by default, because it is time
+       ;; consuming.
+;      (let ((ffn (find-function-noselect (intern fn))))
+;        (insert
+;         (format
+;          "%s:%d: "
+;          (file-name-nondirectory (buffer-file-name (car ffn)))
+;          (with-current-buffer (car ffn)
+;            (1+ (count-lines (point-min) (cdr ffn)))))))
+       (insert (format "%s " fn)))
+      ;; The message.
+      (insert (apply 'format fmt-string args)))))
+
+(defvar tramp-message-show-message t
+  "Show Tramp message in the minibuffer.
+This variable is used to disable messages from `tramp-error'.
+The messages are visible anyway, because an error is raised.")
+
+(defsubst tramp-message (vec-or-proc level fmt-string &rest args)
+  "Emit a message depending on verbosity level.
+VEC-OR-PROC identifies the Tramp buffer to use.  It can be either a
+vector or a process.  LEVEL says to be quiet if `tramp-verbose' is
+less than LEVEL.  The message is emitted only if `tramp-verbose' is
+greater than or equal to LEVEL.
+
+The message is also logged into the debug buffer when `tramp-verbose'
+is greater than or equal 4.
+
+Calls functions `message' and `tramp-debug-message' with FMT-STRING as
+control string and the remaining ARGS to actually emit the message (if
+applicable)."
+  (condition-case nil
+      (when (<= level tramp-verbose)
+       ;; Match data must be preserved!
+       (save-match-data
+         ;; Display only when there is a minimum level.
+         (when (and tramp-message-show-message (<= level 3))
+           (apply 'message
+                  (concat
+                   (cond
+                    ((= level 0) "")
+                    ((= level 1) "")
+                    ((= level 2) "Warning: ")
+                    (t           "Tramp: "))
+                   fmt-string)
+                  args))
+         ;; Log only when there is a minimum level.
+         (when (>= tramp-verbose 4)
+           (when (and vec-or-proc
+                      (processp vec-or-proc)
+                      (buffer-name (process-buffer vec-or-proc)))
+             (with-current-buffer (process-buffer vec-or-proc)
+               ;; Translate proc to vec.
+               (setq vec-or-proc (tramp-dissect-file-name default-directory))))
+           (when (and vec-or-proc (vectorp vec-or-proc))
+             (apply 'tramp-debug-message
+                    vec-or-proc
+                    (concat (format "(%d) # " level) fmt-string)
+                    args)))))
+    ;; Suppress all errors.
+    (error nil)))
+
+(defsubst tramp-error (vec-or-proc signal fmt-string &rest args)
+  "Emit an error.
+VEC-OR-PROC identifies the connection to use, SIGNAL is the
+signal identifier to be raised, remaining args passed to
+`tramp-message'.  Finally, signal SIGNAL is raised."
+  (let (tramp-message-show-message)
+    (tramp-message
+     vec-or-proc 1 "%s"
+     (error-message-string
+      (list signal
+           (get signal 'error-message)
+           (apply 'format fmt-string args))))
+    (signal signal (list (apply 'format fmt-string args)))))
+
+(defsubst tramp-error-with-buffer
+  (buffer vec-or-proc signal fmt-string &rest args)
+  "Emit an error, and show BUFFER.
+If BUFFER is nil, show the connection buffer.  Wait for 30\", or until
+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))
+                (not (tramp-completion-mode-p)))
+       (let ((enable-recursive-minibuffers t))
+         (pop-to-buffer
+          (or (and (bufferp buffer) buffer)
+              (and (processp vec-or-proc) (process-buffer vec-or-proc))
+              (tramp-get-buffer vec-or-proc)))
+         (sit-for 30))))))
+
+(defmacro with-parsed-tramp-file-name (filename var &rest body)
+  "Parse a Tramp filename and make components available in the body.
+
+First arg FILENAME is evaluated and dissected into its components.
+Second arg VAR is a symbol.  It is used as a variable name to hold
+the filename structure.  It is also used as a prefix for the variables
+holding the components.  For example, if VAR is the symbol `foo', then
+`foo' will be bound to the whole structure, `foo-method' will be bound to
+the method component, and so on for `foo-user', `foo-host', `foo-localname'.
+
+Remaining args are Lisp expressions to be evaluated (inside an implicit
+`progn').
+
+If VAR is nil, then we bind `v' to the structure and `method', `user',
+`host', `localname' to the components."
+  `(let* ((,(or var 'v) (tramp-dissect-file-name ,filename))
+         (,(if var (intern (concat (symbol-name var) "-method")) 'method)
+          (tramp-file-name-method ,(or var 'v)))
+         (,(if var (intern (concat (symbol-name var) "-user")) 'user)
+          (tramp-file-name-user ,(or var 'v)))
+         (,(if var (intern (concat (symbol-name var) "-host")) 'host)
+          (tramp-file-name-host ,(or var 'v)))
+         (,(if var (intern (concat (symbol-name var) "-localname")) 'localname)
+          (tramp-file-name-localname ,(or var 'v))))
+     ,@body))
+
+(put 'with-parsed-tramp-file-name 'lisp-indent-function 2)
+(put 'with-parsed-tramp-file-name 'edebug-form-spec '(form symbolp body))
+(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-parsed-tramp-file-name\\>"))
+
+(defun tramp-progress-reporter-update (reporter &optional value)
+  (let* ((parameters (cdr reporter))
+        (message (aref parameters 3)))
+    (when (string-match message (or (current-message) ""))
+      (funcall 'progress-reporter-update reporter value))))
+
+(defmacro with-progress-reporter (vec level message &rest body)
+  "Executes BODY, spinning a progress reporter with MESSAGE.
+If LEVEL does not fit for visible messages, or if this is a
 nested call of the macro, there are only traces without a visible
 progress reporter."
   `(let (pr tm)
@@ -2361,7 +2512,7 @@ Return the local name of the temporary file."
          (setq result nil)
        ;; This creates the file by side effect.
        (set-file-times result)
-       (set-file-modes result (tramp-octal-to-decimal "0700"))))
+       (set-file-modes result (tramp-compat-octal-to-decimal "0700"))))
 
     ;; Return the local part.
     (with-parsed-tramp-file-name result nil localname)))
@@ -2401,7 +2552,7 @@ Example:
                       ;; Windows registry.
                       (and (memq system-type '(cygwin windows-nt))
                            (zerop
-                            (tramp-local-call-process
+                            (tramp-compat-call-process
                              "reg" nil nil nil "query" (nth 1 (car v)))))
                     ;; Configuration file.
                     (file-exists-p (nth 1 (car v)))))
@@ -2539,7 +2690,7 @@ target of the symlink differ."
       (unless ln
        (tramp-error
         l 'file-error
-        "Making a symbolic link. ln(1) does not exist on the remote host."))
+        "Making a symbolic link.  ln(1) does not exist on the remote host."))
 
       ;; Do the 'confirm if exists' thing.
       (when (file-exists-p linkname)
@@ -2560,6 +2711,9 @@ target of the symlink differ."
              (tramp-file-name-localname
               (tramp-dissect-file-name (expand-file-name filename)))))
 
+      (tramp-flush-file-property l (file-name-directory l-localname))
+      (tramp-flush-file-property l l-localname)
+
       ;; Right, they are on the same host, regardless of user, method, etc.
       ;; We now make the link on the remote machine. This will occur as the user
       ;; that FILENAME belongs to.
@@ -3010,7 +3164,7 @@ of."
     (unless (zerop (tramp-send-command-and-check
                    v
                    (format "chmod %s %s"
-                           (tramp-decimal-to-octal mode)
+                           (tramp-compat-decimal-to-octal mode)
                            (tramp-shell-quote-argument localname))))
       ;; FIXME: extract the proper text from chmod's stderr.
       (tramp-error
@@ -3041,7 +3195,7 @@ of."
      ;; We handle also the local part, because in older Emacsen,
      ;; without `set-file-times', this function is an alias for this.
      ;; We are local, so we don't need the UTC settings.
-     (tramp-local-call-process
+     (tramp-compat-call-process
       "touch" nil nil nil "-t"
       (format-time-string "%Y%m%d%H%M.%S" time)
       (tramp-shell-quote-argument filename)))))
@@ -3074,7 +3228,7 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
       ;; `set-file-uid-gid'.  On W32 "chown" might not work.
       (let ((uid (or (and (integerp uid) uid) (tramp-get-local-uid 'integer)))
            (gid (or (and (integerp gid) gid) (tramp-get-local-gid 'integer))))
-       (tramp-local-call-process
+       (tramp-compat-call-process
         "chown" nil nil nil
          (format "%d:%d" uid gid) (tramp-shell-quote-argument filename))))))
 
@@ -3202,7 +3356,7 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
 If the file modes of FILENAME cannot be determined, return the
 value of `default-file-modes', without execute permissions."
   (or (file-modes filename)
-      (logand (default-file-modes) (tramp-octal-to-decimal "0666"))))
+      (logand (default-file-modes) (tramp-compat-octal-to-decimal "0666"))))
 
 (defun tramp-handle-file-directory-p (filename)
   "Like `file-directory-p' for Tramp files."
@@ -3889,7 +4043,8 @@ the uid and gid from FILENAME."
                      ;; Since this does not work reliable, we also
                      ;; give read permissions.
                      (set-file-modes
-                      (concat prefix tmpfile) (tramp-octal-to-decimal "0777"))
+                      (concat prefix tmpfile)
+                      (tramp-compat-octal-to-decimal "0777"))
                      (tramp-set-file-uid-gid
                       (concat prefix tmpfile)
                       (tramp-get-local-uid 'integer)
@@ -3905,7 +4060,8 @@ the uid and gid from FILENAME."
                      ;; We must change the ownership as local user.
                      ;; Since this does not work reliable, we also
                      ;; give read permissions.
-                     (set-file-modes tmpfile (tramp-octal-to-decimal "0777"))
+                     (set-file-modes
+                      tmpfile (tramp-compat-octal-to-decimal "0777"))
                      (tramp-set-file-uid-gid
                       tmpfile
                       (tramp-get-remote-uid v 'integer)
@@ -4223,7 +4379,7 @@ This is like `dired-recursive-delete-directory' for Tramp files."
   ;; DIR-P is valid for XEmacs only.
   (with-parsed-tramp-file-name
       (if (or dir-p (file-directory-p dir)) dir (file-name-directory dir)) nil
-    (tramp-flush-file-property v localname)))
+    (tramp-flush-directory-property v localname)))
 
 ;; Pacify byte-compiler.  The function is needed on XEmacs only.  I'm
 ;; not sure at all that this is the right way to do it, but let's hope
@@ -4492,20 +4648,30 @@ beginning of local filename are not substituted."
   (with-parsed-tramp-file-name default-directory nil
     (tramp-find-executable v command (tramp-get-remote-path v) t)))
 
+(defun tramp-process-sentinel (proc event)
+  "Flush file caches."
+  (unless (memq (process-status proc) '(run open))
+    (let ((vec (tramp-get-connection-property proc "vector" nil)))
+      (when vec
+       (tramp-message vec 5 "Sentinel called: `%s' `%s'" proc event)
+        (tramp-flush-directory-property vec "")))))
+
 ;; We use BUFFER also as connection buffer during setup. Because of
 ;; this, its original contents must be saved, and restored once
 ;; connection has been setup.
 (defun tramp-handle-start-file-process (name buffer program &rest args)
   "Like `start-file-process' for Tramp files."
   (with-parsed-tramp-file-name default-directory nil
-    (unless (stringp program)
-      (tramp-error
-       v 'file-error "pty association is not supported for `%s'" name))
     (unwind-protect
-       (let ((command (format "cd %s; exec %s"
-                              (tramp-shell-quote-argument localname)
-                              (mapconcat 'tramp-shell-quote-argument
-                                         (cons program args) " ")))
+       ;; When PROGRAM is nil, we just provide a tty.
+       (let ((command
+              (when (stringp program)
+                (format "cd %s; exec %s"
+                        (tramp-shell-quote-argument localname)
+                        (mapconcat 'tramp-shell-quote-argument
+                                   (cons program args) " "))))
+             (tramp-process-connection-type
+              (or (null program) tramp-process-connection-type))
              (name1 name)
              (i 0))
          (unless buffer
@@ -4525,14 +4691,21 @@ beginning of local filename are not substituted."
          (with-current-buffer (tramp-get-connection-buffer v)
            (clear-visited-file-modtime)
            (narrow-to-region (point-max) (point-max)))
-         ;; Send the command.  `tramp-send-command' opens a new
-         ;; connection.
-         (tramp-send-command v command nil t) ; nooutput
-         ;; Set query flag for this process.
-         (tramp-set-process-query-on-exit-flag
-          (tramp-get-connection-process v) t)
-         ;; Return process.
-         (tramp-get-connection-process v))
+         (if command
+             ;; Send the command.
+             (tramp-send-command v command nil t) ; nooutput
+           ;; Check, whether a pty is associated.
+           (tramp-maybe-open-connection v)
+           (unless (process-get (tramp-get-connection-process v) 'remote-tty)
+             (tramp-error
+              v 'file-error "pty association is not supported for `%s'" name)))
+         (let ((p (tramp-get-connection-process v)))
+           ;; Set sentinel and query flag for this process.
+           (tramp-set-connection-property p "vector" v)
+           (set-process-sentinel p 'tramp-process-sentinel)
+           (tramp-set-process-query-on-exit-flag p t)
+           ;; Return process.
+           p))
       ;; Save exit.
       (with-current-buffer (tramp-get-connection-buffer v)
        (if (string-match tramp-temp-buffer-name (buffer-name))
@@ -4608,7 +4781,9 @@ beginning of local filename are not substituted."
        (setq outbuf (current-buffer))))
       (when stderr (setq command (format "%s 2>%s" command stderr)))
 
-      ;; Send the command.  It might not return in time, so we protect it.
+      ;; Send the command.  It might not return in time, so we protect
+      ;; it.  Call it in a subshell, in order to preserve working
+      ;; directory.
       (condition-case nil
          (unwind-protect
               (setq ret
@@ -4616,7 +4791,7 @@ beginning of local filename are not substituted."
                      v (format "\\cd %s; %s"
                                (tramp-shell-quote-argument localname)
                                command)
-                    nil t))
+                    t t))
            ;; We should show the output anyway.
            (when outbuf
              (with-current-buffer outbuf
@@ -4654,20 +4829,6 @@ beginning of local filename are not substituted."
          (keyboard-quit)
        ret))))
 
-(defun tramp-local-call-process
-  (program &optional infile destination display &rest args)
-  "Calls `call-process' on the local host.
-This is needed because for some Emacs flavors Tramp has
-defadviced `call-process' to behave like `process-file'.  The
-Lisp error raised when PROGRAM is nil is trapped also, returning 1."
-  (let ((default-directory
-         (if (file-remote-p default-directory)
-             (tramp-compat-temporary-file-directory)
-           default-directory)))
-    (if (executable-find program)
-       (apply 'call-process program infile destination display args)
-      1)))
-
 (defun tramp-handle-call-process-region
   (start end program &optional delete buffer display &rest args)
   "Like `call-process-region' for Tramp files."
@@ -4737,7 +4898,7 @@ Lisp error raised when PROGRAM is nil is trapped also, returning 1."
          ;; Display output.
          (pop-to-buffer output-buffer)
          (setq mode-line-process '(":%s"))
-         (require 'shell) (shell-mode))
+         (shell-mode))
 
       (prog1
          ;; Run the process.
@@ -4946,7 +5107,7 @@ coding system might not be determined.  This function repairs it."
              ;; 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"))
+             (set-file-modes local-copy (tramp-compat-octal-to-decimal "0600"))
 
              (when (and (null remote-copy)
                         (tramp-get-method-parameter
@@ -5184,7 +5345,8 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
          ;; Ensure, that it is still readable.
          (when modes
            (set-file-modes
-            tmpfile (logior (or modes 0) (tramp-octal-to-decimal "0400"))))
+            tmpfile
+            (logior (or modes 0) (tramp-compat-octal-to-decimal "0400"))))
 
          ;; This is a bit lengthy due to the different methods
          ;; possible for file transfer.  First, we check whether the
@@ -5283,7 +5445,7 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
                        (erase-buffer)
                        (and
                         ;; cksum runs locally, if possible.
-                        (zerop (tramp-local-call-process "cksum" tmpfile t))
+                        (zerop (tramp-compat-call-process "cksum" tmpfile t))
                         ;; cksum runs remotely.
                         (zerop
                          (tramp-send-command-and-check
@@ -5391,10 +5553,10 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
                 (tramp-send-command-and-read
                  v
                  (format
-                  "tramp_vc_registered_read_file_names %s"
+                  "tramp_vc_registered_read_file_names <<'EOF'\n%s\nEOF\n"
                   (mapconcat 'tramp-shell-quote-argument
                              tramp-vc-registered-file-names
-                             " "))))
+                             "\n"))))
 
              (tramp-set-file-property
               v (car elt) (cadr elt) (cadr (cdr elt))))))
@@ -5760,6 +5922,7 @@ should never be set globally, the intention is to let-bind it.")
 ;; Tramp file name syntax. Maybe another variable should be introduced
 ;; overwriting this check in such cases. Or we change Tramp file name
 ;; syntax in order to avoid ambiguities, like in XEmacs ...
+;;;###tramp-autoload
 (defun tramp-completion-mode-p ()
   "Check, whether method / user name / host name completion is active."
   (or
@@ -6309,7 +6472,7 @@ User is always nil."
   (let ((default-directory (tramp-compat-temporary-file-directory))
        res)
     (with-temp-buffer
-      (when (zerop (tramp-local-call-process "reg" nil t nil "query" registry))
+      (when (zerop (tramp-compat-call-process "reg" nil t nil "query" registry))
        (goto-char (point-min))
        (while (not (eobp))
          (push (tramp-parse-putty-group registry) res))))
@@ -6373,28 +6536,16 @@ Returns the exit code of the `test' program.  Barfs if the methods,
 hosts, or files, disagree."
   (unless (tramp-equal-remote file1 file2)
     (with-parsed-tramp-file-name (if (tramp-tramp-file-p file1) file1 file2) nil
-      (tramp-error
-       v 'file-error
-       "tramp-run-test2 only implemented for same method, user, host")))
-  (with-parsed-tramp-file-name file1 v1
-    (with-parsed-tramp-file-name file1 v2
-      (tramp-send-command-and-check
-       v1
-       (format format-string
-              (tramp-shell-quote-argument v1-localname)
-              (tramp-shell-quote-argument v2-localname))))))
-
-(defun tramp-buffer-name (vec)
-  "A name for the connection buffer VEC."
-  ;; We must use `tramp-file-name-real-host', because for gateway
-  ;; methods the default port will be expanded later on, which would
-  ;; tamper the name.
-  (let ((method (tramp-file-name-method vec))
-       (user   (tramp-file-name-user vec))
-       (host   (tramp-file-name-real-host vec)))
-    (if (not (zerop (length user)))
-       (format "*tramp/%s %s@%s*" method user host)
-      (format "*tramp/%s %s*" method host))))
+      (tramp-error
+       v 'file-error
+       "tramp-run-test2 only implemented for same method, user, host")))
+  (with-parsed-tramp-file-name file1 v1
+    (with-parsed-tramp-file-name file1 v2
+      (tramp-send-command-and-check
+       v1
+       (format format-string
+              (tramp-shell-quote-argument v1-localname)
+              (tramp-shell-quote-argument v2-localname))))))
 
 (defun tramp-delete-temp-file-function ()
   "Remove temporary files related to current buffer."
@@ -6409,74 +6560,6 @@ hosts, or files, disagree."
            (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))
-      (with-current-buffer (get-buffer-create (tramp-buffer-name vec))
-       (setq buffer-undo-list t)
-       (setq default-directory
-             (tramp-make-tramp-file-name
-              (tramp-file-name-method vec)
-              (tramp-file-name-user vec)
-              (tramp-file-name-host vec)
-              "/"))
-       (current-buffer))))
-
-(defun tramp-get-connection-buffer (vec)
-  "Get the connection buffer to be used for VEC.
-In case a second asynchronous communication has been started, it is different
-from `tramp-get-buffer'."
-  (or (tramp-get-connection-property vec "process-buffer" nil)
-      (tramp-get-buffer vec)))
-
-(defun tramp-get-connection-process (vec)
-  "Get the connection process to be used for VEC.
-In case a second asynchronous communication has been started, it is different
-from the default one."
-  (get-process
-   (or (tramp-get-connection-property vec "process-name" nil)
-       (tramp-buffer-name vec))))
-
-(defun tramp-debug-buffer-name (vec)
-  "A name for the debug buffer for VEC."
-  ;; We must use `tramp-file-name-real-host', because for gateway
-  ;; methods the default port will be expanded later on, which would
-  ;; tamper the name.
-  (let ((method (tramp-file-name-method vec))
-       (user   (tramp-file-name-user vec))
-       (host   (tramp-file-name-real-host vec)))
-    (if (not (zerop (length user)))
-       (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
-      ;; `outline-mode-hook'.  We must prevent that local processes
-      ;; 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) tramp-debug-outline-regexp)
-      (set (make-local-variable 'outline-level) 'tramp-outline-level))
-    (current-buffer)))
-
-(defun tramp-outline-level ()
-  "Return the depth to which a statement is nested in the outline.
-Point must be at the beginning of a header line.
-
-The outline level is equal to the verbosity of the Tramp message."
-  (1+ (string-to-number (match-string 1))))
-
 (defun tramp-find-executable
   (vec progname dirlist &optional ignore-tilde ignore-path)
   "Searches for PROGNAME in $PATH and all directories mentioned in DIRLIST.
@@ -6590,7 +6673,29 @@ file exists and nonzero exit status otherwise."
        vec 'file-error "Couldn't find command to check if file exists"))
     result))
 
-;; CCC test ksh or bash found for tilde expansion?
+(defun tramp-open-shell (vec shell)
+  "Opens shell SHELL."
+  (with-progress-reporter vec 5 (format "Opening remote shell `%s'" shell)
+    ;; Find arguments for this shell.
+    (let ((tramp-end-of-output tramp-initial-end-of-output)
+         (alist tramp-sh-extra-args)
+         item extra-args)
+      (while (and alist (null extra-args))
+       (setq item (pop alist))
+       (when (string-match (car item) shell)
+         (setq extra-args (cdr item))))
+      (when extra-args (setq shell (concat shell " " extra-args)))
+      (tramp-send-command
+       vec (format "exec env ENV='' PROMPT_COMMAND='' PS1=%s PS2='' PS3='' %s"
+                  (shell-quote-argument tramp-end-of-output) shell)
+       t))
+    ;; Setting prompts.
+    (tramp-send-command
+     vec (format "PS1=%s" (shell-quote-argument tramp-end-of-output)) t)
+    (tramp-send-command vec "PS2=''" t)
+    (tramp-send-command vec "PS3=''" t)
+    (tramp-send-command vec "PROMPT_COMMAND=''" t)))
+
 (defun tramp-find-shell (vec)
   "Opens a shell on the remote host which groks tilde expansion."
   (unless (tramp-get-connection-property vec "remote-shell" nil)
@@ -6611,29 +6716,9 @@ file exists and nonzero exit status otherwise."
            (tramp-error
             vec 'file-error
             "Couldn't find a shell which groks tilde expansion"))
-         ;; Find arguments for this shell.
-         (let ((alist tramp-sh-extra-args)
-               item extra-args)
-           (while (and alist (null extra-args))
-             (setq item (pop alist))
-             (when (string-match (car item) shell)
-               (setq extra-args (cdr item))))
-           (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 tramp-initial-end-of-output))
-           (tramp-send-command
-            vec
-            (format "PROMPT_COMMAND='' PS1=%s PS2='' PS3='' exec %s"
-                    (shell-quote-argument tramp-end-of-output) shell)
-            t))
-         ;; Setting prompts.
-         (with-progress-reporter vec 5 (format "Setting remote shell prompt")
-           (tramp-send-command
-            vec (format "PS1=%s" (shell-quote-argument tramp-end-of-output)) t)
-           (tramp-send-command vec "PS2=''" t)
-           (tramp-send-command vec "PS3=''" t)
-           (tramp-send-command vec "PROMPT_COMMAND=''" t)))
+         (tramp-open-shell vec shell))
 
         (t (tramp-message
             vec 5 "Remote `%s' groks tilde expansion, good"
@@ -6666,8 +6751,10 @@ file exists and nonzero exit status otherwise."
   "Query the user for a password."
   (with-current-buffer (process-buffer proc)
     (tramp-check-for-regexp proc tramp-password-prompt-regexp)
-    (tramp-message vec 3 "Sending %s" (match-string 1)))
-  (tramp-enter-password proc))
+    (tramp-message vec 3 "Sending %s" (match-string 1))
+    (tramp-enter-password proc)
+    ;; Hide password prompt.
+    (narrow-to-region (point-max) (point-max))))
 
 (defun tramp-action-succeed (proc vec)
   "Signal success in finding shell prompt."
@@ -6778,6 +6865,7 @@ The terminal type can be configured with `tramp-terminal-type'."
                      (tramp-process-one-action proc vec actions))
                  (tramp-process-one-action proc vec actions)))))
       (with-current-buffer (tramp-get-connection-buffer vec)
+       (widen)
        (tramp-message vec 6 "\n%s" (buffer-string)))
       (unless (eq exit 'ok)
        (tramp-clear-passwd vec)
@@ -6914,14 +7002,9 @@ process to set up.  VEC specifies the connection."
     ;; way, we avoid the startup file clobbering $PS1.  $PROMP_COMMAND
     ;; is another way to set the prompt in /bin/bash, it must be
     ;; discarded as well.
-    (tramp-send-command
+    (tramp-open-shell
      vec
-     (format
-      "exec env ENV='' PROMPT_COMMAND='' PS1=%s PS2='' PS3='' %s"
-      (shell-quote-argument tramp-end-of-output)
-      (tramp-get-method-parameter
-       (tramp-file-name-method vec) 'tramp-remote-sh))
-     t)
+     (tramp-get-method-parameter (tramp-file-name-method vec) 'tramp-remote-sh))
 
     ;; Disable echo.
     (tramp-message vec 5 "Setting up remote shell environment")
@@ -6979,7 +7062,7 @@ process to set up.  VEC specifies the connection."
        ;; stty, instead.
        (tramp-send-command vec "stty -onlcr" t))))
   ;; Dump stty settings in the traces.
-  (when (>= tramp-verbose 10)
+  (when (>= tramp-verbose 9)
     (tramp-send-command vec "stty -a" t))
   (tramp-send-command vec "set +o vi +o emacs" t)
 
@@ -7037,7 +7120,7 @@ process to set up.  VEC specifies the connection."
   ;; "echo $?"  part if the "test" part has an error.  In particular,
   ;; 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.
+  ;; in function declarations, or changing HISTFILE in place.
   ;; Therefore, OpenSolaris' /bin/sh is replaced by bash, when
   ;; detected.
   (tramp-find-shell vec)
@@ -7051,6 +7134,11 @@ process to set up.  VEC specifies the connection."
   (when (string-match "^IRIX64" (tramp-get-connection-property vec "uname" ""))
     (tramp-send-command vec "set +H" t))
 
+  ;; Set `remote-tty' process property.
+  (ignore-errors
+    (let ((tty (tramp-send-command-and-read vec "echo \\\"`tty`\\\"")))
+      (unless (zerop (length tty)) (process-put proc 'remote-tty tty))))
+
   ;; Set the environment.
   (tramp-message vec 5 "Setting default environment")
 
@@ -7254,7 +7342,7 @@ INPUT can also be nil which means `/dev/null'.
 OUTPUT can be a string (which specifies a filename), or t (which
 means standard output and thus the current buffer), or nil (which
 means discard it)."
-  (tramp-local-call-process
+  (tramp-compat-call-process
    tramp-encoding-shell
    (when (and input (not (string-match "%s" cmd))) input)
    (if (eq output t) t nil)
@@ -7357,12 +7445,10 @@ Gateway hops are already opened."
            (setq choices tramp-default-proxies-alist)))))
 
     ;; Handle gateways.
-    (when (and (boundp 'tramp-gw-tunnel-method)
-              (string-match (format
-                             "^\\(%s\\|%s\\)$"
-                             (symbol-value 'tramp-gw-tunnel-method)
-                             (symbol-value 'tramp-gw-socks-method))
-                            (tramp-file-name-method (car target-alist))))
+    (when (string-match
+          (format
+           "^\\(%s\\|%s\\)$" tramp-gw-tunnel-method tramp-gw-socks-method)
+          (tramp-file-name-method (car target-alist)))
       (let ((gw (pop target-alist))
            (hop (pop target-alist)))
        ;; Is the method prepared for gateways?
@@ -7659,6 +7745,7 @@ function waits for output unless NOOUTPUT is set."
       ;; Return value is whether end-of-output sentinel was found.
       found)))
 
+;;;###tramp-autoload
 (defun tramp-send-command-and-check
   (vec command &optional subshell dont-suppress-err)
   "Run COMMAND and check its exit status.
@@ -7767,57 +7854,57 @@ the remote host use line-endings as defined in the variable
     (save-match-data
       (logior
        (cond
-       ((char-equal owner-read ?r) (tramp-octal-to-decimal "00400"))
+       ((char-equal owner-read ?r) (tramp-compat-octal-to-decimal "00400"))
        ((char-equal owner-read ?-) 0)
        (t (error "Second char `%c' must be one of `r-'" owner-read)))
        (cond
-       ((char-equal owner-write ?w) (tramp-octal-to-decimal "00200"))
+       ((char-equal owner-write ?w) (tramp-compat-octal-to-decimal "00200"))
        ((char-equal owner-write ?-) 0)
        (t (error "Third char `%c' must be one of `w-'" owner-write)))
        (cond
        ((char-equal owner-execute-or-setid ?x)
-        (tramp-octal-to-decimal "00100"))
+        (tramp-compat-octal-to-decimal "00100"))
        ((char-equal owner-execute-or-setid ?S)
-        (tramp-octal-to-decimal "04000"))
+        (tramp-compat-octal-to-decimal "04000"))
        ((char-equal owner-execute-or-setid ?s)
-        (tramp-octal-to-decimal "04100"))
+        (tramp-compat-octal-to-decimal "04100"))
        ((char-equal owner-execute-or-setid ?-) 0)
        (t (error "Fourth char `%c' must be one of `xsS-'"
                  owner-execute-or-setid)))
        (cond
-       ((char-equal group-read ?r) (tramp-octal-to-decimal "00040"))
+       ((char-equal group-read ?r) (tramp-compat-octal-to-decimal "00040"))
        ((char-equal group-read ?-) 0)
        (t (error "Fifth char `%c' must be one of `r-'" group-read)))
        (cond
-       ((char-equal group-write ?w) (tramp-octal-to-decimal "00020"))
+       ((char-equal group-write ?w) (tramp-compat-octal-to-decimal "00020"))
        ((char-equal group-write ?-) 0)
        (t (error "Sixth char `%c' must be one of `w-'" group-write)))
        (cond
        ((char-equal group-execute-or-setid ?x)
-        (tramp-octal-to-decimal "00010"))
+        (tramp-compat-octal-to-decimal "00010"))
        ((char-equal group-execute-or-setid ?S)
-        (tramp-octal-to-decimal "02000"))
+        (tramp-compat-octal-to-decimal "02000"))
        ((char-equal group-execute-or-setid ?s)
-        (tramp-octal-to-decimal "02010"))
+        (tramp-compat-octal-to-decimal "02010"))
        ((char-equal group-execute-or-setid ?-) 0)
        (t (error "Seventh char `%c' must be one of `xsS-'"
                  group-execute-or-setid)))
        (cond
        ((char-equal other-read ?r)
-        (tramp-octal-to-decimal "00004"))
+        (tramp-compat-octal-to-decimal "00004"))
        ((char-equal other-read ?-) 0)
        (t (error "Eighth char `%c' must be one of `r-'" other-read)))
        (cond
-         ((char-equal other-write ?w) (tramp-octal-to-decimal "00002"))
+         ((char-equal other-write ?w) (tramp-compat-octal-to-decimal "00002"))
         ((char-equal other-write ?-) 0)
          (t (error "Nineth char `%c' must be one of `w-'" other-write)))
        (cond
        ((char-equal other-execute-or-sticky ?x)
-        (tramp-octal-to-decimal "00001"))
+        (tramp-compat-octal-to-decimal "00001"))
        ((char-equal other-execute-or-sticky ?T)
-        (tramp-octal-to-decimal "01000"))
+        (tramp-compat-octal-to-decimal "01000"))
        ((char-equal other-execute-or-sticky ?t)
-        (tramp-octal-to-decimal "01001"))
+        (tramp-compat-octal-to-decimal "01001"))
        ((char-equal other-execute-or-sticky ?-) 0)
        (t (error "Tenth char `%c' must be one of `xtT-'"
                  other-execute-or-sticky)))))))
@@ -7978,24 +8065,6 @@ This is used internally by `tramp-file-mode-from-int'."
                (and suid (upcase suid-text)) ; suid, !execute
                (and x "x") "-"))))     ; !suid
 
-(defun tramp-decimal-to-octal (i)
-  "Return a string consisting of the octal digits of I.
-Not actually used.  Use `(format \"%o\" i)' instead?"
-  (cond ((< i 0) (error "Cannot convert negative number to octal"))
-        ((not (integerp i)) (error "Cannot convert non-integer to octal"))
-        ((zerop i) "0")
-        (t (concat (tramp-decimal-to-octal (/ i 8))
-                   (number-to-string (% i 8))))))
-
-;; Kudos to Gerd Moellmann for this suggestion.
-(defun tramp-octal-to-decimal (ostr)
-  "Given a string of octal digits, return a decimal number."
-  (let ((x (or ostr "")))
-    ;; `save-match' is in `tramp-mode-string-to-int' which calls this.
-    (unless (string-match "\\`[0-7]*\\'" x)
-      (error "Non-octal junk in string `%s'" x))
-    (string-to-number ostr 8)))
-
 (defun tramp-shell-case-fold (string)
   "Converts STRING to shell glob pattern which ignores case."
   (mapconcat
@@ -8006,145 +8075,6 @@ Not actually used.  Use `(format \"%o\" i)' instead?"
    string
    ""))
 
-
-;; ------------------------------------------------------------
-;; -- Tramp file names --
-;; ------------------------------------------------------------
-;; Conversion functions between external representation and
-;; internal data structure.  Convenience functions for internal
-;; data structure.
-
-(defun tramp-file-name-p (vec)
-  "Check, whether VEC is a Tramp object."
-  (and (vectorp vec) (= 4 (length vec))))
-
-(defun tramp-file-name-method (vec)
-  "Return method component of VEC."
-  (and (tramp-file-name-p vec) (aref vec 0)))
-
-(defun tramp-file-name-user (vec)
-  "Return user component of VEC."
-  (and (tramp-file-name-p vec) (aref vec 1)))
-
-(defun tramp-file-name-host (vec)
-  "Return host component of VEC."
-  (and (tramp-file-name-p vec) (aref vec 2)))
-
-(defun tramp-file-name-localname (vec)
-  "Return localname component of VEC."
-  (and (tramp-file-name-p vec) (aref vec 3)))
-
-;; The user part of a Tramp file name vector can be of kind
-;; "user%domain".  Sometimes, we must extract these parts.
-(defun tramp-file-name-real-user (vec)
-  "Return the user name of VEC without domain."
-  (save-match-data
-    (let ((user (tramp-file-name-user vec)))
-      (if (and (stringp user)
-              (string-match tramp-user-with-domain-regexp user))
-         (match-string 1 user)
-       user))))
-
-(defun tramp-file-name-domain (vec)
-  "Return the domain name of VEC."
-  (save-match-data
-    (let ((user (tramp-file-name-user vec)))
-      (and (stringp user)
-          (string-match tramp-user-with-domain-regexp user)
-          (match-string 2 user)))))
-
-;; The host part of a Tramp file name vector can be of kind
-;; "host#port".  Sometimes, we must extract these parts.
-(defun tramp-file-name-real-host (vec)
-  "Return the host name of VEC without port."
-  (save-match-data
-    (let ((host (tramp-file-name-host vec)))
-      (if (and (stringp host)
-              (string-match tramp-host-with-port-regexp host))
-         (match-string 1 host)
-       host))))
-
-(defun tramp-file-name-port (vec)
-  "Return the port number of VEC."
-  (save-match-data
-    (let ((host (tramp-file-name-host vec)))
-      (and (stringp host)
-          (string-match tramp-host-with-port-regexp host)
-          (string-to-number (match-string 2 host))))))
-
-(defun tramp-tramp-file-p (name)
-  "Return t if NAME is a string with Tramp file name syntax."
-  (save-match-data
-    (and (stringp name) (string-match tramp-file-name-regexp name))))
-
-(defun tramp-find-method (method user host)
-  "Return the right method string to use.
-This is METHOD, if non-nil. Otherwise, do a lookup in
-`tramp-default-method-alist'."
-  (or method
-      (let ((choices tramp-default-method-alist)
-           lmethod item)
-       (while choices
-         (setq item (pop choices))
-         (when (and (string-match (or (nth 0 item) "") (or host ""))
-                    (string-match (or (nth 1 item) "") (or user "")))
-           (setq lmethod (nth 2 item))
-           (setq choices nil)))
-       lmethod)
-      tramp-default-method))
-
-(defun tramp-find-user (method user host)
-  "Return the right user string to use.
-This is USER, if non-nil. Otherwise, do a lookup in
-`tramp-default-user-alist'."
-  (or user
-      (let ((choices tramp-default-user-alist)
-           luser item)
-       (while choices
-         (setq item (pop choices))
-         (when (and (string-match (or (nth 0 item) "") (or method ""))
-                    (string-match (or (nth 1 item) "") (or host "")))
-           (setq luser (nth 2 item))
-           (setq choices nil)))
-       luser)
-      tramp-default-user))
-
-(defun tramp-find-host (method user host)
-  "Return the right host string to use.
-This is HOST, if non-nil. Otherwise, it is `tramp-default-host'."
-  (or (and (> (length host) 0) host)
-      tramp-default-host))
-
-(defun tramp-dissect-file-name (name &optional nodefault)
-  "Return a `tramp-file-name' structure.
-The structure consists of remote method, remote user, remote host
-and localname (file name on remote host).  If NODEFAULT is
-non-nil, the file name parts are not expanded to their default
-values."
-  (save-match-data
-    (let ((match (string-match (nth 0 tramp-file-name-structure) name)))
-      (unless match (error "Not a Tramp file name: %s" name))
-      (let ((method    (match-string (nth 1 tramp-file-name-structure) name))
-           (user      (match-string (nth 2 tramp-file-name-structure) name))
-           (host      (match-string (nth 3 tramp-file-name-structure) name))
-           (localname (match-string (nth 4 tramp-file-name-structure) name)))
-       (when (member method '("multi" "multiu"))
-         (error
-          "`%s' method is no longer supported, see (info \"(tramp)Multi-hops\")"
-          method))
-       (when host
-         (when (string-match tramp-prefix-ipv6-regexp host)
-           (setq host (replace-match "" nil t host)))
-         (when (string-match tramp-postfix-ipv6-regexp host)
-           (setq host (replace-match "" nil t host))))
-       (if nodefault
-           (vector method user host localname)
-         (vector
-          (tramp-find-method method user host)
-          (tramp-find-user   method user host)
-          (tramp-find-host   method user host)
-          localname))))))
-
 (defun tramp-equal-remote (file1 file2)
   "Check, whether the remote parts of FILE1 and FILE2 are identical.
 The check depends on method, user and host name of the files.  If
@@ -8163,37 +8093,6 @@ would yield `t'.  On the other hand, the following check results in nil:
        (stringp (file-remote-p file2))
        (string-equal (file-remote-p file1) (file-remote-p file2))))
 
-(defun tramp-make-tramp-file-name (method user host localname)
-  "Constructs a Tramp file name from METHOD, USER, HOST and LOCALNAME."
-  (concat tramp-prefix-format
-         (when (not (zerop (length method)))
-           (concat method tramp-postfix-method-format))
-         (when (not (zerop (length user)))
-           (concat user tramp-postfix-user-format))
-         (when host
-           (if (string-match tramp-ipv6-regexp host)
-               (concat tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
-             host))
-         tramp-postfix-host-format
-         (when localname localname)))
-
-(defun tramp-completion-make-tramp-file-name (method user host localname)
-  "Constructs a Tramp file name from METHOD, USER, HOST and LOCALNAME.
-It must not be a complete Tramp file name, but as long as there are
-necessary only.  This function will be used in file name completion."
-  (concat tramp-prefix-format
-         (when (not (zerop (length method)))
-           (concat method tramp-postfix-method-format))
-         (when (not (zerop (length user)))
-           (concat user tramp-postfix-user-format))
-         (when (not (zerop (length host)))
-           (concat
-            (if (string-match tramp-ipv6-regexp host)
-                (concat tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
-              host)
-            tramp-postfix-host-format))
-         (when localname localname)))
-
 (defun tramp-make-copy-program-file-name (vec)
   "Create a file name suitable to be passed to `rcp' and workalikes."
   (let ((user (tramp-file-name-user vec))
@@ -8241,6 +8140,7 @@ necessary only.  This function will be used in file name completion."
 
 ;; Variables local to connection.
 
+;;;###tramp-autoload
 (defun tramp-get-remote-path (vec)
   (with-connection-property
       ;; When `tramp-own-remote-path' is in `tramp-remote-path', we
@@ -8314,6 +8214,7 @@ necessary only.  This function will be used in file name completion."
           x))
        remote-path)))))
 
+;;;###tramp-autoload
 (defun tramp-get-remote-tmpdir (vec)
   (with-connection-property vec "tmp-directory"
     (let ((dir (tramp-shell-quote-argument "/tmp")))
@@ -8395,6 +8296,7 @@ necessary only.  This function will be used in file name completion."
     (tramp-message vec 5 "Finding command to check if file exists")
     (tramp-find-file-exists-command vec)))
 
+;;;###tramp-autoload
 (defun tramp-get-remote-ln (vec)
   (with-connection-property vec "ln"
     (tramp-message vec 5 "Finding a suitable `ln' command")
@@ -8642,8 +8544,9 @@ If the `tramp-methods' entry does not exist, return nil."
       ;; Permissions should be set always, because there might be an old
       ;; auto-saved file belonging to another original file.  This could
       ;; be a security threat.
-      (set-file-modes buffer-auto-save-file-name
-                     (or (file-modes bfn) (tramp-octal-to-decimal "0600"))))))
+      (set-file-modes
+       buffer-auto-save-file-name
+       (or (file-modes bfn) (tramp-compat-octal-to-decimal "0600"))))))
 
 (unless (and (featurep 'xemacs)
             (= emacs-major-version 21)
@@ -8747,7 +8650,6 @@ Return the difference in the format of a time value."
 (defun tramp-time-diff (t1 t2)
   "Return the difference between the two times, in seconds.
 T1 and T2 are time values (as returned by `current-time' for example)."
-  ;; Pacify byte-compiler with `symbol-function'.
   (cond ((and (fboundp 'subtract-time)
              (fboundp 'float-time))
          (tramp-compat-funcall
@@ -8823,6 +8725,7 @@ exiting if process is running."
 ;; CCC: This function should be rewritten so that
 ;; `shell-quote-argument' is not used.  This way, we are safe from
 ;; changes in `shell-quote-argument'.
+;;;###tramp-autoload
 (defun tramp-shell-quote-argument (s)
   "Similar to `shell-quote-argument', but groks newlines.
 Only works for Bourne-like shells."
@@ -8848,11 +8751,9 @@ Only works for Bourne-like shells."
 (defun tramp-unload-tramp ()
   "Discard Tramp from loading remote files."
   (interactive)
-  ;; When Tramp is not loaded yet, its autoloads are still active.
-  (tramp-unload-file-name-handlers)
   ;; ange-ftp settings must be enabled.
   (tramp-compat-funcall 'tramp-ftp-enable-ange-ftp)
-  ;; Maybe its not loaded yet.
+  ;; Maybe it's not loaded yet.
   (condition-case nil
       (unload-feature 'tramp 'force)
     (error nil)))
@@ -8882,7 +8783,6 @@ Only works for Bourne-like shells."
 ;;   likely to produce long command lines, and some shells choke on
 ;;   long command lines.
 ;; * How to deal with MULE in `insert-file-contents' and `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
@@ -8946,20 +8846,22 @@ Only works for Bourne-like shells."
 ;;   rsync).
 ;; * Keep a second connection open for out-of-band methods like scp or
 ;;   rsync.
-;; * Support ptys in `tramp-handle-start-file-process'.  (Bug#4604, Bug#6360)
 ;; * 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.
 ;; * Load ~/.emacs_SHELLNAME on the remote host for `shell'.
+;; * I was wondering it it would be possible to use tramp even if I'm
+;;   actually using sshfs.  But when I launch a command I would like
+;;   to get it executed on the remote machine where the files really
+;;   are.  (Andrea Crotti)
+;; * Run emerge on two remote files.  Bug is described here:
+;;   <http://www.mail-archive.com/tramp-devel@nongnu.org/msg01041.html>.
+;;   (Bug#6850)
 
 ;; Functions for file-name-handler-alist:
 ;; diff-latest-backup-file -- in diff.el