* Connection caching:: Reusing connection related information.
* Predefined connection information::
Setting own connection related information.
-* Remote Programs:: How @value{tramp} finds and uses programs on the remote host.
+* Remote programs:: How @value{tramp} finds and uses programs on the remote host.
* Remote shell setup:: Remote shell setup hints.
* Android shell setup:: Android shell setup hints.
* Auto-save and Backup:: Auto-save and Backup.
If you don't know which method is right for you, see @xref{Default
Method}.
+@strong{Note:} In the following description, setting of user options
+or variables is explained. Not all of them are autoloaded by
+@value{emacsname}. All examples expect, that you have loaded
+@value{tramp} first:
+
+@lisp
+(require 'tramp)
+@end lisp
+
@menu
* Connection types:: Types of connections made to remote hosts.
* Connection caching:: Reusing connection related information.
* Predefined connection information::
Setting own connection related information.
-* Remote Programs:: How @value{tramp} finds and uses programs on the remote host.
+* Remote programs:: How @value{tramp} finds and uses programs on the remote host.
* Remote shell setup:: Remote shell setup hints.
* Android shell setup:: Android shell setup hints.
* Auto-save and Backup:: Auto-save and Backup.
@command{mimencode} (part of the @command{metamail} package) or
@command{uuencode} on the remote host. The first reliable command
will be used. The search path can be customized, see @ref{Remote
-Programs}.
+programs}.
If both commands aren't available on the remote host, @value{tramp}
transfers a small piece of Perl code to the remote host, and tries to
@code{tramp-persistency-file-name} to @code{nil}.
Once consequence of reusing connection related information is that
-@var{tramp} needs to distinguish hosts. If you, for example, run a
+@value{tramp} needs to distinguish hosts. If you, for example, run a
local @code{sshd} on port 3001, which tunnels @command{ssh} to another
host, you could access both @file{@trampfn{ssh, , localhost,}} and
-@file{@trampfn{ssh, , localhost#3001,}}. @var{tramp} would use the
+@file{@trampfn{ssh, , localhost#3001,}}. @value{tramp} would use the
same host related information (like paths, Perl variants, etc) for
both connections, although the information is valid only for one of
them.
@node Predefined connection information
@section Setting own connection related information
-Sometimes, @var{tramp} is not able to detect correct connection
-related information. In such cases, you could tell @var{tramp} which
-value it has to take. Since this could result in errors, it has to be
-used with care.
+Sometimes, method specific arguments in @code{tramp-methods} do not
+fit your needs. Sometimes, @value{tramp} is not able to detect
+correct connection related information. In such cases, you could tell
+@value{tramp} which value it has to take. Since this could result in
+errors, it has to be used with care.
@vindex tramp-connection-properties
Such settings can be performed via the list
form @code{(@var{regexp} @var{property} @var{value})}. @var{regexp}
matches remote file names for which a property shall be predefined.
It can be @code{nil}. @var{property} is a string, and @var{value} the
-corresponding value. @var{property} could be any property found in
-the file @code{tramp-persistency-file-name}.
+corresponding value.
-A special property is @code{"busybox"}. This must be set, if the
-remote host runs a very restricted busybox as shell, which closes the
+@var{property} could be any method specific parameter found in
+@code{tramp-methods}. The parameter key in @code{tramp-methods} is a
+symbol name @code{tramp-<foo>}. In order to overwrite it,
+@var{property} must be the string @samp{<foo>}. If you, for example,
+want to change the remote shell to be used on a remote machine, you
+could apply
+
+@lisp
+(add-to-list 'tramp-connection-properties
+ (list (regexp-quote "@trampfn{ssh, user, randomhost.your.domain,}")
+ "remote-shell" "/bin/ksh"))
+(add-to-list 'tramp-connection-properties
+ (list (regexp-quote "@trampfn{ssh, user, randomhost.your.domain,}")
+ "remote-shell-login" '("-")))
+@end lisp
+
+This would overwrite the @code{tramp-remote-shell} and
+@code{tramp-remote-shell-login} parameters in @code{tramp-methods}, to
+be used on that remote host.
+
+@var{property} could also be any property found in the file
+@code{tramp-persistency-file-name}.
+
+A special property is @samp{busybox}. This must be set, if the remote
+host runs a very restricted busybox as shell, which closes the
connection at will. Since there is no reliable test for this,
-@var{tramp} must be indicated this way. Example:
+@value{tramp} must be indicated this way. Example:
@lisp
(add-to-list 'tramp-connection-properties
@end lisp
-@node Remote Programs
+@node Remote programs
@section How @value{tramp} finds and uses programs on the remote host
@value{tramp} depends on a number of programs on the remote host in order to
as:
@lisp
-@i{;; We load @value{tramp} to define the variable.}
-(require 'tramp)
-@i{;; We have @command{perl} in "/usr/local/perl/bin"}
(add-to-list 'tramp-remote-path "/usr/local/perl/bin")
@end lisp
Note that @value{tramp} requires the match for @code{shell-prompt-pattern}
to be at the end of the buffer. Many people have something like the
-following as the value for the variable: @code{"^[^>$][>$] *"}. Now
+following as the value for the variable: @samp{^[^>$][>$] *}. Now
suppose your shell prompt is @code{a <b> c $ }. In this case,
@value{tramp} recognizes the @code{>} character as the end of the prompt,
but it is not at the end of the buffer.
When your program is not found in the default search path
@value{tramp} sets on the remote host, you should either use an
absolute path, or extend @code{tramp-remote-path} (see @ref{Remote
-Programs}):
+programs}):
@lisp
(add-to-list 'tramp-remote-path "~/bin")
The environment for your program can be adapted by customizing
@code{tramp-remote-process-environment}. This variable is a list of
strings. It is structured like @code{process-environment}. Each
-element is a string of the form @code{"ENVVARNAME=VALUE"}. An entry
-@code{"ENVVARNAME="} disables the corresponding environment variable,
+element is a string of the form @samp{ENVVARNAME=VALUE}. An entry
+@samp{ENVVARNAME=} disables the corresponding environment variable,
which might have been set in your init file like @file{~/.profile}.
@noindent
function call traces. Such traces are enabled by the following code:
@lisp
-(require 'tramp)
(require 'trace)
(dolist (elt (all-completions "tramp-" obarray 'functionp))
(trace-function-background (intern elt)))
@c In the Tramp GIT, the version number is auto-frobbed from
@c configure.ac, so you should edit that file and run
@c "autoconf && ./configure" to change the version number.
-@set trampver 2.2.12
+@set trampver 2.2.13-pre
@c Other flags from configuration
@set instprefix /usr/local
Every entry has the form (REGEXP PROPERTY VALUE). The regexp
matches remote file names. It can be nil. PROPERTY is a string,
and VALUE the corresponding value. They are used, if there is no
-matching entry for PROPERTY in `tramp-cache-data'."
+matching entry for PROPERTY in `tramp-cache-data'. For more
+details see the info pages."
:group 'tramp
:version "24.4"
:type '(repeat (list (choice :tag "File Name regexp" regexp (const nil))
\f
;; File name primitives.
+(defun tramp-gvfs-do-copy-or-rename-file
+ (op filename newname &optional ok-if-already-exists keep-date
+ preserve-uid-gid preserve-extended-attributes)
+ "Copy or rename a remote file.
+OP must be `copy' or `rename' and indicates the operation to perform.
+FILENAME specifies the file to copy or rename, NEWNAME is the name of
+the new file (for copy) or the new name of the file (for rename).
+OK-IF-ALREADY-EXISTS means don't barf if NEWNAME exists already.
+KEEP-DATE means to make sure that NEWNAME has the same timestamp
+as FILENAME. PRESERVE-UID-GID, when non-nil, instructs to keep
+the uid and gid if both files are on the same host.
+PRESERVE-EXTENDED-ATTRIBUTES is ignored.
+
+This function is invoked by `tramp-gvfs-handle-copy-file' and
+`tramp-gvfs-handle-rename-file'. It is an error if OP is neither
+of `copy' and `rename'. FILENAME and NEWNAME must be absolute
+file names."
+ (unless (memq op '(copy rename))
+ (error "Unknown operation `%s', must be `copy' or `rename'" op))
+
+ (let ((t1 (tramp-tramp-file-p filename))
+ (t2 (tramp-tramp-file-p newname))
+ (equal-remote (tramp-equal-remote filename newname))
+ (file-operation (intern (format "%s-file" op)))
+ (gvfs-operation (if (eq op 'copy) "gvfs-copy" "gvfs-move"))
+ (msg-operation (if (eq op 'copy) "Copying" "Renaming")))
+
+ (with-parsed-tramp-file-name (if t1 filename newname) nil
+ (when (and (not ok-if-already-exists) (file-exists-p newname))
+ (tramp-error
+ v 'file-already-exists "File %s already exists" newname))
+
+ (if (or (and equal-remote
+ (tramp-get-connection-property v "direct-copy-failed" nil))
+ (and t1 (not (tramp-gvfs-file-name-p filename)))
+ (and t2 (not (tramp-gvfs-file-name-p newname))))
+
+ ;; We cannot copy or rename directly.
+ (let ((tmpfile (tramp-compat-make-temp-file filename)))
+ (cond
+ (preserve-extended-attributes
+ (tramp-compat-funcall
+ file-operation
+ filename tmpfile t keep-date preserve-uid-gid
+ preserve-extended-attributes))
+ (preserve-uid-gid
+ (tramp-compat-funcall
+ file-operation filename tmpfile t keep-date preserve-uid-gid))
+ (t
+ (tramp-compat-funcall
+ file-operation filename tmpfile t keep-date)))
+ (rename-file tmpfile newname ok-if-already-exists))
+
+ ;; Direct action.
+ (with-tramp-progress-reporter
+ v 0 (format "%s %s to %s" msg-operation filename newname)
+ (unless
+ (apply
+ 'tramp-gvfs-send-command v gvfs-operation
+ (append
+ (and (eq op 'copy) (or keep-date preserve-uid-gid)
+ (list "--preserve"))
+ (list
+ (tramp-gvfs-url-file-name filename)
+ (tramp-gvfs-url-file-name newname))))
+
+ (if (or (not equal-remote)
+ (and equal-remote
+ (tramp-get-connection-property
+ v "direct-copy-failed" nil)))
+ ;; Propagate the error.
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (goto-char (point-min))
+ (tramp-error-with-buffer
+ nil v 'file-error
+ "%s failed, see buffer `%s' for details."
+ msg-operation (buffer-name)))
+
+ ;; Some WebDAV server, like the one from QNAP, do not
+ ;; support direct copy/move. Try a fallback.
+ (tramp-set-connection-property v "direct-copy-failed" t)
+ (tramp-gvfs-do-copy-or-rename-file
+ op filename newname ok-if-already-exists keep-date
+ preserve-uid-gid preserve-extended-attributes))))
+
+ (when (and t1 (eq op 'rename))
+ (with-parsed-tramp-file-name filename nil
+ (tramp-flush-file-property v (file-name-directory localname))
+ (tramp-flush-file-property v localname)))
+
+ (when t2
+ (with-parsed-tramp-file-name newname nil
+ (tramp-flush-file-property v (file-name-directory localname))
+ (tramp-flush-file-property v localname)))))))
+
(defun tramp-gvfs-handle-copy-file
(filename newname &optional ok-if-already-exists keep-date
preserve-uid-gid preserve-extended-attributes)
"Like `copy-file' for Tramp files."
- (with-parsed-tramp-file-name
- (if (tramp-tramp-file-p filename) filename newname) nil
-
- (when (and (not ok-if-already-exists) (file-exists-p newname))
- (tramp-error
- v 'file-already-exists "File %s already exists" newname))
-
- (if (or (and (tramp-tramp-file-p filename)
- (not (tramp-gvfs-file-name-p filename)))
- (and (tramp-tramp-file-p newname)
- (not (tramp-gvfs-file-name-p newname))))
-
- ;; We cannot call `copy-file' directly. Use
- ;; `tramp-compat-funcall' for backward compatibility (number
- ;; of arguments).
- (let ((tmpfile (tramp-compat-make-temp-file filename)))
- (cond
- (preserve-extended-attributes
- (tramp-compat-funcall
- 'copy-file
- filename tmpfile t keep-date preserve-uid-gid
- preserve-extended-attributes))
- (preserve-uid-gid
- (tramp-compat-funcall
- 'copy-file filename tmpfile t keep-date preserve-uid-gid))
- (t
- (copy-file filename tmpfile t keep-date)))
- (rename-file tmpfile newname ok-if-already-exists))
-
- ;; Direct copy.
- (with-tramp-progress-reporter
- v 0 (format "Copying %s to %s" filename newname)
- (unless
- (let ((args
- (append (if (or keep-date preserve-uid-gid)
- (list "--preserve")
- nil)
- (list
- (tramp-gvfs-url-file-name filename)
- (tramp-gvfs-url-file-name newname)))))
- (apply 'tramp-gvfs-send-command v "gvfs-copy" args))
- ;; Propagate the error.
- (with-current-buffer (tramp-get-connection-buffer v)
- (goto-char (point-min))
- (tramp-error-with-buffer
- nil v 'file-error
- "Copying failed, see buffer `%s' for details." (buffer-name)))))
-
- (when (tramp-tramp-file-p newname)
- (with-parsed-tramp-file-name newname nil
- (tramp-flush-file-property v (file-name-directory localname))
- (tramp-flush-file-property v localname))))))
+ (setq filename (expand-file-name filename))
+ (setq newname (expand-file-name newname))
+ (cond
+ ;; At least one file a Tramp file?
+ ((or (tramp-tramp-file-p filename)
+ (tramp-tramp-file-p newname))
+ (tramp-gvfs-do-copy-or-rename-file
+ 'copy filename newname ok-if-already-exists keep-date
+ preserve-uid-gid preserve-extended-attributes))
+ ;; Compat section.
+ (preserve-extended-attributes
+ (tramp-run-real-handler
+ 'copy-file
+ (list filename newname ok-if-already-exists keep-date
+ preserve-uid-gid preserve-extended-attributes)))
+ (preserve-uid-gid
+ (tramp-run-real-handler
+ 'copy-file
+ (list filename newname ok-if-already-exists keep-date preserve-uid-gid)))
+ (t
+ (tramp-run-real-handler
+ 'copy-file (list filename newname ok-if-already-exists keep-date)))))
(defun tramp-gvfs-handle-delete-directory (directory &optional recursive trash)
"Like `delete-directory' for Tramp files."
(defun tramp-gvfs-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
+ (setq dir (directory-file-name (expand-file-name dir)))
(with-parsed-tramp-file-name dir nil
- (unless
- (apply
- 'tramp-gvfs-send-command v "gvfs-mkdir"
- (if parents
- (list "-p" (tramp-gvfs-url-file-name dir))
- (list (tramp-gvfs-url-file-name dir))))
- ;; Propagate the error.
- (tramp-error v 'file-error "Couldn't make directory %s" dir))))
+ (tramp-flush-file-property v (file-name-directory localname))
+ (tramp-flush-directory-property v localname)
+ (save-match-data
+ (let ((ldir (file-name-directory dir)))
+ ;; Make missing directory parts. "gvfs-mkdir -p ..." does not
+ ;; work robust.
+ (when (and parents (not (file-directory-p ldir)))
+ (make-directory ldir parents))
+ ;; Just do it.
+ (unless (tramp-gvfs-send-command
+ v "gvfs-mkdir" (tramp-gvfs-url-file-name dir))
+ (tramp-error v 'file-error "Couldn't make directory %s" dir))))))
(defun tramp-gvfs-handle-rename-file
(filename newname &optional ok-if-already-exists)
"Like `rename-file' for Tramp files."
- (with-parsed-tramp-file-name
- (if (tramp-tramp-file-p filename) filename newname) nil
-
- (when (and (not ok-if-already-exists) (file-exists-p newname))
- (tramp-error
- v 'file-already-exists "File %s already exists" newname))
-
- (if (or (and (tramp-tramp-file-p filename)
- (not (tramp-gvfs-file-name-p filename)))
- (and (tramp-tramp-file-p newname)
- (not (tramp-gvfs-file-name-p newname))))
-
- ;; We cannot move directly.
- (let ((tmpfile (tramp-compat-make-temp-file filename)))
- (rename-file filename tmpfile t)
- (rename-file tmpfile newname ok-if-already-exists))
-
- ;; Direct move.
- (with-tramp-progress-reporter
- v 0 (format "Renaming %s to %s" filename newname)
- (unless
- (tramp-gvfs-send-command
- v "gvfs-move"
- (tramp-gvfs-url-file-name filename)
- (tramp-gvfs-url-file-name newname))
- ;; Propagate the error.
- (with-current-buffer (tramp-get-buffer v)
- (goto-char (point-min))
- (tramp-error-with-buffer
- nil v 'file-error
- "Renaming failed, see buffer `%s' for details." (buffer-name)))))
-
- (when (tramp-tramp-file-p filename)
- (with-parsed-tramp-file-name filename nil
- (tramp-flush-file-property v (file-name-directory localname))
- (tramp-flush-file-property v localname)))
-
- (when (tramp-tramp-file-p newname)
- (with-parsed-tramp-file-name newname nil
- (tramp-flush-file-property v (file-name-directory localname))
- (tramp-flush-file-property v localname))))))
+ ;; Check if both files are local -- invoke normal rename-file.
+ ;; Otherwise, use Tramp from local system.
+ (setq filename (expand-file-name filename))
+ (setq newname (expand-file-name newname))
+ ;; At least one file a Tramp file?
+ (if (or (tramp-tramp-file-p filename)
+ (tramp-tramp-file-p newname))
+ (tramp-gvfs-do-copy-or-rename-file
+ 'rename filename newname ok-if-already-exists t t)
+ (tramp-run-real-handler
+ 'rename-file (list filename newname ok-if-already-exists))))
(defun tramp-gvfs-handle-write-region
(start end filename &optional append visit lockname confirm)
;; indicated by the "mounted" signal, i.e. the "fuse-mountpoint"
;; file property.
(with-timeout
- ((or (tramp-get-method-parameter method 'tramp-connection-timeout)
+ ((or (tramp-get-method-parameter vec 'tramp-connection-timeout)
tramp-connection-timeout)
(if (zerop (length (tramp-file-name-user vec)))
(tramp-error
(tramp-login-program "rsh")
(tramp-login-args (("%h") ("-l" "%u")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "rcp")
(tramp-copy-args (("-p" "%k") ("-r")))
(tramp-login-program "remsh")
(tramp-login-args (("%h") ("-l" "%u")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "rcp")
(tramp-copy-args (("-p" "%k")))
("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "scp")
(tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q") ("-r") ("%c")))
("-e" "none") ("-t" "-t") ("%h") ("/bin/sh")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "scp")
(tramp-copy-args (("-P" "%p") ("-p" "%k")
("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "rsync")
(tramp-copy-args (("-t" "%k") ("-r")))
(tramp-login-program "rsh")
(tramp-login-args (("%h") ("-l" "%u")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))))
;;;###tramp-autoload
(add-to-list 'tramp-methods
(tramp-login-program "remsh")
(tramp-login-args (("%h") ("-l" "%u")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))))
;;;###tramp-autoload
(add-to-list 'tramp-methods
("-e" "none") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
("-o" "UserKnownHostsFile=/dev/null")
("-e" "none") ("-t" "-t") ("%h") ("/bin/sh")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null")
("-o" "UserKnownHostsFile=/dev/null")
(tramp-login-program "telnet")
(tramp-login-args (("%h") ("%p") ("2>/dev/null")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-default-port 23)))
;;;###tramp-autoload
(tramp-login-program "telnet")
(tramp-login-args (("%h") ("%p") ("2>/dev/null")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "nc")
;; We use "-v" for better error tracking.
(tramp-login-program "su")
(tramp-login-args (("-") ("%u")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-connection-timeout 10)))
;;;###tramp-autoload
;; Local $SHELL could be a nasty one, like zsh or fish. Let's override it.
(tramp-login-env (("SHELL") ("/bin/sh")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-connection-timeout 10)))
;;;###tramp-autoload
(tramp-login-program "ksu")
(tramp-login-args (("%u") ("-q")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-connection-timeout 10)))
;;;###tramp-autoload
(tramp-login-program "krlogin")
(tramp-login-args (("%h") ("-l" "%u") ("-x")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))))
;;;###tramp-autoload
(add-to-list 'tramp-methods
tramp-initial-end-of-output))
("/bin/sh") ("\"")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-default-port 22)))
;;;###tramp-autoload
tramp-initial-end-of-output))
("/bin/sh") ("\"")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))))
;;;###tramp-autoload
(add-to-list 'tramp-methods
tramp-initial-end-of-output))
("/bin/sh") ("\"")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "pscp")
(tramp-copy-args (("-l" "%u") ("-P" "%p") ("-scp") ("-p" "%k")
tramp-initial-end-of-output))
("/bin/sh") ("\"")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "pscp")
(tramp-copy-args (("-l" "%u") ("-P" "%p") ("-sftp") ("-p" "%k")
(tramp-login-program "fsh")
(tramp-login-args (("%h") ("-l" "%u") ("sh" "-i")))
(tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-i") ("-c"))
(tramp-copy-program "fcp")
(tramp-copy-args (("-p" "%k")))
(t2 (tramp-tramp-file-p newname)))
(with-parsed-tramp-file-name (if t1 dirname newname) nil
(if (and (not copy-contents)
- (tramp-get-method-parameter method 'tramp-copy-recursive)
+ (tramp-get-method-parameter v 'tramp-copy-recursive)
;; When DIRNAME and NEWNAME are remote, they must have
;; the same method.
(or (null t1) (null t2)
(tramp-get-connection-property v "login-as" nil)))
;; Check for listener port.
- (when (tramp-get-method-parameter method 'tramp-remote-copy-args)
+ (when (tramp-get-method-parameter v 'tramp-remote-copy-args)
(setq listener (number-to-string (+ 50000 (random 10000))))
(while
(zerop (tramp-call-process v "nc" nil nil nil "-z" host listener))
spec (format-spec-make
?h host ?u user ?p port ?r listener ?c options
?k (if keep-date " " ""))
- copy-program (tramp-get-method-parameter
- method 'tramp-copy-program)
+ copy-program (tramp-get-method-parameter v 'tramp-copy-program)
copy-keep-date (tramp-get-method-parameter
- method 'tramp-copy-keep-date)
+ v 'tramp-copy-keep-date)
copy-args
(delete
;; for the whole keep-date sublist.
" "
(dolist
- (x
- (tramp-get-method-parameter method 'tramp-copy-args)
- copy-args)
+ (x (tramp-get-method-parameter v 'tramp-copy-args) copy-args)
(setq copy-args
(append
copy-args
(lambda (x)
(setq x (mapcar (lambda (y) (format-spec y spec)) x))
(unless (member "" x) (mapconcat 'identity x " ")))
- (tramp-get-method-parameter method 'tramp-copy-env)))
+ (tramp-get-method-parameter v 'tramp-copy-env)))
remote-copy-program
- (tramp-get-method-parameter method 'tramp-remote-copy-program))
+ (tramp-get-method-parameter v 'tramp-remote-copy-program))
- (dolist
- (x
- (or
- (tramp-get-connection-property v "remote-copy-args" nil)
- (tramp-get-method-parameter method 'tramp-remote-copy-args)))
+ (dolist (x (tramp-get-method-parameter v 'tramp-remote-copy-args))
(setq remote-copy-args
(append
remote-copy-args
(if (and (not (stringp start))
(= (or end (point-max)) (point-max))
(= (or start (point-min)) (point-min))
- (tramp-get-method-parameter
- method 'tramp-copy-keep-tmpfile))
+ (tramp-get-method-parameter v 'tramp-copy-keep-tmpfile))
(progn
(setq tramp-temp-buffer-file-name tmpfile)
(condition-case err
(defun tramp-find-shell (vec)
"Opens a shell on the remote host which groks tilde expansion."
(with-current-buffer (tramp-get-buffer vec)
- (let ((default-shell
- (or
- (tramp-get-connection-property
- (tramp-get-connection-process vec) "remote-shell" nil)
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-remote-shell)))
+ (let ((default-shell (tramp-get-method-parameter vec 'tramp-remote-shell))
shell)
(setq shell
(with-tramp-connection-property vec "remote-shell"
Mainly sets the prompt and the echo correctly. PROC is the shell
process to set up. VEC specifies the connection."
(let ((tramp-end-of-output tramp-initial-end-of-output))
- (tramp-open-shell
- vec
- (or (tramp-get-connection-property vec "remote-shell" nil)
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-remote-shell)))
+ (tramp-open-shell vec (tramp-get-method-parameter vec 'tramp-remote-shell))
;; Disable echo.
(tramp-message vec 5 "Setting up remote shell environment")
;; Foreign and out-of-band methods are not supported for multi-hops.
(when (cdr target-alist)
(setq choices target-alist)
- (while choices
- (setq item (pop choices))
- (when
- (or
- (not
- (tramp-get-method-parameter
- (tramp-file-name-method item) 'tramp-login-program))
- (tramp-get-method-parameter
- (tramp-file-name-method item) 'tramp-copy-program))
+ (while (setq item (pop choices))
+ (when (or (not (tramp-get-method-parameter item 'tramp-login-program))
+ (tramp-get-method-parameter item 'tramp-copy-program))
(tramp-error
vec 'file-error
"Method `%s' is not supported for multi-hops."
;; There are multi-hops.
(cdr target-alist)
;; The host name is used for the remote shell command.
- (member
- '("%h") (tramp-get-method-parameter method 'tramp-login-args))
+ (member '("%h") (tramp-get-method-parameter v 'tramp-login-args))
;; The host is local. We cannot use `tramp-local-host-p'
;; here, because it opens a connection as well.
(string-match tramp-local-host-regexp host))
(cond
;; No options to be computed.
((or (null tramp-use-ssh-controlmaster-options)
- (null (assoc "%c" (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-login-args))))
+ (null (assoc "%c" (tramp-get-method-parameter vec 'tramp-login-args))))
"")
;; There is already a value to be used.
(l-host (tramp-file-name-host hop))
(l-port nil)
(login-program
- (tramp-get-method-parameter
- l-method 'tramp-login-program))
+ (tramp-get-method-parameter hop 'tramp-login-program))
(login-args
- (tramp-get-method-parameter
- l-method 'tramp-login-args))
+ (tramp-get-method-parameter hop 'tramp-login-args))
(login-env
- (tramp-get-method-parameter
- l-method 'tramp-login-env))
+ (tramp-get-method-parameter hop 'tramp-login-env))
(async-args
- (tramp-get-method-parameter
- l-method 'tramp-async-args))
+ (tramp-get-method-parameter hop 'tramp-async-args))
(connection-timeout
(tramp-get-method-parameter
- l-method 'tramp-connection-timeout))
+ hop 'tramp-connection-timeout))
(gw-args
- (tramp-get-method-parameter l-method 'tramp-gw-args))
+ (tramp-get-method-parameter hop 'tramp-gw-args))
(gw (let ((tramp-verbose 0))
(tramp-get-file-property hop "" "gateway" nil)))
(g-method (and gw (tramp-file-name-method gw)))
(let ((method (tramp-file-name-method vec))
(user (tramp-file-name-user vec))
(host (tramp-file-name-real-host vec))
- (localname (tramp-shell-quote-argument
- (tramp-file-name-localname vec))))
+ (localname (tramp-file-name-localname vec)))
(when (string-match tramp-ipv6-regexp host)
(setq host (format "[%s]" host)))
+ (unless (string-match "ftp$" method)
+ (setq localname (tramp-shell-quote-argument localname)))
(cond
- ((tramp-get-method-parameter method 'tramp-remote-copy-program)
+ ((tramp-get-method-parameter vec 'tramp-remote-copy-program)
localname)
((not (zerop (length user)))
(shell-quote-argument (format "%s@%s:%s" user host localname)))
"Return t if this is an out-of-band method, nil otherwise."
(and
;; It shall be an out-of-band method.
- (tramp-get-method-parameter (tramp-file-name-method vec) 'tramp-copy-program)
+ (tramp-get-method-parameter vec 'tramp-copy-program)
;; There must be a size, otherwise the file doesn't exist.
(numberp size)
;; Either the file size is large enough, or (in rare cases) there
(tramp-send-command-and-read
vec
(format
- "%s -l %s 'echo %s \\\"$PATH\\\"'"
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-remote-shell)
+ "%s %s %s 'echo %s \\\"$PATH\\\"'"
+ (tramp-get-method-parameter vec 'tramp-remote-shell)
+ (mapconcat
+ 'identity
+ (tramp-get-method-parameter vec 'tramp-remote-shell-login)
+ " ")
(mapconcat
'identity
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-remote-shell-args)
+ (tramp-get-method-parameter vec 'tramp-remote-shell-args)
" ")
(tramp-shell-quote-argument tramp-end-of-heredoc))
nil (regexp-quote tramp-end-of-heredoc)))))
;; * Don't use globbing for directories with many files, as this is
;; likely to produce long command lines, and some shells choke on
;; long command lines.
-;; * Make it work for different encodings, and for different file name
-;; encodings, too. (Daniel Pittman)
;; * Don't search for perl5 and perl. Instead, only search for perl and
;; then look if it's the right version (with `perl -v').
;; * When editing a remote CVS controlled file as a different user, VC
for it. Also note that \"/bin/sh\" exists on all Unixen,
this might not be true for the value that you decide to use.
You Have Been Warned.
+ * `tramp-remote-shell-login'
+ This specifies the arguments to let `tramp-remote-shell' run
+ as a login shell. It defaults to (\"-l\"), but some shells,
+ like ksh, require another argument. See
+ `tramp-connection-properties' for a way to overwrite the
+ default value.
* `tramp-remote-shell-args'
For implementation of `shell-command', this specifies the
arguments to let `tramp-remote-shell' run a single command.
;; internal data structure. Convenience functions for internal
;; data structure.
-(defun tramp-get-method-parameter (method param)
+(defun tramp-get-method-parameter (vec param)
"Return the method parameter PARAM.
-If the `tramp-methods' entry does not exist, return nil."
- (let ((entry (assoc param (assoc method tramp-methods))))
- (when entry (cadr entry))))
+If VEC is a vector, check first in connection properties.
+Afterwards, check in `tramp-methods'. If the `tramp-methods'
+entry does not exist, return nil."
+ (let ((hash-entry
+ (replace-regexp-in-string "^tramp-" "" (symbol-name param))))
+ (if (tramp-connection-property-p vec hash-entry)
+ ;; We use the cached property.
+ (tramp-get-connection-property vec hash-entry nil)
+ ;; Use the static value from `tramp-methods'.
+ (let ((methods-entry
+ (assoc param (assoc (tramp-file-name-method vec) tramp-methods))))
+ (when methods-entry (cadr methods-entry))))))
(defun tramp-file-name-p (vec)
"Check, whether VEC is a Tramp object."
(or (and (stringp host)
(string-match tramp-host-with-port-regexp host)
(string-to-number (match-string 2 host)))
- (tramp-get-method-parameter method 'tramp-default-port)))))
+ (tramp-get-method-parameter vec 'tramp-default-port)))))
;;;###tramp-autoload
(defun tramp-tramp-file-p (name)
;; name handlers.
(when (and (or beg end)
(tramp-get-method-parameter
- (tramp-file-name-method v)
- 'tramp-login-program))
+ v 'tramp-login-program))
(setq remote-copy (tramp-make-tramp-temp-file v))
;; This is defined in tramp-sh.el. Let's assume
;; this is loaded already.
(when (and (null remote-copy)
(tramp-get-method-parameter
- method 'tramp-copy-keep-tmpfile))
+ v 'tramp-copy-keep-tmpfile))
;; We keep the local file for performance reasons,
;; useful for "rsync".
(setq tramp-temp-buffer-file-name local-copy))
(args (append
(cons
(tramp-get-method-parameter
- (tramp-file-name-method
- (tramp-dissect-file-name default-directory))
+ (tramp-dissect-file-name default-directory)
'tramp-remote-shell)
(tramp-get-method-parameter
- (tramp-file-name-method
- (tramp-dissect-file-name default-directory))
+ (tramp-dissect-file-name default-directory)
'tramp-remote-shell-args))
(list (substring command 0 asynchronous))))
current-buffer-p
;; The method shall be applied to one of the shell file name
;; handlers. `tramp-local-host-p' is also called for "smb" and
;; alike, where it must fail.
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-login-program)
+ (tramp-get-method-parameter vec 'tramp-login-program)
;; The local temp directory must be writable for the other user.
(file-writable-p
(tramp-make-tramp-file-name
(defun tramp-get-remote-tmpdir (vec)
"Return directory for temporary files on the remote host identified by VEC."
- (with-tramp-connection-property vec "tmpdir"
- (let ((dir (tramp-make-tramp-file-name
- (tramp-file-name-method vec)
- (tramp-file-name-user vec)
- (tramp-file-name-host vec)
- (or
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-tmpdir)
- "/tmp"))))
- (if (and (file-directory-p dir) (file-writable-p dir))
- dir
- (tramp-error vec 'file-error "Directory %s not accessible" dir)))))
+ (when (file-remote-p (tramp-get-connection-property vec "tmpdir" ""))
+ ;; Compatibility code: Cached value shall be the local path only.
+ (tramp-set-connection-property vec "tmpdir" 'undef))
+ (let ((dir (tramp-make-tramp-file-name
+ (tramp-file-name-method vec)
+ (tramp-file-name-user vec)
+ (tramp-file-name-host vec)
+ (or (tramp-get-method-parameter vec 'tramp-tmpdir) "/tmp"))))
+ (with-tramp-connection-property vec "tmpdir"
+ (or (and (file-directory-p dir) (file-writable-p dir)
+ (file-remote-p dir 'localname))
+ (tramp-error vec 'file-error "Directory %s not accessible" dir)))
+ dir))
;;;###tramp-autoload
(defun tramp-make-tramp-temp-file (vec)
;; should be changed only there.
;;;###tramp-autoload
-(defconst tramp-version "2.2.12"
+(defconst tramp-version "2.2.13-pre"
"This version of Tramp.")
;;;###tramp-autoload
(= emacs-major-version 21)
(>= emacs-minor-version 4)))
"ok"
- (format "Tramp 2.2.12 is not fit for %s"
+ (format "Tramp 2.2.13-pre is not fit for %s"
(when (string-match "^.*$" (emacs-version))
(match-string 0 (emacs-version)))))))
(unless (string-match "\\`ok\\'" x) (error "%s" x)))
(declare (indent 1) (debug (natnump body)))
`(let ((tramp-verbose ,verbose)
(tramp-message-show-message t)
- (tramp-debug-on-error t))
+ (tramp-debug-on-error t)
+ (debug-ignored-errors
+ (cons "^make-symbolic-link not supported$" debug-ignored-errors)))
(unwind-protect
(progn ,@body)
(when (> tramp-verbose 3)
This tests also `file-directory-p' and `file-accessible-directory-p'."
(skip-unless (tramp--test-enabled))
- (let ((tmp-name (tramp--test-make-temp-name)))
+ (let* ((tmp-name1 (tramp--test-make-temp-name))
+ (tmp-name2 (expand-file-name "foo/bar" tmp-name1)))
(unwind-protect
(progn
- (make-directory tmp-name)
- (should (file-directory-p tmp-name))
- (should (file-accessible-directory-p tmp-name))
- (should-error
- (make-directory (expand-file-name "foo/bar" tmp-name))
- :type 'file-error)
- (make-directory (expand-file-name "foo/bar" tmp-name) 'parents)
- (should (file-directory-p (expand-file-name "foo/bar" tmp-name)))
- (should
- (file-accessible-directory-p (expand-file-name "foo/bar" tmp-name))))
+ (make-directory tmp-name1)
+ (should (file-directory-p tmp-name1))
+ (should (file-accessible-directory-p tmp-name1))
+ (should-error (make-directory tmp-name2) :type 'file-error)
+ (make-directory tmp-name2 'parents)
+ (should (file-directory-p tmp-name2))
+ (should (file-accessible-directory-p tmp-name2)))
;; Cleanup.
- (ignore-errors (delete-directory tmp-name 'recursive)))))
+ (ignore-errors (delete-directory tmp-name1 'recursive)))))
(ert-deftest tramp-test14-delete-directory ()
"Check `delete-directory'."
(defun tramp--test-adb-p ()
"Check, whether the remote host runs Android.
This requires restrictions of file name syntax."
- (eq (tramp-find-foreign-file-name-handler
- tramp-test-temporary-file-directory)
- 'tramp-adb-file-name-handler))
+ (tramp-adb-file-name-p tramp-test-temporary-file-directory))
+
+(defun tramp--test-ftp-p ()
+ "Check, whether an FTP-like method is used.
+This does not support globbing characters in file names (yet)."
+ ;; Globbing characters are ??, ?* and ?\[.
+ (and (eq (tramp-find-foreign-file-name-handler
+ tramp-test-temporary-file-directory)
+ 'tramp-sh-file-name-handler)
+ (string-match
+ "ftp$" (file-remote-p tramp-test-temporary-file-directory 'method))))
+
+(defun tramp--test-gvfs-p ()
+ "Check, whether the remote host runs a GVFS based method.
+This requires restrictions of file name syntax."
+ (tramp-gvfs-file-name-p tramp-test-temporary-file-directory))
(defun tramp--test-smb-or-windows-nt-p ()
"Check, whether the locale or remote host runs MS Windows.
This requires restrictions of file name syntax."
(or (eq system-type 'windows-nt)
- (eq (tramp-find-foreign-file-name-handler
- tramp-test-temporary-file-directory)
- 'tramp-smb-file-name-handler)))
+ (tramp-smb-file-name-p tramp-test-temporary-file-directory)))
(defun tramp--test-check-files (&rest files)
"Run a simple but comprehensive test over every file in FILES."
(ignore-errors (delete-directory tmp-name2 'recursive)))))
(defun tramp--test-special-characters ()
- "Perform the test in `tramp-test30-special-characters*'."
+ "Perform the test in `tramp-test31-special-characters*'."
;; Newlines, slashes and backslashes in file names are not
;; supported. So we don't test. And we don't test the tab
;; character on Windows or Cygwin, because the backslash is
;; interpreted as a path separator, preventing "\t" from being
;; expanded to <TAB>.
(tramp--test-check-files
- (if (tramp--test-smb-or-windows-nt-p)
+ (if (or (tramp--test-gvfs-p) (tramp--test-smb-or-windows-nt-p))
"foo bar baz"
(if (or (tramp--test-adb-p) (eq system-type 'cygwin))
" foo bar baz "
"-foo-bar-baz-"
"%foo%bar%baz%"
"&foo&bar&baz&"
- (unless (tramp--test-smb-or-windows-nt-p) "?foo?bar?baz?")
- (unless (tramp--test-smb-or-windows-nt-p) "*foo*bar*baz*")
- (if (tramp--test-smb-or-windows-nt-p) "'foo'bar'baz'" "'foo\"bar'baz\"")
+ (unless (or (tramp--test-ftp-p)
+ (tramp--test-gvfs-p)
+ (tramp--test-smb-or-windows-nt-p))
+ "?foo?bar?baz?")
+ (unless (or (tramp--test-ftp-p)
+ (tramp--test-gvfs-p)
+ (tramp--test-smb-or-windows-nt-p))
+ "*foo*bar*baz*")
+ (if (or (tramp--test-gvfs-p) (tramp--test-smb-or-windows-nt-p))
+ "'foo'bar'baz'"
+ "'foo\"bar'baz\"")
"#foo~bar#baz~"
- (if (tramp--test-smb-or-windows-nt-p) "!foo!bar!baz!" "!foo|bar!baz|")
- (if (tramp--test-smb-or-windows-nt-p) ";foo;bar;baz;" ":foo;bar:baz;")
- (unless (tramp--test-smb-or-windows-nt-p) "<foo>bar<baz>")
+ (if (or (tramp--test-gvfs-p) (tramp--test-smb-or-windows-nt-p))
+ "!foo!bar!baz!"
+ "!foo|bar!baz|")
+ (if (or (tramp--test-gvfs-p) (tramp--test-smb-or-windows-nt-p))
+ ";foo;bar;baz;"
+ ":foo;bar:baz;")
+ (unless (or (tramp--test-gvfs-p) (tramp--test-smb-or-windows-nt-p))
+ "<foo>bar<baz>")
"(foo)bar(baz)"
- "[foo]bar[baz]"
+ (unless (or (tramp--test-ftp-p) (tramp--test-gvfs-p)) "[foo]bar[baz]")
"{foo}bar{baz}"))
;; These tests are inspired by Bug#17238.
(tramp-set-connection-property v "perl" 'undef))))
(defun tramp--test-utf8 ()
- "Perform the test in `tramp-test31-utf8*'."
+ "Perform the test in `tramp-test32-utf8*'."
(let ((coding-system-for-read 'utf-8)
(coding-system-for-write 'utf-8)
(file-name-coding-system 'utf-8))
;; doesn't work well when an interactive password must be provided.
;; * Fix `tramp-test27-start-file-process' for `nc' and on MS
;; Windows (`process-send-eof'?).
-;; * Fix `tramp-test30-special-characters' for `nc'.
-;; * Fix `tramp-test31-utf8' for `nc'/`telnet' (when target is a dumb
+;; * Fix `tramp-test31-special-characters' for `nc'.
+;; * Fix `tramp-test32-utf8' for `nc'/`telnet' (when target is a dumb
;; busybox). Seems to be in `directory-files'.
-;; * Fix Bug#16928. Set expected error of `tramp-test32-asynchronous-requests'.
-;; * Fix `tramp-test34-unload' (Not all symbols are unbound). Set
+;; * Fix Bug#16928. Set expected error of `tramp-test33-asynchronous-requests'.
+;; * Fix `tramp-test35-unload' (Not all symbols are unbound). Set
;; expected error.
(defun tramp-test-all (&optional interactive)