diff lisp/net/tramp.el @ 48973:09acf3f65bb5

* net/tramp*.el: Sync with upstream version 2.0.28. Bugfixes. * net/tramp-ftp.el: Glue code with Ange-FTP, broken out of tramp.el. From Michael Albinus. * net/tramp-smb.el: New file for using smbclient to access Windows shares with Tramp. From Michael Albinus.
author Kai Großjohann <kgrossjo@eu.uu.net>
date Thu, 26 Dec 2002 20:47:51 +0000
parents ac3dfc909b56
children 0d8b17d428b5
line wrap: on
line diff
--- a/lisp/net/tramp.el	Thu Dec 26 17:29:06 2002 +0000
+++ b/lisp/net/tramp.el	Thu Dec 26 20:47:51 2002 +0000
@@ -1,6 +1,6 @@
 ;;; tramp.el --- Transparent Remote Access, Multiple Protocol -*- coding: iso-8859-1; -*-
 
-;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 ;; Author: Kai.Grossjohann@CS.Uni-Dortmund.DE 
 ;; Keywords: comm, processes
@@ -72,7 +72,7 @@
 ;; In the Tramp CVS repository, the version numer is auto-frobbed from
 ;; the Makefile, so you should edit the top-level Makefile to change
 ;; the version number.
-(defconst tramp-version "2.0.25"
+(defconst tramp-version "2.0.28"
   "This version of tramp.")
 
 (defconst tramp-bug-report-address "tramp-devel@mail.freesoftware.fsf.org"
@@ -99,6 +99,22 @@
 ;; (when (fboundp 'efs-file-handler-function)
 ;;   (require 'efs))
 
+;; Load foreign methods.  Because they do require Tramp internally, this
+;; must be done with the `eval-after-load' trick.
+
+;; tramp-ftp supports Ange-FTP only.  Not suited for XEmacs therefore.
+(unless (featurep 'xemacs)
+  (eval-after-load "tramp"
+    '(require '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/path".
+(unless (memq system-type '(cygwin windows-nt))
+  (eval-after-load "tramp"
+    '(require 'tramp-smb)))
+
 (eval-when-compile
   (require 'cl)
   (require 'custom)
@@ -618,20 +634,12 @@
 (defcustom tramp-default-method "ssh"
   "*Default method to use for transferring files.
 See `tramp-methods' for possibilities.
-Also see `tramp-default-method-alist'.
-
-Emacs uses a unified filename syntax for Tramp and Ange-FTP.
-For backward compatibility, the default value of this variable
-is \"ftp\" on Emacs.  But XEmacs uses a separate filename syntax
-for Tramp and EFS, so there the default method is \"sm\"."
+Also see `tramp-default-method-alist'."
   :group 'tramp
   :type 'string)
 
 (defcustom tramp-default-method-alist
-  (when tramp-unified-filenames
-    '(("\\`ftp\\." "" "ftp")
-      ("" "\\`\\(anonymous\\|ftp\\)\\'" "ftp")
-      ("\\`localhost\\'" "\\`root\\'" "su")))
+  '(("\\`localhost\\'" "\\`root\\'" "su"))
   "*Default method to use for specific user/host pairs.
 This is an alist of items (HOST USER METHOD).  The first matching item
 specifies the method to use for a file name which does not specify a
@@ -648,11 +656,6 @@
 		       (regexp :tag "User regexp")
 		       (string :tag "Method"))))
 
-(defcustom tramp-ftp-method "ftp"
-  "*When this method name is used, forward all calls to Ange-FTP."
-  :group 'tramp
-  :type 'string)
-
 ;; Default values for non-Unices seeked
 (defconst tramp-completion-function-alist-rsh
   (unless (memq system-type '(windows-nt))
@@ -687,13 +690,6 @@
   "Default list of (FUNCTION FILE) pairs to be examined for su methods."
 )
 
-;; Default values for non-Unices seeked
-(defconst tramp-completion-function-alist-ftp
-  (unless (memq system-type '(windows-nt))
-    '((tramp-parse-netrc "~/.netrc")))
-  "Default list of (FUNCTION FILE) pairs to be examined for ftp methods."
-)
-
 (defcustom tramp-completion-function-alist
   (list (cons "rcp"      tramp-completion-function-alist-rsh)
 	(cons "scp"      tramp-completion-function-alist-ssh)
@@ -718,7 +714,6 @@
  	(cons "plink"    tramp-completion-function-alist-ssh)
  	(cons "pscp"     tramp-completion-function-alist-ssh)
  	(cons "fcp"      tramp-completion-function-alist-ssh)
- 	(cons "ftp"      tramp-completion-function-alist-ftp)
      )
   "*Alist of methods for remote files.
 This is a list of entries of the form (NAME PAIR1 PAIR2 ...).
@@ -730,7 +725,7 @@
  * `tramp-parse-shosts' for \"ssh_known_hosts\" like files,
  * `tramp-parse-hosts'  for \"/etc/hosts\" like files, and
  * `tramp-parse-passwd' for \"/etc/passwd\" like files.
- * `tramp-parse-netrc ' for \".netrc\" like files.
+ * `tramp-parse-netrc'  for \".netrc\" like files.
 
 FUNCTION can also see a customer defined function.  For more details see
 the info pages."
@@ -870,7 +865,7 @@
   :group 'tramp
   :type 'boolean)
 
-(defcustom tramp-sh-extra-args '(("/bash\\'" . "--norc"))
+(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
 matching the shell file name and ARGS is a string specifying the
@@ -1254,7 +1249,30 @@
 the visited file modtime.")
 (make-variable-buffer-local 'tramp-buffer-file-attributes)
 
-(defvar tramp-end-of-output "/////"
+(defvar tramp-md5-function
+  (cond ((fboundp 'md5) 'md5)
+	((and (require 'md5) (fboundp 'md5-encode)) 'md5-encode)
+	(t (error "Coulnd't find an `md5' function")))
+  "Function to call for running the MD5 algorithm.")
+
+(defvar tramp-end-of-output
+  (concat "///"
+	  (funcall tramp-md5-function
+		   (concat
+		    (prin1-to-string process-environment)
+		    (current-time-string)
+;; 		    (prin1-to-string
+;; 		     (if (fboundp 'directory-files-and-attributes)
+;; 			 (funcall 'directory-files-and-attributes
+;; 				  (or (getenv "HOME")
+;; 				      (tramp-temporary-file-directory)))
+;; 		       (mapcar
+;; 			(lambda (x)
+;; 			  (cons x (file-attributes x)))
+;; 			(directory-files (or (getenv "HOME")
+;; 					     (tramp-temporary-file-directory))
+;; 					 t))))
+		    )))
   "String used to recognize end of output.")
 
 (defvar tramp-connection-function nil
@@ -1622,6 +1640,12 @@
 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.
+(defvar tramp-foreign-file-name-handler-alist nil
+  "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
+calling HANDLER.")
+
 ;;; Internal functions which must come first.
 
 (defsubst tramp-message (level fmt-string &rest args)
@@ -1711,7 +1735,9 @@
        (tramp-parse-shosts \"~/.ssh/known_hosts\")))"
 
   (let ((v (cdr (assoc method tramp-completion-function-alist))))
-    (when v (setcdr v function-list))))
+    (if v (setcdr v function-list)
+      (add-to-list 'tramp-completion-function-alist
+		   (cons method function-list)))))
 
 (defun tramp-get-completion-function (method)
   "Returns list of completion functions for METHOD.
@@ -1732,9 +1758,6 @@
 this can give surprising results if the user/host for the source and
 target of the symlink differ."
   (with-parsed-tramp-file-name linkname l
-    (when (tramp-ange-ftp-file-name-p l-multi-method l-method l-user l-host)
-      (tramp-invoke-ange-ftp 'make-symbolic-link
-			     filename linkname ok-if-already-exists))
     (let ((ln (tramp-get-remote-ln l-multi-method l-method l-user l-host))
 	  (cwd (file-name-directory l-path)))
       (unless ln
@@ -1778,9 +1801,6 @@
   (unless (file-name-absolute-p file)
     (error "Tramp cannot `load' files without absolute path name"))
   (with-parsed-tramp-file-name file nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'load
-			     file noerror nomessage nosuffix must-suffix))
     (unless nosuffix
       (cond ((file-exists-p (concat file ".elc"))
 	     (setq file (concat file ".elc")))
@@ -1813,8 +1833,6 @@
   "Like `file-name-directory' but aware of TRAMP files."
   ;; everything except the last filename thing is the directory
   (with-parsed-tramp-file-name file nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-name-directory file))
     ;; For the following condition, two possibilities should be tried:
     ;; (1) (string= path "")
     ;; (2) (or (string= path "") (string= path "/"))
@@ -1839,18 +1857,11 @@
 (defun tramp-handle-file-name-nondirectory (file)
   "Like `file-name-nondirectory' but aware of TRAMP files."
   (with-parsed-tramp-file-name file nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-name-nondirectory file))
     (file-name-nondirectory path)))
 
 (defun tramp-handle-file-truename (filename &optional counter prev-dirs)
   "Like `file-truename' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    ;; Ange-FTP does not support truename processing, but for
-    ;; convenience we pretend it did and forward the call to Ange-FTP
-    ;; anyway.  Ange-FTP then just invokes `identity'.
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-truename filename))
     (let* ((steps        (tramp-split-string path "/"))
 	   (pathdir (let ((directory-sep-char ?/))
 		      (file-name-as-directory path)))
@@ -1926,8 +1937,6 @@
 (defun tramp-handle-file-exists-p (filename)
   "Like `file-exists-p' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-exists-p filename))
     (save-excursion
       (zerop (tramp-send-command-and-check
 	      multi-method method user host
@@ -1944,8 +1953,6 @@
 rather than as numbers."
   (let (result)
     (with-parsed-tramp-file-name filename nil
-      (when (tramp-ange-ftp-file-name-p multi-method method user host)
-	(tramp-invoke-ange-ftp 'file-attributes filename))
       (when (tramp-handle-file-exists-p filename)
 	;; file exists, find out stuff
 	(save-excursion
@@ -2074,15 +2081,6 @@
   (let ((f (buffer-file-name))
 	(coding-system-used nil))
     (with-parsed-tramp-file-name f nil
-      ;; This operation is not handled by Ange-FTP!  Compare this
-      ;; behavior with `file-truename' which Ange-FTP does not really
-      ;; handle, either, but at least it pretends to.  I wonder if
-      ;; Ange-FTP should also pretend to grok
-      ;; `set-visited-file-modtime', for consistency?
-      (when (tramp-ange-ftp-file-name-p multi-method method user host)
-	(throw 'tramp-forward-to-ange-ftp
-	       (tramp-run-real-handler 'set-visited-file-modtime
-				       (list time-list))))
       (let* ((attr (file-attributes f))
 	     (modtime (nth 5 attr)))
 	;; We use '(0 0) as a don't-know value.  See also
@@ -2114,12 +2112,6 @@
   (with-current-buffer buf
     (let ((f (buffer-file-name)))
       (with-parsed-tramp-file-name f nil
-	(when (tramp-ange-ftp-file-name-p multi-method method user host)
-	  ;; This one requires a hack since the file name is not passed
-	  ;; on the arg list.
-	  (let ((buffer-file-name (tramp-make-ange-ftp-file-name
-				   user host path)))
-	    (tramp-invoke-ange-ftp 'verify-visited-file-modtime buf)))
 	(let* ((attr (file-attributes f))
 	       (modtime (nth 5 attr)))
 	  (cond ((and attr (not (equal modtime '(0 0))))
@@ -2153,8 +2145,6 @@
 (defun tramp-handle-set-file-modes (filename mode)
   "Like `set-file-modes' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'set-file-modes mode filename))
     (save-excursion
       (unless (zerop (tramp-send-command-and-check
 		      multi-method method user host
@@ -2172,22 +2162,16 @@
 (defun tramp-handle-file-executable-p (filename)
   "Like `file-executable-p' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-executable-p filename))
     (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
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-readable-p filename))
     (zerop (tramp-run-test "-r" filename))))
 
 (defun tramp-handle-file-accessible-directory-p (filename)
   "Like `file-accessible-directory-p' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-accessible-directory-p filename))
     (and (zerop (tramp-run-test "-d" filename))
 	 (zerop (tramp-run-test "-r" filename))
 	 (zerop (tramp-run-test "-x" filename)))))
@@ -2213,7 +2197,7 @@
 		 (fa2 (file-attributes file2)))
 	     (if (and (not (equal (nth 5 fa1) '(0 0)))
 		      (not (equal (nth 5 fa2) '(0 0))))
-		 (> 0 (car (subtract-time (nth 5 fa1) (nth 5 fa2))))
+		 (> 0 (car (tramp-time-diff (nth 5 fa1) (nth 5 fa2))))
 	       ;; If one of them is the dont-know value, then we can
 	       ;; still try to run a shell command on the remote host.
 	       ;; However, this only works if both files are Tramp
@@ -2228,12 +2212,6 @@
 		   file1 file2)))
 	       (with-parsed-tramp-file-name file1 v1
 		 (with-parsed-tramp-file-name file2 v2
-		   (when (and (tramp-ange-ftp-file-name-p
-			       v1-multi-method v1-method v1-user v1-host)
-			      (tramp-ange-ftp-file-name-p
-			       v2-multi-method v2-method v2-user v2-host))
-		     (tramp-invoke-ange-ftp 'file-newer-than-file-p
-					    file1 file2))
 		   (unless (and (equal v1-multi-method v2-multi-method)
 				(equal v1-method v2-method)
 				(equal v1-user v2-user)
@@ -2257,11 +2235,9 @@
 (defun tramp-handle-file-modes (filename)
   "Like `file-modes' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-modes filename))
     (when (file-exists-p filename)
       (tramp-mode-string-to-int
-       (nth 8 (tramp-handle-file-attributes filename))))))
+       (nth 8 (file-attributes filename))))))
 
 (defun tramp-handle-file-directory-p (filename)
   "Like `file-directory-p' for tramp files."
@@ -2274,8 +2250,6 @@
   ;;
   ;; Alternatives: `cd %s', `test -d %s'
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-directory-p filename))
     (save-excursion
       (zerop
        (tramp-send-command-and-check
@@ -2287,24 +2261,18 @@
 (defun tramp-handle-file-regular-p (filename)
   "Like `file-regular-p' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-regular-p filename))
     (and (tramp-handle-file-exists-p filename)
 	 (eq ?- (aref (nth 8 (tramp-handle-file-attributes filename)) 0)))))
 
 (defun tramp-handle-file-symlink-p (filename)
   "Like `file-symlink-p' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-symlink-p filename))
     (let ((x (car (tramp-handle-file-attributes filename))))
       (when (stringp x) x))))
 
 (defun tramp-handle-file-writable-p (filename)
   "Like `file-writable-p' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-writable-p filename))
     (if (tramp-handle-file-exists-p filename)
 	;; Existing files must be writable.
 	(zerop (tramp-run-test "-w" filename))
@@ -2317,8 +2285,6 @@
 (defun tramp-handle-file-ownership-preserved-p (filename)
   "Like `file-ownership-preserved-p' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-ownership-preserved-p filename))
     (or (not (tramp-handle-file-exists-p filename))
 	;; Existing files must be writable.
 	(zerop (tramp-run-test "-O" filename)))))
@@ -2337,8 +2303,6 @@
 (defun tramp-handle-directory-file-name (directory)
   "Like `directory-file-name' for tramp files."
   (with-parsed-tramp-file-name directory nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'directory-file-name directory))
     (let ((directory-length-1 (1- (length directory))))
       (save-match-data
 	(if (and (eq (aref directory directory-length-1) ?/)
@@ -2353,9 +2317,6 @@
 				     &optional full match nosort files-only)
   "Like `directory-files' for tramp files."
   (with-parsed-tramp-file-name directory nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'directory-files
-			     directory full match nosort files-only))
     (let (result x)
       (save-excursion
 	(tramp-barf-unless-okay
@@ -2410,9 +2371,6 @@
 (defun tramp-handle-file-name-all-completions (filename directory)
   "Like `file-name-all-completions' for tramp files."
   (with-parsed-tramp-file-name directory nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-name-all-completions
-			     filename directory))
     (unless (save-match-data (string-match "/" filename))
       (let* ((nowild tramp-completion-without-shell-p)
 	     result)
@@ -2463,13 +2421,10 @@
      "tramp-handle-file-name-completion invoked on non-tramp directory `%s'"
      directory))
   (with-parsed-tramp-file-name directory nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-name-completion
-			     filename directory))
     (try-completion
      filename
      (mapcar (lambda (x) (cons x nil))
-	     (tramp-handle-file-name-all-completions filename directory)))))
+	     (file-name-all-completions filename directory)))))
 
 ;; cp, mv and ln
 
@@ -2487,16 +2442,6 @@
 		     (equal v1-host v2-host))
 	  (error "add-name-to-file: %s"
 		 "only implemented for same method, same user, same host"))
-	(when (and (tramp-ange-ftp-file-name-p v1-multi-method v1-method v1-user v1-host)
-		   (tramp-ange-ftp-file-name-p v2-multi-method v2-method v2-user v2-host))
-	  (tramp-invoke-ange-ftp 'add-name-to-file
-				 filename newname ok-if-already-exists))
-	(when (tramp-ange-ftp-file-name-p v1-multi-method v1-method v1-user v1-host)
-	  (tramp-invoke-ange-ftp 'add-name-to-file
-				 filename newname ok-if-already-exists))
-	(when (tramp-ange-ftp-file-name-p v2-multi-method v2-method v2-user v2-host)
-	  (tramp-invoke-ange-ftp 'add-name-to-file
-				 filename newname ok-if-already-exists))
 	(when (and (not ok-if-already-exists)
 		   (file-exists-p newname)
 		   (not (numberp ok-if-already-exists))
@@ -2571,14 +2516,6 @@
       ;; Both are Tramp files.
       (with-parsed-tramp-file-name filename v1
 	(with-parsed-tramp-file-name newname v2
-	  ;; Possibly invoke Ange-FTP.
-	  (when (and (tramp-ange-ftp-file-name-p v1-multi-method v1-method v1-user v1-host)
-		     (tramp-ange-ftp-file-name-p v2-multi-method v2-method v2-user v2-host))
-	    (if (eq op 'copy)
-		(tramp-invoke-ange-ftp
-		 'copy-file filename newname ok-if-already-exists keep-date)
-	      (tramp-invoke-ange-ftp
-	       'rename-file filename newname ok-if-already-exists)))
 	  ;; Check if we can use a shortcut.
 	  (if (and (equal v1-multi-method v2-multi-method)
 		   (equal v1-method v2-method)
@@ -2663,8 +2600,6 @@
   "Like `make-directory' for tramp files."
   (setq dir (expand-file-name dir))
   (with-parsed-tramp-file-name dir nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'make-directory dir parents))
     (save-excursion
       (tramp-barf-unless-okay
        multi-method method user host
@@ -2679,8 +2614,6 @@
   "Like `delete-directory' for tramp files."
   (setq directory (expand-file-name directory))
   (with-parsed-tramp-file-name directory nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'delete-directory directory))
     (save-excursion
       (tramp-send-command
        multi-method method user host
@@ -2692,8 +2625,6 @@
   "Like `delete-file' for tramp files."
   (setq filename (expand-file-name filename))
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'delete-file filename))
     (save-excursion
       (unless (zerop (tramp-send-command-and-check
 		      multi-method method user host
@@ -2709,9 +2640,6 @@
   "Recursively delete the directory given.
 This is like `dired-recursive-delete-directory' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'dired-recursive-delete-directory
-			     filename))
     ;; run a shell command 'rm -r <path>'
     ;; Code shamelessly stolen for the dired implementation and, um, hacked :)
     (or (tramp-handle-file-exists-p filename)
@@ -2732,11 +2660,6 @@
 (defun tramp-handle-dired-call-process (program discard &rest arguments)
   "Like `dired-call-process' for tramp files."
   (with-parsed-tramp-file-name default-directory nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (let ((default-directory
-	      (tramp-make-ange-ftp-file-name user host path)))
-	(tramp-invoke-ange-ftp 'dired-call-process
-			       program discard arguments)))
     (save-excursion
       (tramp-barf-unless-okay
        multi-method method user host
@@ -2779,9 +2702,6 @@
     (setq switches (replace-match "" nil t switches)))
   (setq filename (expand-file-name filename))
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'insert-directory
-			     filename switches wildcard full-directory-p))
     (tramp-message-for-buffer
      multi-method method user host 10
      "Inserting directory `ls %s %s', wildcard %s, fulldir %s"
@@ -2857,9 +2777,6 @@
 (defun tramp-handle-unhandled-file-name-directory (filename)
   "Like `unhandled-file-name-directory' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'unhandled-file-name-directory
-			     filename))
     (expand-file-name "~/")))
 
 ;; Canonicalization of file names.
@@ -2893,8 +2810,6 @@
                               (list name nil))
     ;; Dissect NAME.
     (with-parsed-tramp-file-name name nil
-      (when (tramp-ange-ftp-file-name-p multi-method method user host)
-	(tramp-invoke-ange-ftp 'expand-file-name name nil))
       (unless (file-name-absolute-p path)
 	(setq path (concat "~/" path)))
       (save-excursion
@@ -2935,11 +2850,6 @@
 `tramp-end-of-output', followed by another newline."
   (if (tramp-tramp-file-p default-directory)
       (with-parsed-tramp-file-name default-directory nil
-	(when (tramp-ange-ftp-file-name-p multi-method method user host)
-	  (let ((default-directory (tramp-make-ange-ftp-file-name
-				    user host path)))
-	    (tramp-invoke-ange-ftp 'shell-command
-				   command output-buffer error-buffer)))
 	(let (status)
 	  (when (string-match "&[ \t]*\\'" command)
 	    (error "Tramp doesn't grok asynchronous shell commands, yet"))
@@ -2979,7 +2889,7 @@
 	    (skip-chars-forward "^ ")
 	    (setq status (read (current-buffer))))
 	  (unless (zerop (buffer-size))
-	    (pop-to-buffer output-buffer))
+	    (display-buffer output-buffer))
 	  status))
     ;; The following is only executed if something strange was
     ;; happening.  Emit a helpful message and do it anyway.
@@ -2998,8 +2908,6 @@
 (defun tramp-handle-file-local-copy (filename)
   "Like `file-local-copy' for tramp files."
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'file-local-copy filename))
     (let ((output-buf (get-buffer-create "*tramp output*"))
 	  (tramp-buf (tramp-get-buffer multi-method method user host))
 	  (rcp-program (tramp-get-rcp-program
@@ -3114,10 +3022,7 @@
   (barf-if-buffer-read-only)
   (setq filename (expand-file-name filename))
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'insert-file-contents
-			     filename visit beg end replace))
-    (if (not (tramp-handle-file-exists-p filename))
+    (if (not (file-exists-p filename))
 	(progn
 	  (when visit
 	    (setq buffer-file-name filename)
@@ -3125,8 +3030,8 @@
 	    (set-buffer-modified-p nil))
 	  (signal 'file-error
 		  (format "File `%s' not found on remote host" filename))
-	  (list (tramp-handle-expand-file-name filename) 0))
-      (let ((local-copy (tramp-handle-file-local-copy filename))
+	  (list (expand-file-name filename) 0))
+      (let ((local-copy (file-local-copy filename))
 	    (coding-system-used nil)
 	    (result nil))
 	(when visit
@@ -3136,9 +3041,7 @@
 	(tramp-message-for-buffer
 	 multi-method method user host
 	 9 "Inserting local temp file `%s'..." local-copy)
-	(setq result
-	      (tramp-run-real-handler 'insert-file-contents
-				      (list local-copy nil beg end replace)))
+	(setq result (insert-file-contents local-copy nil beg end replace))
 	;; Now `last-coding-system-used' has right value.  Remember it.
 	(when (boundp 'last-coding-system-used)
 	  (setq coding-system-used last-coding-system-used))
@@ -3174,9 +3077,6 @@
                               filename))
       (error "File not overwritten")))
   (with-parsed-tramp-file-name filename nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'write-region
-			     start end filename append visit))
     (let ((curbuf (current-buffer))
 	  (rcp-program (tramp-get-rcp-program
 			multi-method (tramp-find-method multi-method method user host)
@@ -3380,15 +3280,15 @@
   "Invoke normal file name handler for OPERATION.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
-  (let* ((op (if (eq operation 'ange-ftp-hook-function)
-		 (car args)
-	       operation))
-	 (inhibit-file-name-handlers
-	  (list 'tramp-file-name-handler
-		'tramp-completion-file-name-handler
-		(and (eq inhibit-file-name-operation op)
-		     inhibit-file-name-handlers)))
-	 (inhibit-file-name-operation op))
+  (let* ((inhibit-file-name-handlers
+	  `(tramp-file-name-handler
+	    tramp-completion-file-name-handler
+	    cygwin-mount-name-hook-function
+	    cygwin-mount-map-drive-hook-function
+	    .
+	    ,(and (eq inhibit-file-name-operation operation)
+		  inhibit-file-name-handlers)))
+	 (inhibit-file-name-operation operation))
     (apply operation args)))
 
 ;; This function is used from `tramp-completion-file-name-handler' functions
@@ -3399,26 +3299,106 @@
   "Invoke `tramp-file-name-handler' for OPERATION.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
-  (let* ((op (if (eq operation 'ange-ftp-hook-function)
-		 (car args)
-	       operation))
-	 (inhibit-file-name-handlers
-	  (list 'tramp-completion-file-name-handler
-		(and (eq inhibit-file-name-operation op)
-		     inhibit-file-name-handlers)))
-	 (inhibit-file-name-operation op))
+  (let* ((inhibit-file-name-handlers
+	  `(tramp-completion-file-name-handler
+	    cygwin-mount-name-hook-function
+	    cygwin-mount-map-drive-hook-function
+	    .
+	    ,(and (eq inhibit-file-name-operation operation)
+		  inhibit-file-name-handlers)))
+	 (inhibit-file-name-operation operation))
     (apply operation args)))
 
+;; We handle here all file primitives.  Most of them have the file
+;; name as first parameter; nevertheless we check for them explicitly
+;; in order to be be signalled if a new primitive appears.  This
+;; scenario is needed because there isn't a way to decide by
+;; syntactical means whether a foreign method must be called.  It would
+;; ease the live if `file-name-handler-alist' would support a decision
+;; function as well but regexp only.
+(defun tramp-file-name-for-operation (operation &rest args)
+  "Return file name related to OPERATION file primitive.
+ARGS are the arguments OPERATION has been called with."
+  (cond
+   ; FILE resp DIRECTORY
+   ((member operation
+	    (list 'access-file 'byte-compiler-base-file-name 'delete-directory
+		  'delete-file 'diff-latest-backup-file 'directory-file-name
+		  'directory-files 'directory-files-and-attributes
+		  'dired-compress-file 'dired-uncache
+		  'file-accessible-directory-p 'file-attributes
+		  'file-directory-p 'file-executable-p 'file-exists-p
+		  'file-local-copy 'file-modes 'file-name-as-directory
+		  'file-name-directory 'file-name-nondirectory
+		  'file-name-sans-versions 'file-ownership-preserved-p
+		  'file-readable-p 'file-regular-p 'file-symlink-p
+		  'file-truename 'file-writable-p 'find-backup-file-name
+		  'find-file-noselect 'get-file-buffer 'insert-directory
+		  'insert-file-contents 'load 'make-directory
+		  'make-directory-internal 'set-file-modes
+		  'substitute-in-file-name 'unhandled-file-name-directory
+		  'vc-registered
+		  ; XEmacs only
+		  'abbreviate-file-name 'create-file-buffer
+		  'dired-file-modtime 'dired-make-compressed-filename
+		  'dired-recursive-delete-directory 'dired-set-file-modtime
+		  'dired-shell-unhandle-file-name 'dired-uucode-file
+		  'insert-file-contents-literally 'recover-file
+		  'vm-imap-check-mail 'vm-pop-check-mail 'vm-spool-check-mail))
+    (expand-file-name (nth 0 args)))
+   ; FILE DIRECTORY resp FILE1 FILE2
+   ((member operation
+	    (list 'add-name-to-file 'copy-file 'expand-file-name
+		  'file-name-all-completions 'file-name-completion
+		  'file-newer-than-file-p 'make-symbolic-link 'rename-file
+		  ; XEmacs only
+		  'dired-make-relative-symlink
+		  'vm-imap-move-mail 'vm-pop-move-mail 'vm-spool-move-mail))
+    (save-match-data
+      (cond
+       ((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
+   ((eq operation 'write-region)
+    (nth 2 args))
+   ; BUF
+   ((member operation
+	    (list 'set-visited-file-modtime 'verify-visited-file-modtime
+	          ; XEmacs only
+		  'backup-buffer))
+    (buffer-file-name
+     (if (bufferp (nth 0 args)) (nth 0 args) (current-buffer))))
+   ; COMMAND
+   ((member operation
+	    (list 'dired-call-process 'shell-command
+	          ; XEmacs only
+		  'dired-print-file 'dired-shell-call-process))
+    default-directory)
+   ; 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."
+  (let (elt res)
+    (dolist (elt tramp-foreign-file-name-handler-alist res)
+      (when (funcall (car elt) filename)
+	(setq res (cdr elt))))
+    res))
+
 ;; Main function.
 ;;;###autoload
 (defun tramp-file-name-handler (operation &rest args)
   "Invoke tramp file name handler.
 Falls back to normal file name handler if no tramp file name handler exists."
-  (let ((fn (assoc operation tramp-file-name-handler-alist)))
-    (if fn
-	(catch 'tramp-forward-to-ange-ftp
-	  (save-match-data (apply (cdr fn) args)))
-      (tramp-run-real-handler operation args))))
+  (save-match-data
+    (let* ((fn (assoc operation tramp-file-name-handler-alist))
+	   (filename (apply 'tramp-file-name-for-operation operation args))
+	   (foreign (tramp-find-foreign-file-name-handler filename)))
+      (cond
+       (foreign (apply foreign operation args))
+       (fn (apply (cdr fn) args))
+       (t (tramp-run-real-handler operation args))))))
 
 (put 'tramp-file-name-handler 'file-remote-p t)	;for file-remote-p
 
@@ -3432,8 +3412,7 @@
 ;; 		 operation args (with-output-to-string (backtrace)))
   (let ((fn (assoc operation tramp-completion-file-name-handler-alist)))
     (if fn
-	(catch 'tramp-forward-to-ange-ftp
-	  (save-match-data (apply (cdr fn) args)))
+	(save-match-data (apply (cdr fn) args))
       (tramp-completion-run-real-handler operation args))))
 
 ;; Register in file name handler alist
@@ -3444,32 +3423,6 @@
 	     (cons tramp-completion-file-name-regexp
 		   'tramp-completion-file-name-handler))
 
-;; To handle EFS, the following functions need to be dealt with:
-;;
-;; * dired-before-readin-hook contains efs-dired-before-readin
-;; * file-name-handler-alist contains efs-file-handler-function
-;;   and efs-root-handler-function and efs-sifn-handler-function
-;; * find-file-hooks contains efs-set-buffer-mode
-;;
-;; But it won't happen for EFS since the XEmacs maintainers
-;; don't want to use a unified filename syntax.
-(defun tramp-disable-ange-ftp ()
-  "Turn Ange-FTP off.
-This is useful for unified remoting.  See
-`tramp-file-name-structure-unified' and
-`tramp-file-name-structure-separate' for details.  Requests suitable
-for Ange-FTP will be forwarded to Ange-FTP.  Also see the variables
-`tramp-ftp-method', `tramp-default-method', and
-`tramp-default-method-alist'.
-
-This function is not needed in Emacsen which include Tramp, but is
-present for backward compatibility."
-  (let ((a1 (rassq 'ange-ftp-hook-function file-name-handler-alist))
-	(a2 (rassq 'ange-ftp-completion-hook-function file-name-handler-alist)))
-    (setq file-name-handler-alist
-	  (delete a1 (delete a2 file-name-handler-alist)))))
-(tramp-disable-ange-ftp)
-
 (defun tramp-repair-jka-compr ()
   "If jka-compr is already loaded, move it to the front of
 `file-name-handler-alist'.  On Emacs 21.4 or so this will not be
@@ -3480,40 +3433,6 @@
 	    (cons jka (delete jka file-name-handler-alist))))))
 (tramp-repair-jka-compr)
 
-(defun tramp-flatten-list (arg)
-  "Expands all lists inside ARG to a sequential list.
-Return (nil) if arg is nil."
-  (let ((car (car arg))
-	(cdr (cdr arg)))
-    (cond
-     ((eq arg nil) '(nil))
-     ((listp car)
-      (if (null cdr)
-	  (tramp-flatten-list car)
-	(append (tramp-flatten-list car) (tramp-flatten-list cdr))))
-     ((null cdr) (list car))
-     (t (cons car (tramp-flatten-list cdr))))))
-
-(defun tramp-invoke-ange-ftp (operation &rest args)
-  "Invoke the Ange-FTP handler function and throw."
-  (or (boundp 'ange-ftp-name-format)
-      (and (require 'ange-ftp)
-	   (tramp-disable-ange-ftp)))
-  (let ((ange-ftp-name-format
-	 (list (nth 0 tramp-file-name-structure)
-	       (nth 3 tramp-file-name-structure)
-	       (nth 2 tramp-file-name-structure)
-	       (nth 4 tramp-file-name-structure))))
-    (throw 'tramp-forward-to-ange-ftp
-	   (tramp-run-real-handler 'ange-ftp-hook-function
-				   (cons operation args)))))
-
-(defun tramp-ange-ftp-file-name-p (multi-method method user host)
-  "Check if it's a filename that should be forwarded to Ange-FTP."
-  (and tramp-unified-filenames
-       (null multi-method)
-       (string= (tramp-find-method multi-method method user host) tramp-ftp-method)))
-
 
 ;;; Interactions with other packages:
 
@@ -3523,8 +3442,6 @@
 (defun tramp-handle-expand-many-files (name)
   "Like `PC-expand-many-files' for tramp files."
   (with-parsed-tramp-file-name name nil
-    (when (tramp-ange-ftp-file-name-p multi-method method user host)
-      (tramp-invoke-ange-ftp 'expand-many-files name))
     (save-match-data
       (if (or (string-match "\\*" name)
 	      (string-match "\\?" name)
@@ -3604,8 +3521,7 @@
      (concat tramp-prefix-regexp
       "\\(" tramp-method-regexp  "\\)" tramp-postfix-single-method-regexp "$")
      file)
-    (member (match-string 1 file)
-	    (cons tramp-ftp-method (mapcar 'car tramp-methods))))
+    (member (match-string 1 file) (mapcar 'car tramp-methods)))
    ((or (equal last-input-event 'tab)
 	(and (not (event-modifiers last-input-event))
 	     (integerp last-input-event)
@@ -3672,17 +3588,17 @@
 	    ;; Method dependent user / host combinations
 	    (progn
 	      (mapcar
-	       '(lambda (x)
-		  (setq all-user-hosts
-			(append all-user-hosts
-				(funcall (nth 0 x) (nth 1 x)))))
+	       (lambda (x)
+		 (setq all-user-hosts
+		       (append all-user-hosts
+			       (funcall (nth 0 x) (nth 1 x)))))
 	       (tramp-get-completion-function m))
 
 	      (setq result (append result 
 	        (mapcar
-		 '(lambda (x)
-		    (tramp-get-completion-user-host
-		     method user host (nth 0 x) (nth 1 x)))
+		 (lambda (x)
+		   (tramp-get-completion-user-host
+		    method user host (nth 0 x) (nth 1 x)))
 		 (delq nil all-user-hosts)))))
 
 	    ;; Possible methods
@@ -3734,47 +3650,46 @@
 They are collected by `tramp-completion-dissect-file-name1'."
 
   (let* ((result)
-	 (x-nil "\\|\\(\\)"))
-
-    ;; "/method" "/[method"
-    (defconst tramp-completion-file-name-structure1
-      (list (concat tramp-prefix-regexp "\\(" tramp-method-regexp x-nil "\\)$")
-	    1 9 9 9))
-    ;; "/user" "/[user"
-    (defconst tramp-completion-file-name-structure2
-      (list (concat tramp-prefix-regexp "\\(" tramp-user-regexp x-nil   "\\)$")
-	    9 1 9 9))
-    ;; "/host" "/[host"
-    (defconst tramp-completion-file-name-structure3
-      (list (concat tramp-prefix-regexp "\\(" tramp-host-regexp x-nil   "\\)$")
-	    9 9 1 9))
-    ;; "/user@host" "/[user@host"
-    (defconst tramp-completion-file-name-structure4
-      (list (concat tramp-prefix-regexp
-		    "\\(" tramp-user-regexp "\\)"   tramp-postfix-user-regexp
-		    "\\(" tramp-host-regexp x-nil   "\\)$")
-	    9 1 2 9))
-    ;; "/method:user" "/[method/user"
-    (defconst tramp-completion-file-name-structure5
-      (list (concat tramp-prefix-regexp
-		    "\\(" tramp-method-regexp "\\)" tramp-postfix-single-method-regexp
-		    "\\(" tramp-user-regexp x-nil   "\\)$")
-	    1 2 9 9))
-    ;; "/method:host" "/[method/host"
-    (defconst tramp-completion-file-name-structure6
-      (list (concat tramp-prefix-regexp
-		    "\\(" tramp-method-regexp "\\)" tramp-postfix-single-method-regexp
-		    "\\(" tramp-host-regexp x-nil   "\\)$")
-	    1 9 2 9))
-    ;; "/method:user@host" "/[method/user@host"
-    (defconst tramp-completion-file-name-structure7
-      (list (concat tramp-prefix-regexp
-		    "\\(" tramp-method-regexp "\\)" tramp-postfix-single-method-regexp
-		    "\\(" tramp-user-regexp "\\)"   tramp-postfix-user-regexp
-		    "\\(" tramp-host-regexp x-nil   "\\)$")
-	    1 2 3 9))
-  
-    (mapcar '(lambda (regexp)
+	 (x-nil "\\|\\(\\)")
+	 ;; "/method" "/[method"
+	 (tramp-completion-file-name-structure1
+	  (list (concat tramp-prefix-regexp "\\(" tramp-method-regexp x-nil "\\)$")
+		1 nil nil nil))
+	 ;; "/user" "/[user"
+	 (tramp-completion-file-name-structure2
+	  (list (concat tramp-prefix-regexp "\\(" tramp-user-regexp x-nil   "\\)$")
+		nil 1 nil nil))
+	 ;; "/host" "/[host"
+	 (tramp-completion-file-name-structure3
+	  (list (concat tramp-prefix-regexp "\\(" tramp-host-regexp x-nil   "\\)$")
+		nil nil 1 nil))
+	 ;; "/user@host" "/[user@host"
+	 (tramp-completion-file-name-structure4
+	  (list (concat tramp-prefix-regexp
+			"\\(" tramp-user-regexp "\\)"   tramp-postfix-user-regexp
+			"\\(" tramp-host-regexp x-nil   "\\)$")
+		nil 1 2 nil))
+	 ;; "/method:user" "/[method/user"
+	 (tramp-completion-file-name-structure5
+	  (list (concat tramp-prefix-regexp
+			"\\(" tramp-method-regexp "\\)" tramp-postfix-single-method-regexp
+			"\\(" tramp-user-regexp x-nil   "\\)$")
+		1 2 nil nil))
+	 ;; "/method:host" "/[method/host"
+	 (tramp-completion-file-name-structure6
+	  (list (concat tramp-prefix-regexp
+			"\\(" tramp-method-regexp "\\)" tramp-postfix-single-method-regexp
+			"\\(" tramp-host-regexp x-nil   "\\)$")
+		1 nil 2 nil))
+	 ;; "/method:user@host" "/[method/user@host"
+	 (tramp-completion-file-name-structure7
+	  (list (concat tramp-prefix-regexp
+			"\\(" tramp-method-regexp "\\)" tramp-postfix-single-method-regexp
+			"\\(" tramp-user-regexp "\\)"   tramp-postfix-user-regexp
+			"\\(" tramp-host-regexp x-nil   "\\)$")
+		1 2 3 nil)))
+
+    (mapcar (lambda (regexp)
       (add-to-list 'result
 	(tramp-completion-dissect-file-name1 regexp name)))
       (list
@@ -3797,7 +3712,8 @@
   (let (method)
     (save-match-data
       (when (string-match (nth 0 structure) name)
-	(setq method (match-string (nth 1 structure) name))
+	(setq method (and (nth 1 structure)
+			  (match-string (nth 1 structure) name)))
 	(if (and method (member method tramp-multi-methods))
 	    ;; Not handled (yet).
 	    (make-tramp-file-name
@@ -3806,9 +3722,12 @@
 	     :user nil
 	     :host nil
 	     :path nil)
-	  (let ((user   (match-string (nth 2 structure) name))
-		(host   (match-string (nth 3 structure) name))
-		(path   (match-string (nth 4 structure) name)))
+	  (let ((user   (and (nth 2 structure)
+			     (match-string (nth 2 structure) name)))
+		(host   (and (nth 3 structure)
+			     (match-string (nth 3 structure) name)))
+		(path   (and (nth 4 structure)
+			     (match-string (nth 4 structure) name))))
 	    (make-tramp-file-name
 	     :multi-method nil
 	     :method method
@@ -3818,21 +3737,15 @@
 
 ;; This function returns all possible method completions, adding the
 ;; trailing method delimeter.
-;; In case of Emacs, `tramp-ftp-method' is handled as well because it doesn't
-;; belong to `tramp-methods'.
 (defun tramp-get-completion-methods (partial-method)
   "Returns all method completions for PARTIAL-METHOD."
-  (let ((all-methods (delete "multi" (mapcar 'car tramp-methods))))
-
-    (mapcar
-     '(lambda (method)
-	(and method
-	 (string-match (concat "^" (regexp-quote partial-method)) method)
-	 ;; we must remove leading "/".
-	 (substring (tramp-make-tramp-file-name nil method nil nil nil) 1)))
-
-     (add-to-list 'all-methods
-		  (when tramp-unified-filenames tramp-ftp-method)))))
+  (mapcar
+   (lambda (method)
+     (and method
+	  (string-match (concat "^" (regexp-quote partial-method)) method)
+	  ;; we must remove leading "/".
+	  (substring (tramp-make-tramp-file-name nil method nil nil nil) 1)))
+   (delete "multi" (mapcar 'car tramp-methods))))
 
 ;; Compares partial user and host names with possible completions.
 (defun tramp-get-completion-user-host (method partial-user partial-host user host)
@@ -4401,8 +4314,8 @@
     (pop-to-buffer (tramp-get-buffer multi-method method user host))
     (unless (y-or-n-p (match-string 0))
       (kill-process p)
-      (erase-buffer)
       (throw 'tramp-action 'permission-denied))
+    (erase-buffer)
     (process-send-string p (concat "y" tramp-rsh-end-of-line))))
 
 (defun tramp-action-terminal (p multi-method method user host)
@@ -4692,8 +4605,8 @@
 			(tramp-find-method multi-method method user host)
 			user host)
                        (mapcar
-                        '(lambda (x)
-                           (format-spec x `((?u . ,(or user "root")))))
+                        (lambda (x)
+			  (format-spec x `((?u . ,(or user "root")))))
                         (tramp-get-su-args
 			 multi-method
 			 (tramp-find-method multi-method method user host)
@@ -5808,16 +5721,22 @@
   "Return an `tramp-file-name' structure.
 The structure consists of remote method, remote user, remote host and
 remote path name."
-  (let (method)
-    (save-match-data
-      (unless (string-match (nth 0 tramp-file-name-structure) name)
-        (error "Not a tramp file name: %s" name))
-      (setq method (match-string (nth 1 tramp-file-name-structure) name))
+  (save-match-data
+    (let* ((match (string-match (nth 0 tramp-file-name-structure) name))
+	   (method
+	    ; single-hop
+	    (if match (match-string (nth 1 tramp-file-name-structure) name)
+	      ; maybe multi-hop
+	      (string-match
+	       (format (nth 0 tramp-multi-file-name-structure)
+		       (nth 0 tramp-multi-file-name-hop-structure)) name)
+	      (match-string (nth 1 tramp-multi-file-name-structure) name))))
       (if (and method (member method tramp-multi-methods))
           ;; If it's a multi method, the file name structure contains
           ;; arrays of method, user and host.
           (tramp-dissect-multi-file-name name)
         ;; Normal method.  First, find out default method.
+	(unless match (error "Not a tramp file name: %s" name))
 	(let ((user (match-string (nth 2 tramp-file-name-structure) name))
 	      (host (match-string (nth 3 tramp-file-name-structure) name))
 	      (path (match-string (nth 4 tramp-file-name-structure) name)))
@@ -5923,12 +5842,6 @@
       (format "%s@%s:%s" user host path)
     (format "%s:%s" host path)))
 
-(defun tramp-make-ange-ftp-file-name (user host path)
-  "Given user, host, and path, return an Ange-FTP filename."
-  (if user
-      (format "/%s@%s:%s" user host path)
-    (format "/%s:%s" host path)))
-
 (defun tramp-method-out-of-band-p (multi-method method user host)
   "Return t if this is an out-of-band method, nil otherwise.
 It is important to check for this condition, since it is not possible
@@ -6412,6 +6325,14 @@
 
 ;;; TODO:
 
+;; * Allow putting passwords in the filename.
+;;   This should be implemented via a general mechanism to add
+;;   parameters in filenames.  There is currently a kludge for
+;;   putting the port number into the filename for ssh and ftp
+;;   files.  This could be subsumed by the new mechanism as well.
+;;   Another approach is to read a netrc file like ~/.authinfo
+;;   from Gnus.
+;; * Handle nonlocal exits such as C-g.
 ;; * Autodetect if remote `ls' groks the "--dired" switch.
 ;; * Add fallback for inline encodings.  This should be used
 ;;   if the remote end doesn't support mimencode or a similar program.
@@ -6517,10 +6438,6 @@
 ;;    connect to host "blabla" already if that host is unique. No idea
 ;;    how to suppress. Maybe not an essential problem.
 ;; ** Try to avoid usage of `last-input-event' in `tramp-completion-mode'.
-;; ** Handle quoted file names, starting with "/:". Problem is that
-;;    `file-name-non-special' calls later on `file-name-all-completions'
-;;    without ":". Hmm. Worth a bug report?
-;; ** Acknowledge port numbers.
 ;; ** Extend `tramp-get-completion-su' for NIS and shadow passwords.
 ;; ** Unify `tramp-parse-{rhosts,shosts,hosts,passwd,netrc}'.
 ;;    Code is nearly identical.