(mode-line-format): Moved global-mode-string last.
[bpt/emacs.git] / lisp / net / tramp.el
CommitLineData
fb7933a3
KG
1;;; tramp.el --- Transparent Remote Access, Multiple Protocol -*- coding: iso-8859-1; -*-
2
3;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
4
5;; Author: Kai.Grossjohann@CS.Uni-Dortmund.DE
6;; Keywords: comm, processes
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation; either version 2, or (at your option)
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
24
25;;; Commentary:
26
27;; This package provides remote file editing, similar to ange-ftp.
28;; The difference is that ange-ftp uses FTP to transfer files between
29;; the local and the remote host, whereas tramp.el uses a combination
30;; of rsh and rcp or other work-alike programs, such as ssh/scp.
31;;
32;; For more detailed instructions, please see the info file, which is
33;; included in the file `tramp.tar.gz' mentioned below.
34;;
35;; Notes:
36;; -----
37;;
38;; This package only works for Emacs 20 and higher, and for XEmacs 21
39;; and higher. (XEmacs 20 is missing the `with-timeout' macro. Emacs
40;; 19 is reported to have other problems. For XEmacs 21, you need the
41;; package `fsf-compat' for the `with-timeout' macro.)
42;;
43;; This version might not work with pre-Emacs 21 VC unless VC is
44;; loaded before tramp.el. Could you please test this and tell me about
45;; the result? Thanks.
46;;
47;; Also see the todo list at the bottom of this file.
48;;
49;; The current version of tramp.el can be retrieved from the following
50;; URL: ftp://ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/tramp.tar.gz
51;; For your convenience, the *.el file is available separately from
52;; the same directory.
53;;
54;; There's a mailing list for this, as well. Its name is:
c62c9d08 55;; tramp-devel@mail.freesoftware.fsf.org
fb7933a3
KG
56;; Send a mail with `help' in the subject (!) to the administration
57;; address for instructions on joining the list. The administration
58;; address is:
c62c9d08 59;; tramp-devel-request@mail.freesoftware.fsf.org
fb7933a3 60;; You can also use the Web to subscribe, under the following URL:
c62c9d08 61;; http://mail.freesoftware.fsf.org/mailman/listinfo/tramp-devel
fb7933a3
KG
62;;
63;; For the adventurous, the current development sources are available
64;; via CVS. You can find instructions about this at the following URL:
c62c9d08 65;; http://savannah.gnu.org/projects/tramp/
fb7933a3
KG
66;; Click on "CVS" in the navigation bar near the top.
67;;
68;; Don't forget to put on your asbestos longjohns, first!
69
70;;; Code:
71
b1d06e75
KG
72;; In the Tramp CVS repository, the version numer is auto-frobbed from
73;; the Makefile, so you should edit the top-level Makefile to change
74;; the version number.
685f5858 75(defconst tramp-version "2.0.12"
fb7933a3 76 "This version of tramp.")
ac474af1 77
fb7933a3
KG
78(defconst tramp-bug-report-address "tramp-devel@mail.freesoftware.fsf.org"
79 "Email address to send bug reports to.")
80
81(require 'timer)
82(require 'format-spec) ;from Gnus 5.8, also in tar ball
83(require 'base64) ;for the mimencode methods
84(require 'shell)
85(require 'advice)
86
87;; ;; It does not work to load EFS after loading TRAMP.
88;; (when (fboundp 'efs-file-handler-function)
89;; (require 'efs))
90
91(eval-when-compile
92 (require 'cl)
93 (require 'custom)
94 ;; Emacs 19.34 compatibility hack -- is this needed?
95 (or (>= emacs-major-version 20)
96 (load "cl-seq")))
97
98(unless (boundp 'custom-print-functions)
99 (defvar custom-print-functions nil)) ; not autoloaded before Emacs 20.4
100
101;;; User Customizable Internal Variables:
102
103(defgroup tramp nil
104 "Edit remote files with a combination of rsh and rcp or similar programs."
105 :group 'files)
106
107(defcustom tramp-verbose 10
108 "*Verbosity level for tramp.el. 0 means be silent, 10 is most verbose."
109 :group 'tramp
110 :type 'integer)
111
112(defcustom tramp-debug-buffer nil
113 "*Whether to send all commands and responses to a debug buffer."
114 :group 'tramp
115 :type 'boolean)
116
117(defcustom tramp-auto-save-directory nil
118 "*Put auto-save files in this directory, if set.
119The idea is to use a local directory so that auto-saving is faster."
120 :group 'tramp
121 :type '(choice (const nil)
122 string))
123
124(defcustom tramp-sh-program "/bin/sh"
125 "*Use this program for shell commands on the local host.
126This MUST be a Bourne-like shell. This shell is used to execute
127the encoding and decoding command on the local host, so if you
128want to use `~' in those commands, you should choose a shell here
129which groks tilde expansion. `/bin/sh' normally does not
130understand tilde expansion.
131
132Note that this variable is not used for remote commands. There are
133mechanisms in tramp.el which automatically determine the right shell to
134use for the remote host."
135 :group 'tramp
136 :type '(file :must-match t))
137
90dc758d
KG
138(defcustom tramp-multi-sh-program
139 (if (memq system-type '(windows-nt))
140 "cmd.exe"
141 tramp-sh-program)
142 "*Use this program for bootstrapping multi-hop connections.
143This variable is similar to `tramp-sh-program', but it is only used
144when initializing a multi-hop connection. Therefore, the set of
145commands sent to this shell is quite restricted, and if you are
146careful it works to use CMD.EXE under Windows (instead of a Bourne-ish
147shell which does not normally exist on Windows anyway).
148
149To use multi-hop methods from Windows, you also need suitable entries
150in `tramp-multi-connection-function-alist' for the first hop.
151
152This variable defaults to CMD.EXE on Windows NT, and to the value of
153`tramp-sh-program' on other systems."
154 :group 'tramp
155 :type '(file :must-match t))
156
fb7933a3
KG
157;; CCC I have changed all occurrences of comint-quote-filename with
158;; tramp-shell-quote-argument, except in tramp-handle-expand-many-files.
159;; There, comint-quote-filename was removed altogether. If it turns
160;; out to be necessary there, something will need to be done.
161;;-(defcustom tramp-file-name-quote-list
162;;- '(?] ?[ ?\| ?& ?< ?> ?\( ?\) ?\; ?\ ?\* ?\? ?\! ?\" ?\' ?\` ?# ?\@ ?\+ )
163;;- "*Protect these characters from the remote shell.
164;;-Any character in this list is quoted (preceded with a backslash)
165;;-because it means something special to the shell. This takes effect
166;;-when sending file and directory names to the remote shell.
167;;-
168;;-See `comint-file-name-quote-list' for details."
169;;- :group 'tramp
170;;- :type '(repeat character))
171
172(defcustom tramp-methods
173 '( ("rcp" (tramp-connection-function tramp-open-connection-rsh)
174 (tramp-rsh-program "rsh")
175 (tramp-rcp-program "rcp")
176 (tramp-remote-sh "/bin/sh")
177 (tramp-rsh-args nil)
178 (tramp-rcp-args nil)
179 (tramp-rcp-keep-date-arg "-p")
180 (tramp-su-program nil)
181 (tramp-su-args nil)
fb7933a3
KG
182 (tramp-telnet-program nil)
183 (tramp-telnet-args nil))
184 ("scp" (tramp-connection-function tramp-open-connection-rsh)
185 (tramp-rsh-program "ssh")
186 (tramp-rcp-program "scp")
187 (tramp-remote-sh "/bin/sh")
188 (tramp-rsh-args ("-e" "none"))
189 (tramp-rcp-args nil)
190 (tramp-rcp-keep-date-arg "-p")
191 (tramp-su-program nil)
192 (tramp-su-args nil)
fb7933a3
KG
193 (tramp-telnet-program nil)
194 (tramp-telnet-args nil))
195 ("scp1" (tramp-connection-function tramp-open-connection-rsh)
90dc758d
KG
196 (tramp-rsh-program "ssh")
197 (tramp-rcp-program "scp")
198 (tramp-remote-sh "/bin/sh")
199 (tramp-rsh-args ("-1" "-e" "none"))
200 (tramp-rcp-args ("-1"))
201 (tramp-rcp-keep-date-arg "-p")
202 (tramp-su-program nil)
203 (tramp-su-args nil)
90dc758d
KG
204 (tramp-telnet-program nil)
205 (tramp-telnet-args nil))
206 ("scp2" (tramp-connection-function tramp-open-connection-rsh)
207 (tramp-rsh-program "ssh")
208 (tramp-rcp-program "scp")
209 (tramp-remote-sh "/bin/sh")
210 (tramp-rsh-args ("-2" "-e" "none"))
211 (tramp-rcp-args ("-2"))
212 (tramp-rcp-keep-date-arg "-p")
213 (tramp-su-program nil)
214 (tramp-su-args nil)
90dc758d
KG
215 (tramp-telnet-program nil)
216 (tramp-telnet-args nil))
ac474af1
KG
217 ("scp1-old"
218 (tramp-connection-function tramp-open-connection-rsh)
fb7933a3
KG
219 (tramp-rsh-program "ssh1")
220 (tramp-rcp-program "scp1")
221 (tramp-remote-sh "/bin/sh")
222 (tramp-rsh-args ("-e" "none"))
223 (tramp-rcp-args nil)
224 (tramp-rcp-keep-date-arg "-p")
225 (tramp-su-program nil)
226 (tramp-su-args nil)
fb7933a3
KG
227 (tramp-telnet-program nil)
228 (tramp-telnet-args nil))
ac474af1
KG
229 ("scp2-old"
230 (tramp-connection-function tramp-open-connection-rsh)
fb7933a3
KG
231 (tramp-rsh-program "ssh2")
232 (tramp-rcp-program "scp2")
233 (tramp-remote-sh "/bin/sh")
234 (tramp-rsh-args ("-e" "none"))
235 (tramp-rcp-args nil)
236 (tramp-rcp-keep-date-arg "-p")
237 (tramp-su-program nil)
238 (tramp-su-args nil)
fb7933a3
KG
239 (tramp-telnet-program nil)
240 (tramp-telnet-args nil))
241 ("rsync" (tramp-connection-function tramp-open-connection-rsh)
242 (tramp-rsh-program "ssh")
243 (tramp-rcp-program "rsync")
244 (tramp-remote-sh "/bin/sh")
245 (tramp-rsh-args ("-e" "none"))
246 (tramp-rcp-args ("-e" "ssh"))
247 (tramp-rcp-keep-date-arg "-t")
248 (tramp-su-program nil)
249 (tramp-su-args nil)
fb7933a3
KG
250 (tramp-telnet-program nil)
251 (tramp-telnet-args nil))
ac474af1 252 ("rsh" (tramp-connection-function tramp-open-connection-rsh)
fb7933a3
KG
253 (tramp-rsh-program "rsh")
254 (tramp-rcp-program nil)
255 (tramp-remote-sh "/bin/sh")
256 (tramp-rsh-args nil)
257 (tramp-rcp-args nil)
258 (tramp-rcp-keep-date-arg nil)
259 (tramp-su-program nil)
260 (tramp-su-args nil)
fb7933a3
KG
261 (tramp-telnet-program nil)
262 (tramp-telnet-args nil))
ac474af1 263 ("ssh" (tramp-connection-function tramp-open-connection-rsh)
fb7933a3
KG
264 (tramp-rsh-program "ssh")
265 (tramp-rcp-program nil)
266 (tramp-remote-sh "/bin/sh")
267 (tramp-rsh-args ("-e" "none"))
268 (tramp-rcp-args nil)
269 (tramp-rcp-keep-date-arg nil)
270 (tramp-su-program nil)
271 (tramp-su-args nil)
fb7933a3
KG
272 (tramp-telnet-program nil)
273 (tramp-telnet-args nil))
ac474af1 274 ("ssh1" (tramp-connection-function tramp-open-connection-rsh)
90dc758d
KG
275 (tramp-rsh-program "ssh")
276 (tramp-rcp-program nil)
277 (tramp-remote-sh "/bin/sh")
278 (tramp-rsh-args ("-1" "-e" "none"))
279 (tramp-rcp-args ("-1"))
280 (tramp-rcp-keep-date-arg nil)
281 (tramp-su-program nil)
282 (tramp-su-args nil)
90dc758d
KG
283 (tramp-telnet-program nil)
284 (tramp-telnet-args nil))
ac474af1 285 ("ssh2" (tramp-connection-function tramp-open-connection-rsh)
90dc758d
KG
286 (tramp-rsh-program "ssh")
287 (tramp-rcp-program nil)
288 (tramp-remote-sh "/bin/sh")
289 (tramp-rsh-args ("-2" "-e" "none"))
290 (tramp-rcp-args ("-2"))
291 (tramp-rcp-keep-date-arg nil)
292 (tramp-su-program nil)
293 (tramp-su-args nil)
90dc758d
KG
294 (tramp-telnet-program nil)
295 (tramp-telnet-args nil))
ac474af1
KG
296 ("ssh1-old"
297 (tramp-connection-function tramp-open-connection-rsh)
fb7933a3
KG
298 (tramp-rsh-program "ssh1")
299 (tramp-rcp-program nil)
300 (tramp-remote-sh "/bin/sh")
301 (tramp-rsh-args ("-e" "none"))
302 (tramp-rcp-args nil)
303 (tramp-rcp-keep-date-arg nil)
304 (tramp-su-program nil)
305 (tramp-su-args nil)
fb7933a3
KG
306 (tramp-telnet-program nil)
307 (tramp-telnet-args nil))
ac474af1
KG
308 ("ssh2-old"
309 (tramp-connection-function tramp-open-connection-rsh)
fb7933a3
KG
310 (tramp-rsh-program "ssh2")
311 (tramp-rcp-program nil)
312 (tramp-remote-sh "/bin/sh")
313 (tramp-rsh-args ("-e" "none"))
314 (tramp-rcp-args nil)
315 (tramp-rcp-keep-date-arg nil)
316 (tramp-su-program nil)
317 (tramp-su-args nil)
90dc758d
KG
318 (tramp-telnet-program nil)
319 (tramp-telnet-args nil))
ac474af1
KG
320 ("ssh1-old"
321 (tramp-connection-function tramp-open-connection-rsh)
fb7933a3
KG
322 (tramp-rsh-program "ssh1")
323 (tramp-rcp-program nil)
324 (tramp-remote-sh "/bin/sh")
325 (tramp-rsh-args ("-e" "none"))
326 (tramp-rcp-args nil)
327 (tramp-rcp-keep-date-arg nil)
328 (tramp-su-program nil)
329 (tramp-su-args nil)
fb7933a3
KG
330 (tramp-telnet-program nil)
331 (tramp-telnet-args nil))
ac474af1
KG
332 ("ssh2-old"
333 (tramp-connection-function tramp-open-connection-rsh)
fb7933a3
KG
334 (tramp-rsh-program "ssh2")
335 (tramp-rcp-program nil)
336 (tramp-remote-sh "/bin/sh")
337 (tramp-rsh-args ("-e" "none"))
338 (tramp-rcp-args nil)
339 (tramp-rcp-keep-date-arg nil)
340 (tramp-su-program nil)
341 (tramp-su-args nil)
fb7933a3
KG
342 (tramp-telnet-program nil)
343 (tramp-telnet-args nil))
ac474af1
KG
344 ("telnet"
345 (tramp-connection-function tramp-open-connection-telnet)
fb7933a3
KG
346 (tramp-rsh-program nil)
347 (tramp-rcp-program nil)
348 (tramp-remote-sh "/bin/sh")
349 (tramp-rsh-args nil)
350 (tramp-rcp-args nil)
351 (tramp-rcp-keep-date-arg nil)
352 (tramp-su-program nil)
353 (tramp-su-args nil)
fb7933a3
KG
354 (tramp-telnet-program "telnet")
355 (tramp-telnet-args nil))
ac474af1 356 ("su" (tramp-connection-function tramp-open-connection-su)
fb7933a3
KG
357 (tramp-rsh-program nil)
358 (tramp-rcp-program nil)
359 (tramp-remote-sh "/bin/sh")
360 (tramp-rsh-args nil)
361 (tramp-rcp-args nil)
362 (tramp-rcp-keep-date-arg nil)
363 (tramp-su-program "su")
364 (tramp-su-args ("-" "%u"))
fb7933a3
KG
365 (tramp-telnet-program nil)
366 (tramp-telnet-args nil))
ac474af1 367 ("sudo" (tramp-connection-function tramp-open-connection-su)
fb7933a3
KG
368 (tramp-rsh-program nil)
369 (tramp-rcp-program nil)
370 (tramp-remote-sh "/bin/sh")
371 (tramp-rsh-args nil)
372 (tramp-rcp-args nil)
373 (tramp-rcp-keep-date-arg nil)
374 (tramp-su-program "sudo")
375 (tramp-su-args ("-u" "%u" "-s"))
fb7933a3
KG
376 (tramp-telnet-program nil)
377 (tramp-telnet-args nil))
378 ("multi" (tramp-connection-function tramp-open-connection-multi)
379 (tramp-rsh-program nil)
380 (tramp-rcp-program nil)
381 (tramp-remote-sh "/bin/sh")
382 (tramp-rsh-args nil)
383 (tramp-rcp-args nil)
384 (tramp-rcp-keep-date-arg nil)
385 (tramp-su-program nil)
386 (tramp-su-args nil)
fb7933a3
KG
387 (tramp-telnet-program nil)
388 (tramp-telnet-args nil))
389 ("scpx" (tramp-connection-function tramp-open-connection-rsh)
390 (tramp-rsh-program "ssh")
391 (tramp-rcp-program "scp")
392 (tramp-remote-sh "/bin/sh")
393 (tramp-rsh-args ("-e" "none" "-t" "-t" "/bin/sh"))
394 (tramp-rcp-args nil)
395 (tramp-rcp-keep-date-arg "-p")
fb7933a3
KG
396 (tramp-telnet-program nil)
397 (tramp-telnet-args nil))
ac474af1 398 ("sshx" (tramp-connection-function tramp-open-connection-rsh)
fb7933a3
KG
399 (tramp-rsh-program "ssh")
400 (tramp-rcp-program nil)
401 (tramp-remote-sh "/bin/sh")
402 (tramp-rsh-args ("-e" "none" "-t" "-t" "/bin/sh"))
403 (tramp-rcp-args nil)
404 (tramp-rcp-keep-date-arg nil)
405 (tramp-su-program nil)
406 (tramp-su-args nil)
fb7933a3
KG
407 (tramp-telnet-program nil)
408 (tramp-telnet-args nil))
ac474af1 409 ("krlogin"
fb7933a3
KG
410 (tramp-connection-function tramp-open-connection-rsh)
411 (tramp-rsh-program "krlogin")
412 (tramp-rcp-program nil)
413 (tramp-remote-sh "/bin/sh")
414 (tramp-rsh-args ("-x"))
415 (tramp-rcp-args nil)
416 (tramp-rcp-keep-date-arg nil)
417 (tramp-su-program nil)
418 (tramp-su-args nil)
fb7933a3
KG
419 (tramp-telnet-program nil)
420 (tramp-telnet-args nil))
ac474af1 421 ("plink"
fb7933a3
KG
422 (tramp-connection-function tramp-open-connection-rsh)
423 (tramp-rsh-program "plink")
424 (tramp-rcp-program nil)
425 (tramp-remote-sh "/bin/sh")
426 (tramp-rsh-args ("-ssh")) ;optionally add "-v"
427 (tramp-rcp-args nil)
428 (tramp-rcp-keep-date-arg nil)
429 (tramp-su-program nil)
430 (tramp-su-args nil)
fb7933a3
KG
431 (tramp-telnet-program nil)
432 (tramp-telnet-args nil))
433 ("pscp"
434 (tramp-connection-function tramp-open-connection-rsh)
435 (tramp-rsh-program "plink")
436 (tramp-rcp-program "pscp")
437 (tramp-remote-sh "/bin/sh")
438 (tramp-rsh-args ("-ssh"))
439 (tramp-rcp-args nil)
440 (tramp-rcp-keep-date-arg "-p")
441 (tramp-su-program nil)
442 (tramp-su-args nil)
fb7933a3
KG
443 (tramp-telnet-program nil)
444 (tramp-telnet-args nil))
445 ("fcp"
446 (tramp-connection-function tramp-open-connection-rsh)
447 (tramp-rsh-program "fsh")
448 (tramp-rcp-program "fcp")
449 (tramp-remote-sh "/bin/sh -i")
450 (tramp-rsh-args ("sh" "-i"))
451 (tramp-rcp-args nil)
452 (tramp-rcp-keep-date-arg "-p")
453 (tramp-su-program nil)
454 (tramp-su-args nil)
fb7933a3
KG
455 (tramp-telnet-program nil)
456 (tramp-telnet-args nil))
457 )
458 "*Alist of methods for remote files.
459This is a list of entries of the form (NAME PARAM1 PARAM2 ...).
460Each NAME stands for a remote access method. Each PARAM is a
461pair of the form (KEY VALUE). The following KEYs are defined:
462 * `tramp-connection-function'
463 This specifies the function to use to connect to the remote host.
464 Currently, `tramp-open-connection-rsh', `tramp-open-connection-telnet'
465 and `tramp-open-connection-su' are defined. See the documentation
466 of these functions for more details.
467 * `tramp-remote-sh'
468 This specifies the Bourne shell to use on the remote host. This
469 MUST be a Bourne-like shell. It is normally not necessary to set
470 this to any value other than \"/bin/sh\": tramp wants to use a shell
471 which groks tilde expansion, but it can search for it. Also note
472 that \"/bin/sh\" exists on all Unixen, this might not be true for
473 the value that you decide to use. You Have Been Warned.
474 * `tramp-rsh-program'
475 This specifies the name of the program to use for rsh; this might be
476 the full path to rsh or the name of a workalike program.
477 * `tramp-rsh-args'
478 This specifies the list of arguments to pass to the above
479 mentioned program. Please note that this is a list of arguments,
480 that is, normally you don't want to put \"-a -b\" or \"-f foo\"
481 here. Instead, you want two list elements, one for \"-a\" and one
482 for \"-b\", or one for \"-f\" and one for \"foo\".
483 * `tramp-rcp-program'
484 This specifies the name of the program to use for rcp; this might be
485 the full path to rcp or the name of a workalike program.
486 * `tramp-rcp-args'
487 This specifies the list of parameters to pass to the above mentioned
488 program, the hints for `tramp-rsh-args' also apply here.
489 * `tramp-rcp-keep-date-arg'
490 This specifies the parameter to use for `rcp' when the timestamp
491 of the original file should be kept. For `rcp', use `-p', for
492 `rsync', use `-t'.
493 * `tramp-su-program'
494 This specifies the name of the program to use for `su'.
495 * `tramp-su-args'
496 This specifies the list of arguments to pass to `su'.
497 \"%u\" is replaced by the user name, use \"%%\" for a literal
498 percent character.
499 * `tramp-encoding-command'
500 This specifies a command to use to encode the file contents for
501 transfer. The command should read the raw file contents from
502 standard input and write the encoded file contents to standard
503 output. In this string, the percent escape \"%f\" should be used
504 to indicate the file to convert. Use \"%%\" if you need a literal
505 percent character in your command.
506 * `tramp-decoding-command'
507 This specifies a command to use to decode file contents encoded
508 with `tramp-encoding-command'. The command should read from standard
509 input and write to standard output.
510 * `tramp-encoding-function'
511 This specifies a function to be called to encode the file contents
512 on the local side. This function should accept two arguments
513 START and END, the beginning and end of the region to encode. The
514 region should be replaced with the encoded contents.
515 * `tramp-decoding-function'
516 Same for decoding on the local side.
517 * `tramp-telnet-program'
518 Specifies the telnet program to use when using
519 `tramp-open-connection-telnet' to log in.
520 * `tramp-telnet-args'
521 Specifies list of arguments to pass to `telnet'. The hints for
522 `tramp-rsh-args' also apply here.
523
524What does all this mean? Well, you should specify `tramp-rsh-program',
525`tramp-telnet-program' or `tramp-su-program' for all methods; this program
526is used to log in to the remote site. Then, there are two ways to
527actually transfer the files between the local and the remote side.
528One way is using an additional rcp-like program. If you want to do
529this, set `tramp-rcp-program' in the method.
530
531Another possibility for file transfer is inline transfer, i.e. the
532file is passed through the same buffer used by `tramp-rsh-program'. In
533this case, the file contents need to be protected since the
534`tramp-rsh-program' might use escape codes or the connection might not
535be eight-bit clean. Therefore, file contents are encoded for transit.
536
537Two possibilities for encoding are uuencode/uudecode and mimencode.
538For uuencode/uudecode you want to set `tramp-encoding-command' to
539something like \"uuencode\" and `tramp-decoding-command' to \"uudecode
540-p\". For mimencode you want to set `tramp-encoding-command' to
541something like \"mimencode -b\" and `tramp-decoding-command' to
542\"mimencode -b -u\".
543
544When using inline transfer, you can use a program or a Lisp function
545on the local side to encode or decode the file contents. Set the
546`tramp-encoding-function' and `tramp-decoding-function' parameters to nil
547in order to use the commands or to the function to use. It is
548possible to specify one function and the other parameter as nil.
549
550So, to summarize: if the method is an inline method, you must specify
551`tramp-encoding-command' and `tramp-decoding-command', and
552`tramp-rcp-program' must be nil. If the method is out of band, then
553you must specify `tramp-rcp-program' and `tramp-rcp-args' and
554`tramp-encoding-command' and `tramp-decoding-command' must be nil.
555Every method, inline or out of band, must specify
556`tramp-connection-function' plus the associated arguments (for
557example, the telnet program if you chose
558`tramp-open-connection-telnet').
559
560Notes:
561
562When using `tramp-open-connection-su' the phrase `open connection to a
563remote host' sounds strange, but it is used nevertheless, for
564consistency. No connection is opened to a remote host, but `su' is
565started on the local host. You are not allowed to specify a remote
566host other than `localhost' or the name of the local host.
567
568Using a uuencode/uudecode inline method is discouraged, please use one
569of the base64 methods instead since base64 encoding is much more
570reliable and the commands are more standardized between the different
571Unix versions. But if you can't use base64 for some reason, please
572note that the default uudecode command does not work well for some
573Unices, in particular AIX and Irix. For AIX, you might want to use
574the following command for uudecode:
575
576 sed '/^begin/d;/^[` ]$/d;/^end/d' | iconv -f uucode -t ISO8859-1
577
578For Irix, no solution is known yet."
579 :group 'tramp
580 :type '(repeat
581 (cons string
582 (set (list (const tramp-connection-function) function)
583 (list (const tramp-rsh-program)
584 (choice (const nil) string))
585 (list (const tramp-rcp-program)
586 (choice (const nil) string))
587 (list (const tramp-remote-sh)
588 (choice (const nil) string))
589 (list (const tramp-rsh-args) (repeat string))
590 (list (const tramp-rcp-args) (repeat string))
591 (list (const tramp-rcp-keep-date-arg)
592 (choice (const nil) string))
593 (list (const tramp-su-program)
594 (choice (const nil) string))
595 (list (const tramp-su-args) (repeat string))
596 (list (const tramp-encoding-command)
597 (choice (const nil) string))
598 (list (const tramp-decoding-command)
599 (choice (const nil) string))
600 (list (const tramp-encoding-function)
601 (choice (const nil) function))
602 (list (const tramp-decoding-function)
603 (choice (const nil) function))
604 (list (const tramp-telnet-program)
605 (choice (const nil) string))
606 (list (const tramp-telnet-args) (repeat string))))))
607
608(defcustom tramp-multi-methods '("multi" "multiu")
609 "*List of multi-hop methods.
610Each entry in this list should be a method name as mentioned in the
611variable `tramp-methods'."
612 :group 'tramp
613 :type '(repeat string))
614
615(defcustom tramp-multi-connection-function-alist
616 '(("telnet" tramp-multi-connect-telnet "telnet %h%n")
617 ("rsh" tramp-multi-connect-rlogin "rsh %h -l %u%n")
618 ("ssh" tramp-multi-connect-rlogin "ssh %h -l %u%n")
619 ("su" tramp-multi-connect-su "su - %u%n")
620 ("sudo" tramp-multi-connect-su "sudo -u %u -s%n"))
621 "*List of connection functions for multi-hop methods.
622Each list item is a list of three items (METHOD FUNCTION COMMAND),
623where METHOD is the name as used in the file name, FUNCTION is the
624function to be executed, and COMMAND is the shell command used for
625connecting.
626
627COMMAND may contain percent escapes. `%u' will be replaced with the
628user name, `%h' will be replaced with the host name, and `%n' will be
629replaced with an end-of-line character, as specified in the variable
630`tramp-rsh-end-of-line'. Use `%%' for a literal percent character.
631Note that the interpretation of the percent escapes also depends on
632the FUNCTION. For example, the `%u' escape is forbidden with the
633function `tramp-multi-connect-telnet'. See the documentation of the
634various functions for details."
635 :group 'tramp
636 :type '(repeat (list string function string)))
637
b1d06e75 638(defcustom tramp-default-method "ssh"
fb7933a3 639 "*Default method to use for transferring files.
c62c9d08 640See `tramp-methods' for possibilities.
505edaeb
KG
641Also see `tramp-default-method-alist'.
642
643Emacs uses a unified filename syntax for Tramp and Ange-FTP.
644For backward compatibility, the default value of this variable
645is \"ftp\" on Emacs. But XEmacs uses a separate filename syntax
646for Tramp and EFS, so there the default method is \"sm\"."
c62c9d08
KG
647 :group 'tramp
648 :type 'string)
649
505edaeb
KG
650(defcustom tramp-default-method-alist
651 (if (featurep 'xemacs)
652 nil
653 '(("\\`ftp\\." "" "ftp")
654 ("" "\\`\\(anonymous\\|ftp\\)\\'" "ftp")))
c62c9d08
KG
655 "*Default method to use for specific user/host pairs.
656This is an alist of items (HOST USER METHOD). The first matching item
657specifies the method to use for a file name which does not specify a
658method. HOST and USER are regular expressions or nil, which is
659interpreted as a regular expression which always matches. If no entry
660matches, the variable `tramp-default-method' takes effect.
661
662If the file name does not specify the user, lookup is done using the
663empty string for the user name.
664
665See `tramp-methods' for a list of possibilities for METHOD."
666 :group 'tramp
667 :type '(repeat (list (regexp :tag "Host regexp")
668 (regexp :tag "User regexp")
669 (string :tag "Method"))))
670
671(defcustom tramp-ftp-method "ftp"
672 "*When this method name is used, forward all calls to Ange-FTP."
fb7933a3
KG
673 :group 'tramp
674 :type 'string)
675
676(defcustom tramp-rsh-end-of-line "\n"
677 "*String used for end of line in rsh connections.
678I don't think this ever needs to be changed, so please tell me about it
679if you need to change this."
680 :group 'tramp
681 :type 'string)
682
683(defcustom tramp-remote-path
684 '("/bin" "/usr/bin" "/usr/sbin" "/usr/local/bin" "/usr/ccs/bin"
685 "/local/bin" "/local/freeware/bin" "/local/gnu/bin"
686 "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin")
687 "*List of directories to search for executables on remote host.
688Please notify me about other semi-standard directories to include here.
689
690You can use `~' in this list, but when searching for a shell which groks
691tilde expansion, all directory names starting with `~' will be ignored."
692 :group 'tramp
693 :type '(repeat string))
694
695(defcustom tramp-login-prompt-regexp
ac474af1 696 ".*ogin: *"
fb7933a3 697 "*Regexp matching login-like prompts.
ac474af1 698The regexp should match at end of buffer."
fb7933a3
KG
699 :group 'tramp
700 :type 'regexp)
701
702(defcustom tramp-password-prompt-regexp
ac474af1 703 "^.*\\([pP]assword\\|passphrase.*\\):\^@? *"
fb7933a3 704 "*Regexp matching password-like prompts.
ac474af1 705The regexp should match at end of buffer.
fb7933a3
KG
706
707The `sudo' program appears to insert a `^@' character into the prompt."
708 :group 'tramp
709 :type 'regexp)
710
711(defcustom tramp-wrong-passwd-regexp
b1d06e75
KG
712 (concat "^.*"
713 ;; These strings should be on the last line
714 (regexp-opt '("Permission denied."
715 "Login incorrect"
716 "Login Incorrect"
717 "Connection refused"
718 "Connection closed"
719 "Sorry, try again."
720 "Name or service not known"
721 "Host key verification failed.") t)
722 ".*"
723 "\\|"
724 "^.*\\("
725 ;; Here comes a list of regexes, separated by \\|
726 "Received signal [0-9]+"
727 "\\).*")
fb7933a3 728 "*Regexp matching a `login failed' message.
ac474af1
KG
729The regexp should match at end of buffer."
730 :group 'tramp
731 :type 'regexp)
732
733(defcustom tramp-yesno-prompt-regexp
734 "Are you sure you want to continue connecting (yes/no)\\? *"
735 "Regular expression matching all queries which need to be confirmed.
736The confirmation should be done with yes or no.
737The regexp should match at end of buffer."
fb7933a3
KG
738 :group 'tramp
739 :type 'regexp)
740
741(defcustom tramp-temp-name-prefix "tramp."
742 "*Prefix to use for temporary files.
743If this is a relative file name (such as \"tramp.\"), it is considered
744relative to the directory name returned by the function
745`tramp-temporary-file-directory' (which see). It may also be an
746absolute file name; don't forget to include a prefix for the filename
747part, though."
748 :group 'tramp
749 :type 'string)
750
751(defcustom tramp-discard-garbage nil
752 "*If non-nil, try to discard garbage sent by remote shell.
753Some shells send such garbage upon connection setup."
754 :group 'tramp
755 :type 'boolean)
756
c62c9d08
KG
757(defcustom tramp-sh-extra-args '(("/bash\\'" . "--norc"))
758 "*Alist specifying extra arguments to pass to the remote shell.
759Entries are (REGEXP . ARGS) where REGEXP is a regular expression
760matching the shell file name and ARGS is a string specifying the
761arguments.
762
763This variable is only used when Tramp needs to start up another shell
764for tilde expansion. The extra arguments should typically prevent the
765shell from reading its init file."
766 :group 'tramp
767 :type '(alist :key-type string :value-type string))
768
fb7933a3
KG
769;; File name format.
770
505edaeb 771(defconst tramp-file-name-structure-unified
ac474af1 772 (list (concat "\\`/\\(\\([a-zA-Z0-9-]+\\):\\)?" ;method
505edaeb
KG
773 "\\(\\([^:@/]+\\)@\\)?" ;user
774 "\\([^:/]+\\):" ;host
775 "\\(.*\\)\\'") ;path
776 2 4 5 6)
777 "Default value for `tramp-file-name-structure' for unified remoting.
778On Emacs (not XEmacs), the Tramp and Ange-FTP packages use a unified
779filename space. This value is used for this unified namespace.")
780
781(defconst tramp-file-name-structure-separate
ac474af1 782 (list (concat "\\`/\\[\\(\\([a-zA-Z0-9-]+\\)/\\)?" ;method
487fa986
KG
783 "\\(\\([-a-zA-Z0-9_#/:]+\\)@\\)?" ;user
784 "\\([-a-zA-Z0-9_#/:@.]+\\)\\]" ;host
785 "\\(.*\\)\\'") ;path
fb7933a3 786 2 4 5 6)
505edaeb
KG
787 "Default value for `tramp-file-name-structure' for separate remoting.
788On XEmacs, the Tramp and EFS packages use a separate namespace for
789remote filenames. This value is used in that case. It is designed
790not to clash with the EFS filename syntax.")
791
792(defcustom tramp-file-name-structure
793 (if (featurep 'xemacs)
794 tramp-file-name-structure-separate
795 tramp-file-name-structure-unified)
fb7933a3
KG
796 "*List of five elements (REGEXP METHOD USER HOST FILE), detailing \
797the tramp file name structure.
798
799The first element REGEXP is a regular expression matching a tramp file
800name. The regex should contain parentheses around the method name,
801the user name, the host name, and the file name parts.
802
803The second element METHOD is a number, saying which pair of
804parentheses matches the method name. The third element USER is
805similar, but for the user name. The fourth element HOST is similar,
806but for the host name. The fifth element FILE is for the file name.
807These numbers are passed directly to `match-string', which see. That
808means the opening parentheses are counted to identify the pair.
809
810See also `tramp-file-name-regexp' and `tramp-make-tramp-file-format'."
811 :group 'tramp
812 :type '(list (regexp :tag "File name regexp")
813 (integer :tag "Paren pair for method name")
814 (integer :tag "Paren pair for user name ")
815 (integer :tag "Paren pair for host name ")
816 (integer :tag "Paren pair for file name ")))
817
818;;;###autoload
505edaeb
KG
819(defconst tramp-file-name-regexp-unified
820 "\\`/[^/:]+:"
821 "Value for `tramp-file-name-regexp' for unified remoting.
822Emacs (not XEmacs) uses a unified filename syntax for Ange-FTP and
823Tramp. See `tramp-file-name-structure-unified' for more explanations.")
824
825;;;###autoload
826(defconst tramp-file-name-regexp-separate
827 "\\`/\\[.*\\]"
828 "Value for `tramp-file-name-regexp' for separate remoting.
829XEmacs uses a separate filename syntax for Tramp and EFS.
830See `tramp-file-name-structure-separate' for more explanations.")
831
832;;;###autoload
833(defcustom tramp-file-name-regexp
834 (if (featurep 'xemacs)
835 tramp-file-name-regexp-separate
836 tramp-file-name-regexp-unified)
fb7933a3
KG
837 "*Regular expression matching file names handled by tramp.
838This regexp should match tramp file names but no other file names.
839\(When tramp.el is loaded, this regular expression is prepended to
840`file-name-handler-alist', and that is searched sequentially. Thus,
841if the tramp entry appears rather early in the `file-name-handler-alist'
842and is a bit too general, then some files might be considered tramp
843files which are not really tramp files.
844
845Please note that the entry in `file-name-handler-alist' is made when
846this file (tramp.el) is loaded. This means that this variable must be set
847before loading tramp.el. Alternatively, `file-name-handler-alist' can be
848updated after changing this variable.
849
850Also see `tramp-file-name-structure' and `tramp-make-tramp-file-format'."
851 :group 'tramp
852 :type 'regexp)
853
505edaeb
KG
854(defconst tramp-make-tramp-file-format-unified
855 "/%m:%u@%h:%p"
856 "Value for `tramp-make-tramp-file-format' for unified remoting.
857Emacs (not XEmacs) uses a unified filename syntax for Ange-FTP and Tramp.
858See `tramp-file-name-structure-unified' for more details.")
859
860(defconst tramp-make-tramp-file-format-separate
861 "/[%m/%u@%h]%p"
862 "Value for `tramp-make-tramp-file-format' for separate remoting.
863XEmacs uses a separate filename syntax for EFS and Tramp.
864See `tramp-file-name-structure-separate' for more details.")
865
866(defcustom tramp-make-tramp-file-format
867 (if (featurep 'xemacs)
868 tramp-make-tramp-file-format-separate
869 tramp-make-tramp-file-format-unified)
fb7933a3
KG
870 "*Format string saying how to construct tramp file name.
871`%m' is replaced by the method name.
872`%u' is replaced by the user name.
873`%h' is replaced by the host name.
874`%p' is replaced by the file name.
875`%%' is replaced by %.
876
877Also see `tramp-file-name-structure' and `tramp-file-name-regexp'."
878 :group 'tramp
879 :type 'string)
880
505edaeb
KG
881(defconst tramp-make-tramp-file-user-nil-format-unified
882 "/%m:%h:%p"
883 "Value of `tramp-make-tramp-file-user-nil-format' for unified remoting.
884Emacs (not XEmacs) uses a unified filename syntax for Ange-FTP and Tramp.
885See `tramp-file-name-structure-unified' for details.")
886
887(defconst tramp-make-tramp-file-user-nil-format-separate
888 "/[%m/%h]%p"
889 "Value of `tramp-make-tramp-file-user-nil-format' for separate remoting.
890XEmacs uses a separate filename syntax for EFS and Tramp.
891See `tramp-file-name-structure-separate' for details.")
892
893(defcustom tramp-make-tramp-file-user-nil-format
894 (if (featurep 'xemacs)
895 tramp-make-tramp-file-user-nil-format-separate
896 tramp-make-tramp-file-user-nil-format-unified)
fb7933a3
KG
897 "*Format string saying how to construct tramp file name when the user name is not known.
898`%m' is replaced by the method name.
899`%h' is replaced by the host name.
900`%p' is replaced by the file name.
901`%%' is replaced by %.
902
903Also see `tramp-make-tramp-file-format', `tramp-file-name-structure', and `tramp-file-name-regexp'."
904 :group 'tramp
905 :type 'string)
906
505edaeb 907(defconst tramp-multi-file-name-structure-unified
b29019f8 908 (list (concat "\\`/\\(\\([a-zA-Z0-9]+\\)?:\\)" ;method
505edaeb 909 "\\(\\(%s\\)+\\)" ;hops
b29019f8 910 "\\(.*\\)\\'") ;path
505edaeb
KG
911 2 3 -1)
912 "Value for `tramp-multi-file-name-structure' for unified remoting.
913Emacs (not XEmacs) uses a unified filename syntax for Ange-FTP and Tramp.
914See `tramp-file-name-structure-unified' for details.")
915
90dc758d 916(defconst tramp-multi-file-name-structure-separate
fb7933a3
KG
917 (list (concat
918 ;; prefix
b29019f8 919 "\\`/\\[\\(\\([a-z0-9]+\\)?\\)"
487fa986 920 ;; regexp specifying the hops
fb7933a3
KG
921 "\\(\\(%s\\)+\\)"
922 ;; path name
923 "\\]\\(.*\\)\\'")
924 2 ;number of pair to match method
925 3 ;number of pair to match hops
926 -1) ;number of pair to match path
505edaeb
KG
927 "Value of `tramp-multi-file-name-structure' for separate remoting.
928XEmacs uses a separate filename syntax for EFS and Tramp.
929See `tramp-file-name-structure-separate' for details.")
930
931(defcustom tramp-multi-file-name-structure
932 (if (featurep 'xemacs)
933 tramp-multi-file-name-structure-separate
934 tramp-multi-file-name-structure-unified)
fb7933a3
KG
935 "*Describes the file name structure of `multi' files.
936Multi files allow you to contact a remote host in several hops.
937This is a list of four elements (REGEXP METHOD HOP PATH).
938
939The first element, REGEXP, gives a regular expression to match against
940the file name. In this regular expression, `%s' is replaced with the
941value of `tramp-multi-file-name-hop-structure'. (Note: in order to
942allow multiple hops, you normally want to use something like
943\"\\\\(\\\\(%s\\\\)+\\\\)\" in the regular expression. The outer pair
944of parentheses is used for the HOP element, see below.)
945
946All remaining elements are numbers. METHOD gives the number of the
947paren pair which matches the method name. HOP gives the number of the
948paren pair which matches the hop sequence. PATH gives the number of
949the paren pair which matches the path name on the remote host.
950
951PATH can also be negative, which means to count from the end. Ie, a
952value of -1 means the last paren pair.
953
954I think it would be good if the regexp matches the whole of the
955string, but I haven't actually tried what happens if it doesn't..."
956 :group 'tramp
957 :type '(list (regexp :tag "File name regexp")
958 (integer :tag "Paren pair for method name")
959 (integer :tag "Paren pair for hops")
960 (integer :tag "Paren pair to match path")))
961
505edaeb 962(defconst tramp-multi-file-name-hop-structure-unified
b29019f8 963 (list (concat "\\([a-zA-z0-9_]+\\):" ;hop method
505edaeb 964 "\\([^@:/]+\\)@" ;user
b29019f8 965 "\\([^:/]+\\):") ;host
505edaeb
KG
966 1 2 3)
967 "Value of `tramp-multi-file-name-hop-structure' for unified remoting.
968Emacs (not XEmacs) uses a unified filename syntax for Ange-FTP and Tramp.
969See `tramp-file-name-structure-unified' for details.")
970
971(defconst tramp-multi-file-name-hop-structure-separate
487fa986
KG
972 (list (concat "/\\([a-z0-9_]+\\):" ;hop method
973 "\\([a-z0-9_]+\\)@" ;user
974 "\\([a-z0-9.-]+\\)") ;host
fb7933a3 975 1 2 3)
505edaeb
KG
976 "Value of `tramp-multi-file-name-hop-structure' for separate remoting.
977XEmacs uses a separate filename syntax for EFS and Tramp.
978See `tramp-file-name-structure-separate' for details.")
979
980(defcustom tramp-multi-file-name-hop-structure
981 (if (featurep 'xemacs)
982 tramp-multi-file-name-hop-structure-separate
983 tramp-multi-file-name-hop-structure-unified)
fb7933a3
KG
984 "*Describes the structure of a hop in multi files.
985This is a list of four elements (REGEXP METHOD USER HOST). First
986element REGEXP is used to match against the hop. Pair number METHOD
987matches the method of one hop, pair number USER matches the user of
988one hop, pair number HOST matches the host of one hop.
989
990This regular expression should match exactly all of one hop."
991 :group 'tramp
992 :type '(list (regexp :tag "Hop regexp")
993 (integer :tag "Paren pair for method name")
994 (integer :tag "Paren pair for user name")
995 (integer :tag "Paren pair for host name")))
996
505edaeb
KG
997(defconst tramp-make-multi-tramp-file-format-unified
998 (list "/%m" ":%m:%u@%h" ":%p")
999 "Value of `tramp-make-multi-tramp-file-format' for unified remoting.
1000Emacs (not XEmacs) uses a unified filename syntax for Ange-FTP and Tramp.
1001See `tramp-file-name-structure-unified' for details.")
1002
1003(defconst tramp-make-multi-tramp-file-format-separate
fb7933a3 1004 (list "/[%m" "/%m:%u@%h" "]%p")
505edaeb
KG
1005 "Value of `tramp-make-multi-tramp-file-format' for separate remoting.
1006XEmacs uses a separate filename syntax for EFS and Tramp.
1007See `tramp-file-name-structure-separate' for details.")
1008
1009(defcustom tramp-make-multi-tramp-file-format
1010 (if (featurep 'xemacs)
1011 tramp-make-multi-tramp-file-format-separate
1012 tramp-make-multi-tramp-file-format-unified)
fb7933a3
KG
1013 "*Describes how to construct a `multi' file name.
1014This is a list of three elements PREFIX, HOP and PATH.
1015
1016The first element PREFIX says how to construct the prefix, the second
1017element HOP specifies what each hop looks like, and the final element
1018PATH says how to construct the path name.
1019
1020In PREFIX, `%%' means `%' and `%m' means the method name.
1021
1022In HOP, `%%' means `%' and `%m', `%u', `%h' mean the hop method, hop
1023user and hop host, respectively.
1024
1025In PATH, `%%' means `%' and `%p' means the path name.
1026
1027The resulting file name always contains one copy of PREFIX and one
1028copy of PATH, but there is one copy of HOP for each hop in the file
1029name.
1030
1031Note: the current implementation requires the prefix to contain the
1032method name, followed by all the hops, and the path name must come
1033last."
1034 :group 'tramp
1035 :type '(list string string string))
1036
1037(defcustom tramp-terminal-type "dumb"
1038 "*Value of TERM environment variable for logging in to remote host.
1039Because Tramp wants to parse the output of the remote shell, it is easily
1040confused by ANSI color escape sequences and suchlike. Often, shell init
1041files conditionalize this setup based on the TERM environment variable."
1042 :group 'tramp
1043 :type 'string)
1044
1045(defcustom tramp-completion-without-shell-p nil
1046 "*If nil, use shell wildcards for completion, else rely on Lisp only.
1047Using shell wildcards for completions has the advantage that it can be
1048fast even in large directories, but completion is always
1049case-sensitive. Relying on Lisp only means that case-insensitive
1050completion is possible (subject to the variable `completion-ignore-case'),
1051but it might be slow on large directories."
1052 :group 'tramp
1053 :type 'boolean)
1054
ac474af1
KG
1055(defcustom tramp-actions-before-shell
1056 '((tramp-password-prompt-regexp tramp-action-password)
1057 (tramp-login-prompt-regexp tramp-action-login)
1058 (shell-prompt-pattern tramp-action-succeed)
1059 (tramp-wrong-passwd-regexp tramp-action-permission-denied)
1060 (tramp-yesno-prompt-regexp tramp-action-yesno))
1061 "List of pattern/action pairs.
1062Whenever a pattern matches, the corresponding action is performed.
1063Each item looks like (PATTERN ACTION).
1064
1065The PATTERN should be a symbol, a variable. The value of this
1066variable gives the regular expression to search for. Note that the
1067regexp must match at the end of the buffer, \"\\'\" is implicitly
1068appended to it.
1069
1070The ACTION should also be a symbol, but a function. When the
1071corresponding PATTERN matches, the ACTION function is called."
1072 :group 'tramp
1073 :type '(repeat (list variable function)))
1074
1075(defcustom tramp-multi-actions
1076 '((tramp-password-prompt-regexp tramp-multi-action-password)
1077 (tramp-login-prompt-regexp tramp-multi-action-login)
1078 (shell-prompt-pattern tramp-multi-action-succeed)
1079 (tramp-wrong-passwd-regexp tramp-multi-action-permission-denied))
1080 "List of pattern/action pairs.
1081This list is used for each hop in multi-hop connections.
1082See `tramp-actions-before-shell' for more info."
1083 :group 'tramp
1084 :type '(repeat (list variable function)))
1085
fb7933a3
KG
1086;;; Internal Variables:
1087
1088(defvar tramp-buffer-file-attributes nil
1089 "Holds the `ls -ild' output for the current buffer.
1090This variable is local to each buffer. It is not used if the remote
1091machine groks Perl. If it is used, it's used as an emulation for
1092the visited file modtime.")
1093(make-variable-buffer-local 'tramp-buffer-file-attributes)
1094
1095(defvar tramp-end-of-output "/////"
1096 "String used to recognize end of output.")
1097
1098(defvar tramp-connection-function nil
1099 "This internal variable holds a parameter for `tramp-methods'.
1100In the connection buffer, this variable has the value of the like-named
1101method parameter, as specified in `tramp-methods' (which see).")
1102
1103(defvar tramp-remote-sh nil
1104 "This internal variable holds a parameter for `tramp-methods'.
1105In the connection buffer, this variable has the value of the like-named
1106method parameter, as specified in `tramp-methods' (which see).")
1107
1108(defvar tramp-rsh-program nil
1109 "This internal variable holds a parameter for `tramp-methods'.
1110In the connection buffer, this variable has the value of the like-named
1111method parameter, as specified in `tramp-methods' (which see).")
1112
1113(defvar tramp-rsh-args nil
1114 "This internal variable holds a parameter for `tramp-methods'.
1115In the connection buffer, this variable has the value of the like-named
1116method parameter, as specified in `tramp-methods' (which see).")
1117
1118(defvar tramp-rcp-program nil
1119 "This internal variable holds a parameter for `tramp-methods'.
1120In the connection buffer, this variable has the value of the like-named
1121method parameter, as specified in `tramp-methods' (which see).")
1122
1123(defvar tramp-rcp-args nil
1124 "This internal variable holds a parameter for `tramp-methods'.
1125In the connection buffer, this variable has the value of the like-named
1126method parameter, as specified in `tramp-methods' (which see).")
1127
1128(defvar tramp-rcp-keep-date-arg nil
1129 "This internal variable holds a parameter for `tramp-methods'.
1130In the connection buffer, this variable has the value of the like-named
1131method parameter, as specified in `tramp-methods' (which see).")
1132
1133(defvar tramp-encoding-command nil
1134 "This internal variable holds a parameter for `tramp-methods'.
1135In the connection buffer, this variable has the value of the like-named
1136method parameter, as specified in `tramp-methods' (which see).")
1137
1138(defvar tramp-decoding-command nil
1139 "This internal variable holds a parameter for `tramp-methods'.
1140In the connection buffer, this variable has the value of the like-named
1141method parameter, as specified in `tramp-methods' (which see).")
1142
1143(defvar tramp-encoding-function nil
1144 "This internal variable holds a parameter for `tramp-methods'.
1145In the connection buffer, this variable has the value of the like-named
1146method parameter, as specified in `tramp-methods' (which see).")
1147
1148(defvar tramp-decoding-function nil
1149 "This internal variable holds a parameter for `tramp-methods'.
1150In the connection buffer, this variable has the value of the like-named
1151method parameter, as specified in `tramp-methods' (which see).")
1152
1153(defvar tramp-telnet-program nil
1154 "This internal variable holds a parameter for `tramp-methods'.
1155In the connection buffer, this variable has the value of the like-named
1156method parameter, as specified in `tramp-methods' (which see).")
1157
1158(defvar tramp-telnet-args nil
1159 "This internal variable holds a parameter for `tramp-methods'.
1160In the connection buffer, this variable has the value of the like-named
1161method parameter, as specified in `tramp-methods' (which see).")
1162
b1d06e75
KG
1163(defvar tramp-su-program nil
1164 "This internal variable holds a parameter for `tramp-methods'.
1165In the connection buffer, this variable has the value of the like-named
1166method parameter, as specified in `tramp-methods' (which see).")
1167
fb7933a3
KG
1168;; CCC `local in each buffer'?
1169(defvar tramp-ls-command nil
1170 "This command is used to get a long listing with numeric user and group ids.
1171This variable is automatically made buffer-local to each rsh process buffer
1172upon opening the connection.")
1173
1174(defvar tramp-current-multi-method nil
1175 "Name of `multi' connection method for this *tramp* buffer, or nil if not multi.
1176This variable is automatically made buffer-local to each rsh process buffer
1177upon opening the connection.")
1178
1179(defvar tramp-current-method nil
1180 "Connection method for this *tramp* buffer.
1181This variable is automatically made buffer-local to each rsh process buffer
1182upon opening the connection.")
1183
1184(defvar tramp-current-user nil
1185 "Remote login name for this *tramp* buffer.
1186This variable is automatically made buffer-local to each rsh process buffer
1187upon opening the connection.")
1188
1189(defvar tramp-current-host nil
1190 "Remote host for this *tramp* buffer.
1191This variable is automatically made buffer-local to each rsh process buffer
1192upon opening the connection.")
1193
1194(defvar tramp-test-groks-nt nil
1195 "Whether the `test' command groks the `-nt' switch.
1196\(`test A -nt B' tests if file A is newer than file B.)
1197This variable is automatically made buffer-local to each rsh process buffer
1198upon opening the connection.")
1199
1200(defvar tramp-file-exists-command nil
1201 "Command to use for checking if a file exists.
1202This variable is automatically made buffer-local to each rsh process buffer
1203upon opening the connection.")
1204
fabf2143
KG
1205(defconst tramp-uudecode "\
1206tramp_uudecode () {
1207\(echo begin 600 /tmp/tramp.$$; tail +2) | uudecode
1208cat /tmp/tramp.$$
1209rm -f /tmp/tramp.$$
1210}"
1211 "Shell function to implement `uudecode' to standard output.
1212Many systems support `uudecode -o -' for this or `uudecode -p', but
1213some systems don't, and for them we have this shell function.")
1214
1215;; Perl script to implement `file-attributes' in a Lisp `read'able
1216;; output. If you are hacking on this, note that you get *no* output
1217;; unless this spits out a complete line, including the '\n' at the
1218;; end.
5beaf831
KG
1219(defconst tramp-perl-file-attributes "\
1220$f = $ARGV[0];
fb7933a3
KG
1221@s = lstat($f);
1222if (($s[2] & 0170000) == 0120000) { $l = readlink($f); $l = \"\\\"$l\\\"\"; }
1223elsif (($s[2] & 0170000) == 040000) { $l = \"t\"; }
1224else { $l = \"nil\" };
5beaf831 1225printf(\"(%s %u %d %d (%u %u) (%u %u) (%u %u) %u %u t (%u . %u) (%u %u))\\n\",
fb7933a3
KG
1226$l, $s[3], $s[4], $s[5], $s[8] >> 16 & 0xffff, $s[8] & 0xffff,
1227$s[9] >> 16 & 0xffff, $s[9] & 0xffff, $s[10] >> 16 & 0xffff, $s[10] & 0xffff,
1228$s[7], $s[2], $s[1] >> 16 & 0xffff, $s[1] & 0xffff, $s[0] >> 16 & 0xffff, $s[0] & 0xffff);"
fb7933a3
KG
1229 "Perl script to produce output suitable for use with `file-attributes'
1230on the remote file system.")
1231
ac474af1
KG
1232;; ;; These two use uu encoding.
1233;; (defvar tramp-perl-encode "%s -e'\
1234;; print qq(begin 644 xxx\n);
1235;; my $s = q();
1236;; my $res = q();
1237;; while (read(STDIN, $s, 45)) {
1238;; print pack(q(u), $s);
1239;; }
1240;; print qq(`\n);
1241;; print qq(end\n);
1242;; '"
1243;; "Perl program to use for encoding a file.
1244;; Escape sequence %s is replaced with name of Perl binary.")
1245
1246;; (defvar tramp-perl-decode "%s -ne '
1247;; print unpack q(u), $_;
1248;; '"
1249;; "Perl program to use for decoding a file.
1250;; Escape sequence %s is replaced with name of Perl binary.")
1251
1252;; These two use base64 encoding.
b1d06e75 1253(defvar tramp-perl-encode-with-module
ac474af1
KG
1254 "perl -MMIME::Base64 -0777 -ne 'print encode_base64($_)'"
1255 "Perl program to use for encoding a file.
b1d06e75 1256Escape sequence %s is replaced with name of Perl binary.
89509ea0 1257This string is passed to `format', so percent characters need to be doubled.
b1d06e75
KG
1258This implementation requires the MIME::Base64 Perl module to be installed
1259on the remote host.")
1260
1261(defvar tramp-perl-decode-with-module
1262 "perl -MMIME::Base64 -0777 -ne 'print decode_base64($_)'"
1263 "Perl program to use for decoding a file.
1264Escape sequence %s is replaced with name of Perl binary.
89509ea0 1265This string is passed to `format', so percent characters need to be doubled.
b1d06e75
KG
1266This implementation requires the MIME::Base64 Perl module to be installed
1267on the remote host.")
1268
1269(defvar tramp-perl-encode
1270 "%s -e '
1271# This script contributed by Juanma Barranquero <lektu@terra.es>.
1272# Copyright (C) 2002 Free Software Foundation, Inc.
1273use strict;
1274
fa32e96a 1275my %%trans = do {
b1d06e75
KG
1276 my $i = 0;
1277 map {(substr(unpack(q(B8), chr $i++), 2, 6), $_)}
1278 split //, q(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/);
1279};
1280
36541701 1281binmode(\\*STDIN);
b1d06e75
KG
1282
1283# We read in chunks of 54 bytes, to generate output lines
1284# of 72 chars (plus end of line)
36541701 1285$/ = \\54;
b1d06e75
KG
1286
1287while (my $data = <STDIN>) {
1288 my $pad = q();
1289
1290 # Only for the last chunk, and only if did not fill the last three-byte packet
1291 if (eof) {
fa32e96a 1292 my $mod = length($data) %% 3;
b1d06e75
KG
1293 $pad = q(=) x (3 - $mod) if $mod;
1294 }
1295
1296 # Not the fastest method, but it is simple: unpack to binary string, split
1297 # by groups of 6 bits and convert back from binary to byte; then map into
1298 # the translation table
1299 print
1300 join q(),
1301 map($trans{$_},
1302 (substr(unpack(q(B*), $data) . q(00000), 0, 432) =~ /....../g)),
1303 $pad,
36541701 1304 qq(\\n);
b1d06e75
KG
1305}
1306'"
1307 "Perl program to use for encoding a file.
fa32e96a 1308Escape sequence %s is replaced with name of Perl binary.
ccf29586 1309This string is passed to `format', so percent characters need to be doubled.")
ac474af1
KG
1310
1311(defvar tramp-perl-decode
b1d06e75
KG
1312 "%s -e '
1313# This script contributed by Juanma Barranquero <lektu@terra.es>.
1314# Copyright (C) 2002 Free Software Foundation, Inc.
1315use strict;
1316
fa32e96a 1317my %%trans = do {
b1d06e75 1318 my $i = 0;
fa32e96a 1319 map {($_, sprintf(q(%%06b), $i++))}
b1d06e75
KG
1320 split //, q(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/)
1321};
1322
fa32e96a 1323my %%bytes = map {(unpack(q(B8), chr $_), chr $_)} 0 .. 255;
b1d06e75 1324
36541701 1325binmode(\\*STDOUT);
b1d06e75
KG
1326
1327# We are going to accumulate into $pending to accept any line length
1328# (we do not check they are <= 76 chars as the RFC says)
1329my $pending = q();
1330
1331while (my $data = <STDIN>) {
1332 chomp $data;
1333
1334 # If we find one or two =, we have reached the end and
1335 # any following data is to be discarded
1336 my $finished = $data =~ s/(==?).*/$1/;
1337 $pending .= $data;
1338
1339 my $len = length($pending);
1340 my $chunk = substr($pending, 0, $len & ~3, q());
1341
1342 # Easy method: translate from chars to (pregenerated) six-bit packets, join,
1343 # split in 8-bit chunks and convert back to char.
1344 print join q(),
1345 map $bytes{$_},
1346 ((join q(), map {$trans{$_} || q()} split //, $chunk) =~ /......../g);
1347
1348 last if $finished;
1349}
1350'"
ac474af1 1351 "Perl program to use for decoding a file.
fa32e96a 1352Escape sequence %s is replaced with name of Perl binary.
ccf29586 1353This string is passed to `format', so percent characters need to be doubled.")
fb7933a3
KG
1354
1355; These values conform to `file-attributes' from XEmacs 21.2.
1356; GNU Emacs and other tools not checked.
1357(defconst tramp-file-mode-type-map '((0 . "-") ; Normal file (SVID-v2 and XPG2)
1358 (1 . "p") ; fifo
1359 (2 . "c") ; character device
1360 (3 . "m") ; multiplexed character device (v7)
1361 (4 . "d") ; directory
1362 (5 . "?") ; Named special file (XENIX)
1363 (6 . "b") ; block device
1364 (7 . "?") ; multiplexed block device (v7)
1365 (8 . "-") ; regular file
1366 (9 . "n") ; network special file (HP-UX)
1367 (10 . "l") ; symlink
1368 (11 . "?") ; ACL shadow inode (Solaris, not userspace)
1369 (12 . "s") ; socket
1370 (13 . "D") ; door special (Solaris)
1371 (14 . "w")) ; whiteout (BSD)
1372 "A list of file types returned from the `stat' system call.
1373This is used to map a mode number to a permission string.")
1374
1375(defvar tramp-dos-coding-system
1376 (if (and (fboundp 'coding-system-p)
1377 (funcall 'coding-system-p '(dos)))
1378 'dos
1379 'undecided-dos)
1380 "Some Emacsen know the `dos' coding system, others need `undecided-dos'.")
1381
ac474af1
KG
1382(defvar tramp-last-cmd-time nil
1383 "Internal Tramp variable recording the time when the last cmd was sent.
1384This variable is buffer-local in every buffer.")
1385(make-variable-buffer-local 'tramp-last-cmd-time)
fb7933a3
KG
1386
1387;; New handlers should be added here. The following operations can be
1388;; handled using the normal primitives: file-name-as-directory,
1389;; file-name-directory, file-name-nondirectory,
1390;; file-name-sans-versions, get-file-buffer.
1391(defconst tramp-file-name-handler-alist
1392 '(
1393 (load . tramp-handle-load)
1394 (make-symbolic-link . tramp-handle-make-symbolic-link)
1395 (file-name-directory . tramp-handle-file-name-directory)
1396 (file-name-nondirectory . tramp-handle-file-name-nondirectory)
1397 (file-truename . tramp-handle-file-truename)
1398 (file-exists-p . tramp-handle-file-exists-p)
1399 (file-directory-p . tramp-handle-file-directory-p)
1400 (file-executable-p . tramp-handle-file-executable-p)
1401 (file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
1402 (file-readable-p . tramp-handle-file-readable-p)
1403 (file-regular-p . tramp-handle-file-regular-p)
1404 (file-symlink-p . tramp-handle-file-symlink-p)
1405 (file-writable-p . tramp-handle-file-writable-p)
1406 (file-ownership-preserved-p . tramp-handle-file-ownership-preserved-p)
1407 (file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
1408 (file-attributes . tramp-handle-file-attributes)
1409 (file-modes . tramp-handle-file-modes)
1410 (file-directory-files . tramp-handle-file-directory-files)
1411 (directory-files . tramp-handle-directory-files)
1412 (file-name-all-completions . tramp-handle-file-name-all-completions)
1413 (file-name-completion . tramp-handle-file-name-completion)
1414 (add-name-to-file . tramp-handle-add-name-to-file)
1415 (copy-file . tramp-handle-copy-file)
1416 (rename-file . tramp-handle-rename-file)
1417 (set-file-modes . tramp-handle-set-file-modes)
1418 (make-directory . tramp-handle-make-directory)
1419 (delete-directory . tramp-handle-delete-directory)
1420 (delete-file . tramp-handle-delete-file)
1421 (directory-file-name . tramp-handle-directory-file-name)
1422 (shell-command . tramp-handle-shell-command)
1423 (insert-directory . tramp-handle-insert-directory)
1424 (expand-file-name . tramp-handle-expand-file-name)
1425 (file-local-copy . tramp-handle-file-local-copy)
1426 (insert-file-contents . tramp-handle-insert-file-contents)
1427 (write-region . tramp-handle-write-region)
1428 (unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory)
1429 (dired-call-process . tramp-handle-dired-call-process)
1430 (dired-recursive-delete-directory
1431 . tramp-handle-dired-recursive-delete-directory)
1432 (set-visited-file-modtime . tramp-handle-set-visited-file-modtime)
1433 (verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime))
1434 "Alist of handler functions.
1435Operations not mentioned here will be handled by the normal Emacs functions.")
1436
fb7933a3
KG
1437;;; Internal functions which must come first.
1438
1439(defsubst tramp-message (level fmt-string &rest args)
1440 "Emit a message depending on verbosity level.
1441First arg LEVEL says to be quiet if `tramp-verbose' is less than LEVEL. The
1442message is emitted only if `tramp-verbose' is greater than or equal to LEVEL.
1443Calls function `message' with FMT-STRING as control string and the remaining
1444ARGS to actually emit the message (if applicable).
1445
1446This function expects to be called from the tramp buffer only!"
1447 (when (<= level tramp-verbose)
1448 (apply #'message (concat "tramp: " fmt-string) args)
1449 (when tramp-debug-buffer
1450 (save-excursion
1451 (set-buffer
1452 (tramp-get-debug-buffer
1453 tramp-current-multi-method tramp-current-method
1454 tramp-current-user tramp-current-host))
1455 (goto-char (point-max))
1456 (tramp-insert-with-face
1457 'italic
1458 (concat "# " (apply #'format fmt-string args) "\n"))))))
1459
1460(defun tramp-message-for-buffer
1461 (multi-method method user host level fmt-string &rest args)
1462 "Like `tramp-message' but temporarily switches to the tramp buffer.
1463First three args METHOD, USER, and HOST identify the tramp buffer to use,
1464remaining args passed to `tramp-message'."
1465 (save-excursion
1466 (set-buffer (tramp-get-buffer multi-method method user host))
1467 (apply 'tramp-message level fmt-string args)))
1468
1469(defsubst tramp-line-end-position nil
1470 "Return point at end of line.
1471Calls `line-end-position' or `point-at-eol' if defined, else
1472own implementation."
1473 (cond
1474 ((fboundp 'line-end-position) (funcall 'line-end-position))
1475 ((fboundp 'point-at-eol) (funcall 'point-at-eol))
1476 (t (save-excursion (end-of-line) (point)))))
1477
c62c9d08
KG
1478(defmacro with-parsed-tramp-file-name (filename var &rest body)
1479 "Parse a Tramp filename and make components available in the body.
1480
1481First arg FILENAME is evaluated and dissected into its components.
1482Second arg VAR is a symbol. It is used as a variable name to hold
1483the filename structure. It is also used as a prefix for the variables
1484holding the components. For example, if VAR is the symbol `foo', then
1485`foo' will be bound to the whole structure, `foo-multi-method' will
1486be bound to the multi-method component, and so on for `foo-method',
1487`foo-user', `foo-host', `foo-path'.
1488
1489Remaining args are Lisp expressions to be evaluated (inside an implicit
1490`progn').
1491
1492If VAR is nil, then we bind `v' to the structure and `multi-method',
1493`method', `user', `host', `path' to the components."
1494 `(let* ((,(or var 'v) (tramp-dissect-file-name ,filename))
1495 (,(if var (intern (concat (symbol-name var) "-multi-method")) 'multi-method)
1496 (tramp-file-name-multi-method ,(or var 'v)))
1497 (,(if var (intern (concat (symbol-name var) "-method")) 'method)
1498 (tramp-file-name-method ,(or var 'v)))
1499 (,(if var (intern (concat (symbol-name var) "-user")) 'user)
1500 (tramp-file-name-user ,(or var 'v)))
1501 (,(if var (intern (concat (symbol-name var) "-host")) 'host)
1502 (tramp-file-name-host ,(or var 'v)))
1503 (,(if var (intern (concat (symbol-name var) "-path")) 'path)
1504 (tramp-file-name-path ,(or var 'v))))
1505 ,@body))
1506
1507(put 'with-parsed-tramp-file-name 'lisp-indent-function 2)
1508
fb7933a3
KG
1509;;; File Name Handler Functions:
1510
fb7933a3
KG
1511(defun tramp-handle-make-symbolic-link
1512 (filename linkname &optional ok-if-already-exists)
1513 "Like `make-symbolic-link' for tramp files.
cebb4ec6
KG
1514If LINKNAME is a non-Tramp file, it is used verbatim as the target of
1515the symlink. If LINKNAME is a Tramp file, only the path component is
1516used as the target of the symlink.
1517
1518If LINKNAME is a Tramp file and the path component is relative, then
1519it is expanded first, before the path component is taken. Note that
1520this can give surprising results if the user/host for the source and
1521target of the symlink differ."
c62c9d08
KG
1522 (with-parsed-tramp-file-name linkname l
1523 (when (tramp-ange-ftp-file-name-p l-multi-method l-method)
1524 (tramp-invoke-ange-ftp 'make-symbolic-link
1525 filename linkname ok-if-already-exists))
487fa986 1526 (let ((ln (tramp-get-remote-ln l-multi-method l-method l-user l-host))
c62c9d08
KG
1527 (cwd (file-name-directory l-path)))
1528 (unless ln
1529 (signal 'file-error
1530 (list "Making a symbolic link."
1531 "ln(1) does not exist on the remote host.")))
1532
1533 ;; Do the 'confirm if exists' thing.
cebb4ec6 1534 (when (file-exists-p linkname)
c62c9d08
KG
1535 ;; What to do?
1536 (if (or (null ok-if-already-exists) ; not allowed to exist
1537 (and (numberp ok-if-already-exists)
1538 (not (yes-or-no-p
1539 (format
1540 "File %s already exists; make it a link anyway? "
1541 l-path)))))
cebb4ec6
KG
1542 (signal 'file-already-exists (list "File already exists" l-path))
1543 (delete-file linkname)))
1544
1545 ;; If FILENAME is a Tramp name, use just the path component.
1546 (when (tramp-tramp-file-p filename)
1547 (setq filename (tramp-file-name-path
1548 (tramp-dissect-file-name
1549 (expand-file-name filename)))))
fb7933a3 1550
c62c9d08
KG
1551 ;; Right, they are on the same host, regardless of user, method, etc.
1552 ;; We now make the link on the remote machine. This will occur as the user
1553 ;; that FILENAME belongs to.
1554 (zerop
1555 (tramp-send-command-and-check
487fa986 1556 l-multi-method l-method l-user l-host
c62c9d08
KG
1557 (format "cd %s && %s -sf %s %s"
1558 cwd ln
cebb4ec6
KG
1559 filename
1560 l-path)
c62c9d08 1561 t)))))
fb7933a3
KG
1562
1563
1564(defun tramp-handle-load (file &optional noerror nomessage nosuffix must-suffix)
1565 "Like `load' for tramp files. Not implemented!"
1566 (unless (file-name-absolute-p file)
1567 (error "Tramp cannot `load' files without absolute path name"))
c62c9d08
KG
1568 (with-parsed-tramp-file-name file nil
1569 (when (tramp-ange-ftp-file-name-p multi-method method)
1570 (tramp-invoke-ange-ftp 'load
1571 file noerror nomessage nosuffix must-suffix))
1572 (unless nosuffix
1573 (cond ((file-exists-p (concat file ".elc"))
1574 (setq file (concat file ".elc")))
1575 ((file-exists-p (concat file ".el"))
1576 (setq file (concat file ".el")))))
1577 (when must-suffix
1578 ;; The first condition is always true for absolute file names.
1579 ;; Included for safety's sake.
1580 (unless (or (file-name-directory file)
1581 (string-match "\\.elc?\\'" file))
1582 (error "File `%s' does not include a `.el' or `.elc' suffix"
1583 file)))
1584 (unless noerror
1585 (when (not (file-exists-p file))
1586 (error "Cannot load nonexistant file `%s'" file)))
1587 (if (not (file-exists-p file))
1588 nil
1589 (unless nomessage
1590 (message "Loading %s..." file))
1591 (let ((local-copy (file-local-copy file)))
1592 ;; MUST-SUFFIX doesn't exist on XEmacs, so let it default to nil.
1593 (load local-copy noerror t t)
1594 (delete-file local-copy))
1595 (unless nomessage
1596 (message "Loading %s...done" file))
1597 t)))
fb7933a3
KG
1598
1599;; Path manipulation functions that grok TRAMP paths...
1600(defun tramp-handle-file-name-directory (file)
1601 "Like `file-name-directory' but aware of TRAMP files."
1602 ;; everything except the last filename thing is the directory
c62c9d08
KG
1603 (with-parsed-tramp-file-name file nil
1604 (when (tramp-ange-ftp-file-name-p multi-method method)
1605 (tramp-invoke-ange-ftp 'file-name-directory file))
505edaeb
KG
1606 ;; For the following condition, two possibilities should be tried:
1607 ;; (1) (string= path "")
1608 ;; (2) (or (string= path "") (string= path "/"))
1609 ;; The second variant fails when completing a "/" directory on
1610 ;; the remote host, that is a filename which looks like
1611 ;; "/user@host:/". But maybe wildcards fail with the first variant.
1612 ;; We should do some investigation.
1613 (if (string= path "")
fb7933a3
KG
1614 ;; For a filename like "/[foo]", we return "/". The `else'
1615 ;; case would return "/[foo]" unchanged. But if we do that,
1616 ;; then `file-expand-wildcards' ceases to work. It's not
1617 ;; quite clear to me what's the intuition that tells that this
1618 ;; behavior is the right behavior, but oh, well.
1619 "/"
1620 ;; run the command on the path portion only
1621 ;; CCC: This should take into account the remote machine type, no?
1622 ;; --daniel <daniel@danann.net>
1623 (tramp-make-tramp-file-name multi-method method user host
1624 ;; This will not recurse...
1625 (or (file-name-directory path) "")))))
1626
1627(defun tramp-handle-file-name-nondirectory (file)
1628 "Like `file-name-nondirectory' but aware of TRAMP files."
c62c9d08
KG
1629 (with-parsed-tramp-file-name file nil
1630 (when (tramp-ange-ftp-file-name-p multi-method method)
1631 (tramp-invoke-ange-ftp 'file-name-nondirectory file))
1632 (file-name-nondirectory path)))
fb7933a3
KG
1633
1634(defun tramp-handle-file-truename (filename &optional counter prev-dirs)
1635 "Like `file-truename' for tramp files."
c62c9d08 1636 (with-parsed-tramp-file-name filename nil
b1d06e75
KG
1637 ;; Ange-FTP does not support truename processing, but for
1638 ;; convenience we pretend it did and forward the call to Ange-FTP
1639 ;; anyway. Ange-FTP then just invokes `identity'.
c62c9d08 1640 (when (tramp-ange-ftp-file-name-p multi-method method)
b1d06e75 1641 (tramp-invoke-ange-ftp 'file-truename filename))
c62c9d08
KG
1642 (let* ((steps (tramp-split-string path "/"))
1643 (pathdir (let ((directory-sep-char ?/))
1644 (file-name-as-directory path)))
1645 (is-dir (string= path pathdir))
1646 (thisstep nil)
1647 (numchase 0)
1648 ;; Don't make the following value larger than necessary.
1649 ;; People expect an error message in a timely fashion when
1650 ;; something is wrong; otherwise they might think that Emacs
1651 ;; is hung. Of course, correctness has to come first.
1652 (numchase-limit 20)
1653 (result nil) ;result steps in reverse order
1654 (curstri "")
1655 symlink-target)
fb7933a3
KG
1656 (tramp-message-for-buffer
1657 multi-method method user host
c62c9d08
KG
1658 10 "Finding true name for `%s'" filename)
1659 (while (and steps (< numchase numchase-limit))
1660 (setq thisstep (pop steps))
1661 (tramp-message-for-buffer
1662 multi-method method user host
1663 10 "Check %s"
1664 (mapconcat 'identity
1665 (append '("") (reverse result) (list thisstep))
1666 "/"))
1667 (setq symlink-target
1668 (nth 0 (tramp-handle-file-attributes
1669 (tramp-make-tramp-file-name
1670 multi-method method user host
1671 (mapconcat 'identity
b1d06e75
KG
1672 (append '("")
1673 (reverse result)
1674 (list thisstep))
c62c9d08
KG
1675 "/")))))
1676 (cond ((string= "." thisstep)
1677 (tramp-message-for-buffer multi-method method user host
1678 10 "Ignoring step `.'"))
1679 ((string= ".." thisstep)
1680 (tramp-message-for-buffer multi-method method user host
1681 10 "Processing step `..'")
1682 (pop result))
1683 ((stringp symlink-target)
1684 ;; It's a symlink, follow it.
1685 (tramp-message-for-buffer
1686 multi-method method user host
1687 10 "Follow symlink to %s" symlink-target)
1688 (setq numchase (1+ numchase))
1689 (when (file-name-absolute-p symlink-target)
1690 (setq result nil))
1691 (setq steps
1692 (append (tramp-split-string symlink-target "/") steps)))
1693 (t
1694 ;; It's a file.
1695 (setq result (cons thisstep result)))))
1696 (when (>= numchase numchase-limit)
1697 (error "Maximum number (%d) of symlinks exceeded" numchase-limit))
1698 (setq result (reverse result))
1699 (tramp-message-for-buffer
1700 multi-method method user host
1701 10 "True name of `%s' is `%s'"
1702 filename (mapconcat 'identity (cons "" result) "/"))
1703 (tramp-make-tramp-file-name
1704 multi-method method user host
1705 (concat (mapconcat 'identity (cons "" result) "/")
1706 (if is-dir "/" ""))))))
fb7933a3
KG
1707
1708;; Basic functions.
1709
1710(defun tramp-handle-file-exists-p (filename)
1711 "Like `file-exists-p' for tramp files."
c62c9d08
KG
1712 (with-parsed-tramp-file-name filename nil
1713 (when (tramp-ange-ftp-file-name-p multi-method method)
1714 (tramp-invoke-ange-ftp 'file-exists-p filename))
fb7933a3
KG
1715 (save-excursion
1716 (zerop (tramp-send-command-and-check
1717 multi-method method user host
1718 (format
c62c9d08
KG
1719 (tramp-get-file-exists-command multi-method method user host)
1720 (tramp-shell-quote-argument path)))))))
fb7933a3
KG
1721
1722;; CCC: This should check for an error condition and signal failure
1723;; when something goes wrong.
1724;; Daniel Pittman <daniel@danann.net>
1725(defun tramp-handle-file-attributes (filename &optional nonnumeric)
1726 "Like `file-attributes' for tramp files.
1727Optional argument NONNUMERIC means return user and group name
1728rather than as numbers."
ac474af1
KG
1729 (let (result)
1730 (with-parsed-tramp-file-name filename nil
1731 (when (tramp-ange-ftp-file-name-p multi-method method)
1732 (tramp-invoke-ange-ftp 'file-attributes filename))
1733 (when (tramp-handle-file-exists-p filename)
1734 ;; file exists, find out stuff
1735 (save-excursion
fb7933a3 1736 (if (tramp-get-remote-perl multi-method method user host)
ac474af1
KG
1737 (setq result
1738 (tramp-handle-file-attributes-with-perl
1739 multi-method method user host path nonnumeric))
1740 (setq result
1741 (tramp-handle-file-attributes-with-ls
1742 multi-method method user host path nonnumeric))))))
1743 result))
fb7933a3
KG
1744
1745
1746(defun tramp-handle-file-attributes-with-ls
1747 (multi-method method user host path &optional nonnumeric)
1748 "Implement `file-attributes' for tramp files using the ls(1) command."
1749 (let (symlinkp dirp
1750 res-inode res-filemodes res-numlinks
1751 res-uid res-gid res-size res-symlink-target)
ac474af1
KG
1752 (tramp-message-for-buffer multi-method method user host 10
1753 "file attributes with ls: %s"
1754 (tramp-make-tramp-file-name
1755 multi-method method user host path))
fb7933a3
KG
1756 (tramp-send-command
1757 multi-method method user host
1758 (format "%s %s %s"
1759 (tramp-get-ls-command multi-method method user host)
1760 (if nonnumeric "-ild" "-ildn")
1761 (tramp-shell-quote-argument path)))
1762 (tramp-wait-for-output)
1763 ;; parse `ls -l' output ...
1764 ;; ... inode
1765 (setq res-inode
1766 (condition-case err
1767 (read (current-buffer))
1768 (invalid-read-syntax
1769 (when (and (equal (cadr err)
1770 "Integer constant overflow in reader")
1771 (string-match
1772 "^[0-9]+\\([0-9][0-9][0-9][0-9][0-9]\\)\\'"
1773 (caddr err)))
1774 (let* ((big (read (substring (caddr err) 0
1775 (match-beginning 1))))
1776 (small (read (match-string 1 (caddr err))))
1777 (twiddle (/ small 65536)))
1778 (cons (+ big twiddle)
1779 (- small (* twiddle 65536))))))))
1780 ;; ... file mode flags
1781 (setq res-filemodes (symbol-name (read (current-buffer))))
1782 ;; ... number links
1783 (setq res-numlinks (read (current-buffer)))
1784 ;; ... uid and gid
1785 (setq res-uid (read (current-buffer)))
1786 (setq res-gid (read (current-buffer)))
1787 (unless nonnumeric
1788 (unless (numberp res-uid) (setq res-uid -1))
1789 (unless (numberp res-gid) (setq res-gid -1)))
1790 ;; ... size
1791 (setq res-size (read (current-buffer)))
1792 ;; From the file modes, figure out other stuff.
1793 (setq symlinkp (eq ?l (aref res-filemodes 0)))
1794 (setq dirp (eq ?d (aref res-filemodes 0)))
1795 ;; if symlink, find out file name pointed to
1796 (when symlinkp
1797 (search-forward "-> ")
1798 (setq res-symlink-target
1799 (buffer-substring (point)
1800 (tramp-line-end-position))))
1801 ;; return data gathered
1802 (list
1803 ;; 0. t for directory, string (name linked to) for symbolic
1804 ;; link, or nil.
1805 (or dirp res-symlink-target nil)
1806 ;; 1. Number of links to file.
1807 res-numlinks
1808 ;; 2. File uid.
1809 res-uid
1810 ;; 3. File gid.
1811 res-gid
1812 ;; 4. Last access time, as a list of two integers. First
1813 ;; integer has high-order 16 bits of time, second has low 16
1814 ;; bits.
1815 ;; 5. Last modification time, likewise.
1816 ;; 6. Last status change time, likewise.
1817 '(0 0) '(0 0) '(0 0) ;CCC how to find out?
1818 ;; 7. Size in bytes (-1, if number is out of range).
1819 res-size
1820 ;; 8. File modes, as a string of ten letters or dashes as in ls -l.
1821 res-filemodes
1822 ;; 9. t iff file's gid would change if file were deleted and
1823 ;; recreated.
1824 nil ;hm?
1825 ;; 10. inode number.
1826 res-inode
1827 ;; 11. Device number.
1828 -1 ;hm?
1829 )))
1830
1831(defun tramp-handle-file-attributes-with-perl
1832 (multi-method method user host path &optional nonnumeric)
1833 "Implement `file-attributes' for tramp files using a Perl script.
1834
1835The Perl command is sent to the remote machine when the connection
1836is initially created and is kept cached by the remote shell."
ac474af1
KG
1837 (tramp-message-for-buffer multi-method method user host 10
1838 "file attributes with perl: %s"
1839 (tramp-make-tramp-file-name
1840 multi-method method user host path))
fb7933a3
KG
1841 (tramp-send-command
1842 multi-method method user host
1843 (format "tramp_file_attributes %s"
1844 (tramp-shell-quote-argument path)))
1845 (tramp-wait-for-output)
1846 (let ((result (read (current-buffer))))
1847 (setcar (nthcdr 8 result)
1848 (tramp-file-mode-from-int (nth 8 result)))
1849 result))
1850
1851(defun tramp-handle-set-visited-file-modtime (&optional time-list)
1852 "Like `set-visited-file-modtime' for tramp files."
1853 (unless (buffer-file-name)
1854 (error "Can't set-visited-file-modtime: buffer `%s' not visiting a file"
1855 (buffer-name)))
1856 (when time-list
1857 (tramp-run-real-handler 'set-visited-file-modtime (list time-list)))
c62c9d08
KG
1858 (let ((f (buffer-file-name))
1859 (coding-system-used nil))
1860 (with-parsed-tramp-file-name f nil
b1d06e75
KG
1861 ;; This operation is not handled by Ange-FTP! Compare this
1862 ;; behavior with `file-truename' which Ange-FTP does not really
1863 ;; handle, either, but at least it pretends to. I wonder if
1864 ;; Ange-FTP should also pretend to grok
1865 ;; `set-visited-file-modtime', for consistency?
c62c9d08
KG
1866 (when (tramp-ange-ftp-file-name-p multi-method method)
1867 (throw 'tramp-forward-to-ange-ftp
1868 (tramp-run-real-handler 'set-visited-file-modtime
1869 (list time-list))))
1870 (let* ((attr (file-attributes f))
1871 (modtime (nth 5 attr)))
1872 ;; We use '(0 0) as a don't-know value. See also
1873 ;; `tramp-handle-file-attributes-with-ls'.
1874 (when (boundp 'last-coding-system-used)
1875 (setq coding-system-used last-coding-system-used))
fb7933a3 1876 (if (not (equal modtime '(0 0)))
c62c9d08 1877 (tramp-run-real-handler 'set-visited-file-modtime (list modtime))
fb7933a3
KG
1878 (save-excursion
1879 (tramp-send-command
1880 multi-method method user host
1881 (format "%s -ild %s"
1882 (tramp-get-ls-command multi-method method user host)
1883 (tramp-shell-quote-argument path)))
1884 (tramp-wait-for-output)
1885 (setq attr (buffer-substring (point)
1886 (progn (end-of-line) (point)))))
c62c9d08
KG
1887 (setq tramp-buffer-file-attributes attr))
1888 (when (boundp 'last-coding-system-used)
1889 (setq last-coding-system-used coding-system-used))
fb7933a3
KG
1890 nil))))
1891
c62c9d08
KG
1892;; CCC continue here
1893
1894;; This function makes the same assumption as
1895;; `tramp-handle-set-visited-file-modtime'.
1896(defun tramp-handle-verify-visited-file-modtime (buf)
1897 "Like `verify-visited-file-modtime' for tramp files."
1898 (with-current-buffer buf
1899 (let ((f (buffer-file-name)))
1900 (with-parsed-tramp-file-name f nil
487fa986 1901 (when (tramp-ange-ftp-file-name-p multi-method method)
c62c9d08
KG
1902 ;; This one requires a hack since the file name is not passed
1903 ;; on the arg list.
1904 (let ((buffer-file-name (tramp-make-ange-ftp-file-name
1905 user host path)))
1906 (tramp-invoke-ange-ftp 'verify-visited-file-modtime buf)))
1907 (let* ((attr (file-attributes f))
1908 (modtime (nth 5 attr)))
1909 (cond ((and attr (not (equal modtime '(0 0))))
1910 ;; Why does `file-attributes' return a list (HIGH
1911 ;; LOW), but `visited-file-modtime' returns a cons
1912 ;; (HIGH . LOW)?
1913 (let ((mt (visited-file-modtime)))
1914 (< (abs (tramp-time-diff
1915 modtime (list (car mt) (cdr mt)))) 2)))
1916 (attr
1917 (save-excursion
1918 (tramp-send-command
1919 multi-method method user host
1920 (format "%s -ild %s"
1921 (tramp-get-ls-command multi-method method
1922 user host)
1923 (tramp-shell-quote-argument path)))
1924 (tramp-wait-for-output)
1925 (setq attr (buffer-substring
1926 (point) (progn (end-of-line) (point)))))
1927 (equal tramp-buffer-file-attributes attr))
1928 ;; If file does not exist, say it is not modified.
487fa986 1929 (t nil)))))))
c62c9d08 1930
fb7933a3
KG
1931(defadvice clear-visited-file-modtime (after tramp activate)
1932 "Set `tramp-buffer-file-attributes' back to nil.
1933Tramp uses this variable as an emulation for the actual modtime of the file,
1934if the remote host can't provide the modtime."
1935 (setq tramp-buffer-file-attributes nil))
1936
1937(defun tramp-handle-set-file-modes (filename mode)
1938 "Like `set-file-modes' for tramp files."
c62c9d08
KG
1939 (with-parsed-tramp-file-name filename nil
1940 (when (tramp-ange-ftp-file-name-p multi-method method)
1941 (tramp-invoke-ange-ftp 'set-file-modes filename mode))
fb7933a3
KG
1942 (save-excursion
1943 (unless (zerop (tramp-send-command-and-check
c62c9d08
KG
1944 multi-method method user host
1945 (format "chmod %s %s"
1946 (tramp-decimal-to-octal mode)
1947 (tramp-shell-quote-argument path))))
fb7933a3
KG
1948 (signal 'file-error
1949 (list "Doing chmod"
1950 ;; FIXME: extract the proper text from chmod's stderr.
1951 "error while changing file's mode"
1952 filename))))))
1953
1954;; Simple functions using the `test' command.
1955
1956(defun tramp-handle-file-executable-p (filename)
1957 "Like `file-executable-p' for tramp files."
c62c9d08
KG
1958 (with-parsed-tramp-file-name filename nil
1959 (when (tramp-ange-ftp-file-name-p multi-method method)
1960 (tramp-invoke-ange-ftp 'file-executable-p filename))
1961 (zerop (tramp-run-test "-x" filename))))
fb7933a3
KG
1962
1963(defun tramp-handle-file-readable-p (filename)
1964 "Like `file-readable-p' for tramp files."
c62c9d08
KG
1965 (with-parsed-tramp-file-name filename nil
1966 (when (tramp-ange-ftp-file-name-p multi-method method)
1967 (tramp-invoke-ange-ftp 'file-readable-p filename))
1968 (zerop (tramp-run-test "-r" filename))))
fb7933a3
KG
1969
1970(defun tramp-handle-file-accessible-directory-p (filename)
1971 "Like `file-accessible-directory-p' for tramp files."
c62c9d08
KG
1972 (with-parsed-tramp-file-name filename nil
1973 (when (tramp-ange-ftp-file-name-p multi-method method)
1974 (tramp-invoke-ange-ftp 'file-accessible-directory-p filename))
1975 (and (zerop (tramp-run-test "-d" filename))
1976 (zerop (tramp-run-test "-r" filename))
1977 (zerop (tramp-run-test "-x" filename)))))
fb7933a3
KG
1978
1979;; When the remote shell is started, it looks for a shell which groks
1980;; tilde expansion. Here, we assume that all shells which grok tilde
1981;; expansion will also provide a `test' command which groks `-nt' (for
1982;; newer than). If this breaks, tell me about it and I'll try to do
1983;; something smarter about it.
1984(defun tramp-handle-file-newer-than-file-p (file1 file2)
1985 "Like `file-newer-than-file-p' for tramp files."
1986 (cond ((not (file-exists-p file1))
1987 nil)
1988 ((not (file-exists-p file2))
1989 t)
c62c9d08
KG
1990 ;; We are sure both files exist at this point. We assume that
1991 ;; both files are Tramp files, otherwise we issue an error
1992 ;; message. Todo: make a better error message.
fb7933a3
KG
1993 (t
1994 (save-excursion
c62c9d08
KG
1995 (with-parsed-tramp-file-name file1 v1
1996 (with-parsed-tramp-file-name file2 v2
1997 (when (and (tramp-ange-ftp-file-name-p v1-multi-method v1-method)
1998 (tramp-ange-ftp-file-name-p v2-multi-method v2-method))
1999 (tramp-invoke-ange-ftp 'file-newer-than-file-p
2000 file1 file2))
2001 (unless (and (equal v1-multi-method v2-multi-method)
2002 (equal v1-method v2-method)
2003 (equal v1-user v2-user)
2004 (equal v1-host v2-host))
2005 (signal 'file-error
2006 (list "Files must have same method, user, host"
2007 file1 file2)))
2008 (unless (and (tramp-tramp-file-p file1)
2009 (tramp-tramp-file-p file2))
2010 (signal 'file-error
2011 (list "Files must be tramp files on same host"
2012 file1 file2)))
2013 (if (tramp-get-test-groks-nt
2014 v1-multi-method v1-method v1-user v1-host)
2015 (zerop (tramp-run-test2 "test" file1 file2 "-nt"))
2016 (zerop (tramp-run-test2 "tramp_test_nt" file1 file2)))))))))
fb7933a3
KG
2017
2018;; Functions implemented using the basic functions above.
2019
2020(defun tramp-handle-file-modes (filename)
2021 "Like `file-modes' for tramp files."
c62c9d08
KG
2022 (with-parsed-tramp-file-name filename nil
2023 (when (tramp-ange-ftp-file-name-p multi-method method)
2024 (tramp-invoke-ange-ftp 'file-modes filename))
2025 (when (file-exists-p filename)
2026 (tramp-mode-string-to-int
2027 (nth 8 (tramp-handle-file-attributes filename))))))
fb7933a3
KG
2028
2029(defun tramp-handle-file-directory-p (filename)
2030 "Like `file-directory-p' for tramp files."
2031 ;; Care must be taken that this function returns `t' for symlinks
2032 ;; pointing to directories. Surely the most obvious implementation
2033 ;; would be `test -d', but that returns false for such symlinks.
2034 ;; CCC: Stefan Monnier says that `test -d' follows symlinks. And
2035 ;; I now think he's right. So we could be using `test -d', couldn't
2036 ;; we?
2037 ;;
2038 ;; Alternatives: `cd %s', `test -d %s'
c62c9d08
KG
2039 (with-parsed-tramp-file-name filename nil
2040 (when (tramp-ange-ftp-file-name-p multi-method method)
2041 (tramp-invoke-ange-ftp 'file-directory-p filename))
2042 (save-excursion
fb7933a3
KG
2043 (zerop
2044 (tramp-send-command-and-check
c62c9d08
KG
2045 multi-method method user host
2046 (format "test -d %s"
2047 (tramp-shell-quote-argument path))
2048 t))))) ;run command in subshell
fb7933a3
KG
2049
2050(defun tramp-handle-file-regular-p (filename)
2051 "Like `file-regular-p' for tramp files."
c62c9d08
KG
2052 (with-parsed-tramp-file-name filename nil
2053 (when (tramp-ange-ftp-file-name-p multi-method method)
2054 (tramp-invoke-ange-ftp 'file-regular-p filename))
2055 (and (tramp-handle-file-exists-p filename)
2056 (eq ?- (aref (nth 8 (tramp-handle-file-attributes filename)) 0)))))
fb7933a3
KG
2057
2058(defun tramp-handle-file-symlink-p (filename)
2059 "Like `file-symlink-p' for tramp files."
c62c9d08
KG
2060 (with-parsed-tramp-file-name filename nil
2061 (when (tramp-ange-ftp-file-name-p multi-method method)
2062 (tramp-invoke-ange-ftp 'file-symlink-p filename))
2063 (let ((x (car (tramp-handle-file-attributes filename))))
2064 (when (stringp x) x))))
fb7933a3
KG
2065
2066(defun tramp-handle-file-writable-p (filename)
2067 "Like `file-writable-p' for tramp files."
c62c9d08
KG
2068 (with-parsed-tramp-file-name filename nil
2069 (when (tramp-ange-ftp-file-name-p multi-method method)
2070 (tramp-invoke-ange-ftp 'file-writable-p filename))
2071 (if (tramp-handle-file-exists-p filename)
2072 ;; Existing files must be writable.
2073 (zerop (tramp-run-test "-w" filename))
2074 ;; If file doesn't exist, check if directory is writable.
2075 (and (zerop (tramp-run-test
2076 "-d" (tramp-handle-file-name-directory filename)))
2077 (zerop (tramp-run-test
2078 "-w" (tramp-handle-file-name-directory filename)))))))
fb7933a3
KG
2079
2080(defun tramp-handle-file-ownership-preserved-p (filename)
2081 "Like `file-ownership-preserved-p' for tramp files."
c62c9d08
KG
2082 (with-parsed-tramp-file-name filename nil
2083 (when (tramp-ange-ftp-file-name-p multi-method method)
2084 (tramp-invoke-ange-ftp 'file-ownership-preserved-p filename))
2085 (or (not (tramp-handle-file-exists-p filename))
2086 ;; Existing files must be writable.
2087 (zerop (tramp-run-test "-O" filename)))))
fb7933a3
KG
2088
2089;; Other file name ops.
2090
2091