Commit | Line | Data |
---|---|---|
bce04fee | 1 | ;;; tramp-ftp.el --- Tramp convenience functions for Ange-FTP |
4007ba5b | 2 | |
76d99f95 | 3 | ;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, |
ae940284 | 4 | ;; 2008, 2009 Free Software Foundation, Inc. |
4007ba5b | 5 | |
d2a2c17f | 6 | ;; Author: Michael Albinus <michael.albinus@gmx.de> |
4007ba5b KG |
7 | ;; Keywords: comm, processes |
8 | ||
9 | ;; This file is part of GNU Emacs. | |
10 | ||
874a927a | 11 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
4007ba5b | 12 | ;; it under the terms of the GNU General Public License as published by |
874a927a GM |
13 | ;; the Free Software Foundation, either version 3 of the License, or |
14 | ;; (at your option) any later version. | |
4007ba5b KG |
15 | |
16 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | ;; GNU General Public License for more details. | |
20 | ||
21 | ;; You should have received a copy of the GNU General Public License | |
874a927a | 22 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
4007ba5b KG |
23 | |
24 | ;;; Commentary: | |
25 | ||
5ec2cc41 KG |
26 | ;; Convenience functions for calling Ange-FTP from Tramp. |
27 | ;; Most of them are displaced from tramp.el. | |
4007ba5b KG |
28 | |
29 | ;;; Code: | |
30 | ||
31 | (require 'tramp) | |
0f205eee | 32 | (autoload 'tramp-set-connection-property "tramp-cache") |
4007ba5b | 33 | |
efe78a6c MA |
34 | (eval-when-compile |
35 | ||
36 | ;; Pacify byte-compiler. | |
37 | (require 'cl) | |
38 | (require 'custom)) | |
4007ba5b KG |
39 | |
40 | ;; Disable Ange-FTP from file-name-handler-alist. | |
41 | ;; To handle EFS, the following functions need to be dealt with: | |
42 | ;; | |
43 | ;; * dired-before-readin-hook contains efs-dired-before-readin | |
44 | ;; * file-name-handler-alist contains efs-file-handler-function | |
45 | ;; and efs-root-handler-function and efs-sifn-handler-function | |
46 | ;; * find-file-hooks contains efs-set-buffer-mode | |
47 | ;; | |
48 | ;; But it won't happen for EFS since the XEmacs maintainers | |
49 | ;; don't want to use a unified filename syntax. | |
50 | (defun tramp-disable-ange-ftp () | |
51 | "Turn Ange-FTP off. | |
52 | This is useful for unified remoting. See | |
53 | `tramp-file-name-structure-unified' and | |
54 | `tramp-file-name-structure-separate' for details. Requests suitable | |
55 | for Ange-FTP will be forwarded to Ange-FTP. Also see the variables | |
56 | `tramp-ftp-method', `tramp-default-method', and | |
57 | `tramp-default-method-alist'. | |
58 | ||
59 | This function is not needed in Emacsen which include Tramp, but is | |
60 | present for backward compatibility." | |
61 | (let ((a1 (rassq 'ange-ftp-hook-function file-name-handler-alist)) | |
62 | (a2 (rassq 'ange-ftp-completion-hook-function file-name-handler-alist))) | |
63 | (setq file-name-handler-alist | |
64 | (delete a1 (delete a2 file-name-handler-alist))))) | |
a69c01a0 MA |
65 | |
66 | (eval-after-load "ange-ftp" | |
67 | '(when (functionp 'tramp-disable-ange-ftp) | |
68 | (tramp-disable-ange-ftp))) | |
69 | ||
70 | ;;;###autoload | |
71 | (defun tramp-ftp-enable-ange-ftp () | |
72 | ;; The following code is commented out in Ange-FTP. | |
73 | ||
74 | ;;; This regexp takes care of real ange-ftp file names (with a slash | |
75 | ;;; and colon). | |
76 | ;;; Don't allow the host name to end in a period--some systems use /.: | |
77 | (or (assoc "^/[^/:]*[^/:.]:" file-name-handler-alist) | |
78 | (setq file-name-handler-alist | |
79 | (cons '("^/[^/:]*[^/:.]:" . ange-ftp-hook-function) | |
80 | file-name-handler-alist))) | |
81 | ||
82 | ;;; This regexp recognizes absolute filenames with only one component, | |
83 | ;;; for the sake of hostname completion. | |
84 | (or (assoc "^/[^/:]*\\'" file-name-handler-alist) | |
85 | (setq file-name-handler-alist | |
86 | (cons '("^/[^/:]*\\'" . ange-ftp-completion-hook-function) | |
87 | file-name-handler-alist))) | |
88 | ||
89 | ;;; This regexp recognizes absolute filenames with only one component | |
90 | ;;; on Windows, for the sake of hostname completion. | |
91 | (and (memq system-type '(ms-dos windows-nt)) | |
92 | (or (assoc "^[a-zA-Z]:/[^/:]*\\'" file-name-handler-alist) | |
93 | (setq file-name-handler-alist | |
94 | (cons '("^[a-zA-Z]:/[^/:]*\\'" . | |
95 | ange-ftp-completion-hook-function) | |
96 | file-name-handler-alist))))) | |
97 | ||
98 | (add-hook 'tramp-ftp-unload-hook 'tramp-ftp-enable-ange-ftp) | |
4007ba5b KG |
99 | |
100 | ;; Define FTP method ... | |
101 | (defcustom tramp-ftp-method "ftp" | |
102 | "*When this method name is used, forward all calls to Ange-FTP." | |
103 | :group 'tramp | |
104 | :type 'string) | |
105 | ||
106 | ;; ... and add it to the method list. | |
107 | (add-to-list 'tramp-methods (cons tramp-ftp-method nil)) | |
108 | ||
109 | ;; Add some defaults for `tramp-default-method-alist' | |
110 | (add-to-list 'tramp-default-method-alist | |
8daea7fc | 111 | (list "\\`ftp\\." "" tramp-ftp-method)) |
4007ba5b | 112 | (add-to-list 'tramp-default-method-alist |
8daea7fc | 113 | (list "" "\\`\\(anonymous\\|ftp\\)\\'" tramp-ftp-method)) |
4007ba5b KG |
114 | |
115 | ;; Add completion function for FTP method. | |
00d6fd04 MA |
116 | (tramp-set-completion-function |
117 | tramp-ftp-method | |
118 | '((tramp-parse-netrc "~/.netrc"))) | |
119 | ||
120 | ;; If there is URL syntax, `substitute-in-file-name' needs special | |
121 | ;; handling. | |
122 | (put 'substitute-in-file-name 'ange-ftp 'tramp-handle-substitute-in-file-name) | |
2d8b5d77 MA |
123 | (add-hook 'tramp-ftp-unload-hook |
124 | '(lambda () | |
125 | (setplist 'substitute-in-file-name | |
126 | (delete 'ange-ftp | |
127 | (delete 'tramp-handle-substitute-in-file-name | |
128 | (symbol-plist | |
129 | 'substitute-in-file-name)))))) | |
4007ba5b KG |
130 | |
131 | (defun tramp-ftp-file-name-handler (operation &rest args) | |
132 | "Invoke the Ange-FTP handler for OPERATION. | |
133 | First arg specifies the OPERATION, second arg is a list of arguments to | |
134 | pass to the OPERATION." | |
135 | (save-match-data | |
136 | (or (boundp 'ange-ftp-name-format) | |
8daea7fc | 137 | (require 'ange-ftp)) |
83bbd71b KG |
138 | (let ((ange-ftp-name-format |
139 | (list (nth 0 tramp-file-name-structure) | |
140 | (nth 3 tramp-file-name-structure) | |
141 | (nth 2 tramp-file-name-structure) | |
5ec2cc41 KG |
142 | (nth 4 tramp-file-name-structure))) |
143 | ;; ange-ftp uses `ange-ftp-ftp-name-arg' and `ange-ftp-ftp-name-res' | |
144 | ;; for optimization in `ange-ftp-ftp-name'. If Tramp wasn't active, | |
145 | ;; there could be incorrect values from previous calls in case the | |
146 | ;; "ftp" method is used in the Tramp file name. So we unset | |
147 | ;; those values. | |
148 | (ange-ftp-ftp-name-arg "") | |
149 | (ange-ftp-ftp-name-res nil)) | |
83bbd71b | 150 | (cond |
0f205eee MA |
151 | ;; If argument is a symlink, `file-directory-p' and |
152 | ;; `file-exists-p' call the traversed file recursively. So we | |
153 | ;; cannot disable the file-name-handler this case. We set the | |
154 | ;; connection property "started" in order to put the remote | |
155 | ;; location into the cache, which is helpful for further | |
b08104a0 MA |
156 | ;; completion. We don't use `with-parsed-tramp-file-name', |
157 | ;; because this returns another user but the one declared in | |
158 | ;; "~/.netrc". | |
83bbd71b | 159 | ((memq operation '(file-directory-p file-exists-p)) |
0f205eee | 160 | (if (apply 'ange-ftp-hook-function operation args) |
b08104a0 MA |
161 | (let ((v (tramp-dissect-file-name (car args) t))) |
162 | (aset v 0 tramp-ftp-method) | |
0f205eee MA |
163 | (tramp-set-connection-property v "started" t)) |
164 | nil)) | |
b50dd0d2 | 165 | |
94be87e8 MA |
166 | ;; If the second argument of `copy-file' or `rename-file' is a |
167 | ;; remote file name but via FTP, ange-ftp doesn't check this. | |
168 | ;; We must copy it locally first, because there is no place in | |
169 | ;; ange-ftp for correct handling. | |
170 | ((and (memq operation '(copy-file rename-file)) | |
171 | (file-remote-p (cadr args)) | |
172 | (not (tramp-ftp-file-name-p (cadr args)))) | |
173 | (let* ((filename (car args)) | |
174 | (newname (cadr args)) | |
258800f8 | 175 | (tmpfile (tramp-compat-make-temp-file filename)) |
94be87e8 | 176 | (args (cddr args))) |
b50dd0d2 MA |
177 | ;; We must set `ok-if-already-exists' to t in the first |
178 | ;; step, because the temp file has been created already. | |
179 | (if (eq operation 'copy-file) | |
180 | (apply operation filename tmpfile t (cdr args)) | |
181 | (apply operation filename tmpfile t)) | |
182 | (unwind-protect | |
183 | (rename-file tmpfile newname (car args)) | |
184 | ;; Cleanup. | |
185 | (ignore-errors (delete-file tmpfile))))) | |
186 | ||
0f205eee | 187 | ;; Normally, the handlers must be discarded. |
2d8b5d77 MA |
188 | ;; `inhibit-file-name-handlers' isn't sufficient, because the |
189 | ;; local file name could be in Tramp syntax as well (for | |
190 | ;; example, returning VMS file names like "/DISK$CAM:/AAA"). | |
191 | ;; That's why we set also `tramp-mode' to nil. | |
8e303a2f | 192 | (t (let* (;(tramp-mode nil) |
2d8b5d77 | 193 | (inhibit-file-name-handlers |
0f205eee MA |
194 | (list 'tramp-file-name-handler |
195 | 'tramp-completion-file-name-handler | |
196 | (and (eq inhibit-file-name-operation operation) | |
197 | inhibit-file-name-handlers))) | |
198 | (inhibit-file-name-operation operation)) | |
199 | (apply 'ange-ftp-hook-function operation args))))))) | |
4007ba5b KG |
200 | |
201 | (defun tramp-ftp-file-name-p (filename) | |
202 | "Check if it's a filename that should be forwarded to Ange-FTP." | |
203 | (let ((v (tramp-dissect-file-name filename))) | |
00d6fd04 | 204 | (string= (tramp-file-name-method v) tramp-ftp-method))) |
4007ba5b KG |
205 | |
206 | (add-to-list 'tramp-foreign-file-name-handler-alist | |
207 | (cons 'tramp-ftp-file-name-p 'tramp-ftp-file-name-handler)) | |
208 | ||
209 | (provide 'tramp-ftp) | |
210 | ||
211 | ;;; TODO: | |
212 | ||
213 | ;; * In case of "/ftp:host:file" this works only for functions which | |
214 | ;; are defined in `tramp-file-name-handler-alist'. Call has to be | |
83bbd71b KG |
215 | ;; pretended in `tramp-file-name-handler' otherwise. |
216 | ;; Furthermore, there are no backup files on FTP hosts. | |
4007ba5b KG |
217 | ;; Worth further investigations. |
218 | ||
cbee283d | 219 | ;; arch-tag: 759fb338-5c63-4b99-bd36-b4d59db91cff |
4007ba5b | 220 | ;;; tramp-ftp.el ends here |