branch: externals/tramp
commit 272846ccfd98671259371591288280103c68f66b
Author: Michael Albinus <[email protected]>
Commit: Michael Albinus <[email protected]>
Tramp ELPA version 2.8.1 released
---
README | 6 +-
test/tramp-tests.el | 281 ++++++++++++++++++++------------
texi/tramp.texi | 107 ++++++++----
texi/trampver.texi | 2 +-
tramp-adb.el | 87 +++++-----
tramp-sh.el | 3 +-
tramp-smb.el | 458 +++++++++++++++++++++++++++++++---------------------
tramp-sshfs.el | 2 +-
tramp.el | 16 +-
trampver.el | 6 +-
10 files changed, 604 insertions(+), 364 deletions(-)
diff --git a/README b/README
index d791d2ec7e..529a204ba0 100644
--- a/README
+++ b/README
@@ -32,11 +32,11 @@ Emacs 28 or older
• Remove all byte-compiled Tramp files
- $ rm -f ~/.emacs.d/elpa/tramp-2.8.0.5/tramp*.elc
+ $ rm -f ~/.emacs.d/elpa/tramp-2.8.1/tramp*.elc
• Start Emacs with Tramp's source files
- $ emacs -L ~/.emacs.d/elpa/tramp-2.8.0.5 -l tramp
+ $ emacs -L ~/.emacs.d/elpa/tramp-2.8.1 -l tramp
This should not give you the error.
@@ -50,7 +50,7 @@ Mitigation of a bug in Emacs 29.1
---------------------------------
Due to a bug in Emacs 29.1, you must apply the following change prior
-installation or upgrading Tramp 2.8.0.5 from GNU ELPA:
+installation or upgrading Tramp 2.8.1 from GNU ELPA:
(when (string-equal emacs-version "29.1")
(with-current-buffer
diff --git a/test/tramp-tests.el b/test/tramp-tests.el
index 76e9a47e41..979ff7edfc 100644
--- a/test/tramp-tests.el
+++ b/test/tramp-tests.el
@@ -80,6 +80,9 @@
(declare-function tramp-method-out-of-band-p "tramp-sh")
(declare-function tramp-smb-get-localname "tramp-smb")
(defvar ange-ftp-make-backup-files)
+(defvar auto-revert-notify-watch-descriptor)
+(defvar auto-revert-remote-files)
+(defvar auto-revert-use-notify)
(defvar comp-warn-primitives)
(defvar tramp-connection-properties)
(defvar tramp-copy-size-limit)
@@ -147,6 +150,8 @@
(setq auth-source-cache-expiry nil
auth-source-save-behavior nil
+ auto-revert-remote-files t
+ auto-revert-use-notify t
ert-batch-backtrace-right-margin nil
password-cache-expiry nil
remote-file-name-inhibit-cache nil
@@ -3878,7 +3883,7 @@ This tests also `access-file', `file-readable-p',
(delete-file tmp-name2)
;; A non-existent or cyclic link target makes the file
- ;; unaccessible.
+ ;; inaccessible.
(dolist (target
`("does-not-exist" ,(file-name-nondirectory tmp-name2)))
(make-symbolic-link target tmp-name2)
@@ -5338,18 +5343,36 @@ This tests also `make-symbolic-link', `file-truename'
and `add-name-to-file'."
kill-buffer-query-functions)
(unwind-protect
(progn
- ;; We cannot use "/bin/true" and "/bin/false"; those paths
- ;; do not exist on MS Windows.
- (should (zerop (process-file "true")))
- (should-not (zerop (process-file "false")))
+ ;; In the "smb" case, default-directory must have a share.
+ (when (tramp--test-smb-p)
+ (let ((default-directory
+ (concat (file-remote-p default-directory) "/")))
+ (should-not
+ (zerop (process-file "exit" nil nil nil "-not" "$true")))))
+ (should
+ (zerop
+ (if (tramp--test-smb-p)
+ ;; $true is converted to 1 in Powershell.
+ (process-file "exit" nil nil nil "-not" "$true")
+ (process-file "true"))))
+ (should-not
+ (zerop
+ (if (tramp--test-smb-p)
+ ;; $false is converted to 0 in Powershell.
+ (process-file "exit" nil nil nil "-not" "$false")
+ (process-file "false"))))
(should-not (zerop (process-file "binary-does-not-exist")))
;; Return exit code.
- (should (= 42 (process-file
- (tramp--test-shell-file-name) nil nil nil
- (tramp--test-shell-command-switch) "exit 42")))
+ ;; FIXME: Make it work with the shell also in the "smb" case.
+ (should
+ (= 42 (if (tramp--test-smb-p)
+ (process-file "exit" nil nil nil "42")
+ (process-file
+ (tramp--test-shell-file-name) nil nil nil
+ (tramp--test-shell-command-switch) "exit 42"))))
;; Return exit code in case the process is interrupted,
;; and there's no indication for a signal describing string.
- (unless (tramp--test-sshfs-p)
+ (unless (or (tramp--test-sshfs-p) (tramp--test-smb-p))
(let (process-file-return-signal-string)
(should
(= (+ 128 2)
@@ -5358,7 +5381,7 @@ This tests also `make-symbolic-link', `file-truename' and
`add-name-to-file'."
(tramp--test-shell-command-switch) "kill -2 $$")))))
;; Return string in case the process is interrupted and
;; there's an indication for a signal describing string.
- (unless (tramp--test-sshfs-p)
+ (unless (or (tramp--test-sshfs-p) (tramp--test-smb-p))
(let ((process-file-return-signal-string t))
(should
(string-match-p
@@ -5375,7 +5398,12 @@ This tests also `make-symbolic-link', `file-truename'
and `add-name-to-file'."
(with-temp-buffer
(write-region "foo" nil tmp-name)
(should (file-exists-p tmp-name))
- (should (zerop (process-file "ls" nil destination nil fnnd)))
+ (should
+ (zerop
+ (if (tramp--test-smb-p)
+ (process-file
+ (format "(ls %s).Name" fnnd) nil destination)
+ (process-file "ls" nil destination nil fnnd))))
(with-current-buffer
(if (bufferp destination) destination (current-buffer))
;; "ls" could produce colorized output.
@@ -5390,7 +5418,12 @@ This tests also `make-symbolic-link', `file-truename'
and `add-name-to-file'."
(goto-char (point-max)))
;; Second run. The output must be appended.
- (should (zerop (process-file "ls" nil destination t fnnd)))
+ (should
+ (zerop
+ (if (tramp--test-smb-p)
+ (process-file
+ (format "(ls %s).Name" fnnd) nil destination t)
+ (process-file "ls" nil destination t fnnd))))
(with-current-buffer
(if (bufferp destination) destination (current-buffer))
;; "ls" could produce colorized output.
@@ -5416,7 +5449,9 @@ This tests also `make-symbolic-link', `file-truename' and
`add-name-to-file'."
(write-region "foo" nil tmp-name)
(should (file-exists-p tmp-name))
(should (zerop (process-file "cat" tmp-name t)))
- (should (string-equal "foo" (buffer-string)))
+ (should
+ (string-equal
+ (if (tramp--test-smb-p) "foo\n" "foo") (buffer-string)))
(should-not (get-buffer-window (current-buffer) t))
(delete-file tmp-name)))
@@ -5443,7 +5478,9 @@ This tests also `make-symbolic-link', `file-truename' and
`add-name-to-file'."
(insert-file-contents tmp-name)
(should
(string-match-p
- (rx "cat:" (* nonl) " No such file or directory")
+ (rx (| (: "cat:" (* nonl) "No such file or directory")
+ ;; MS Windows.
+ (: "cat : Cannot find path")))
(buffer-string)))
(should-not (get-buffer-window (current-buffer) t))
(delete-file tmp-name)))))
@@ -5475,30 +5512,33 @@ This tests also `make-symbolic-link', `file-truename'
and `add-name-to-file'."
kill-buffer-query-functions command proc)
;; Simple process.
- (unwind-protect
- (with-temp-buffer
- (setq command '("cat")
- proc
- (apply #'start-file-process "test1" (current-buffer) command))
- (should (processp proc))
- (should (equal (process-status proc) 'run))
- (should (equal (process-get proc 'remote-command) command))
- (process-send-string proc "foo\n")
- (process-send-eof proc)
- ;; Read output.
- (with-timeout (10 (tramp--test-timeout-handler))
- (while (< (- (point-max) (point-min)) (length "foo"))
- (while (accept-process-output proc 0 nil t))))
- ;; Some `cat' implementations do not support the `cat -'
- ;; call. We skip then.
- (skip-unless
- (not
- (string-match-p (rx "cat: -: input file is output file\n")
- (buffer-string))))
- (should (string-match-p "foo" (buffer-string))))
+ ;; The "smb" method does not support stdin redirection.
+ (unless (tramp--test-smb-p)
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("cat")
+ proc
+ (apply
+ #'start-file-process "test1" (current-buffer) command))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
+ (process-send-string proc "foo\n")
+ (process-send-eof proc)
+ ;; Read output.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (< (- (point-max) (point-min)) (length "foo"))
+ (while (accept-process-output proc 0 nil t))))
+ ;; Some `cat' implementations do not support the `cat -'
+ ;; call. We skip then.
+ (skip-unless
+ (not
+ (string-match-p (rx "cat: -: input file is output file\n")
+ (buffer-string))))
+ (should (string-match-p "foo" (buffer-string))))
- ;; Cleanup.
- (ignore-errors (delete-process proc)))
+ ;; Cleanup.
+ (ignore-errors (delete-process proc))))
;; Simple process using a file.
(unwind-protect
@@ -5512,7 +5552,7 @@ This tests also `make-symbolic-link', `file-truename' and
`add-name-to-file'."
(should (equal (process-get proc 'remote-command) command))
;; Read output.
(with-timeout (10 (tramp--test-timeout-handler))
- (while (< (- (point-max) (point-min)) (length "foo"))
+ (while (not (string-match-p "foo" (buffer-string)))
(while (accept-process-output proc 0 nil t))))
(should (string-match-p "foo" (buffer-string))))
@@ -5522,24 +5562,33 @@ This tests also `make-symbolic-link', `file-truename'
and `add-name-to-file'."
(delete-file tmp-name)))
;; Process filter.
+ ;; The "smb" method does not support the "cat" stdin
+ ;; redirection. The "adb" method does not support late process
+ ;; filter setting for the "echo" command.
(unwind-protect
(with-temp-buffer
- (setq command '("cat")
+ (setq command (if (tramp--test-smb-p) '("echo" "foo") '("cat"))
proc
(apply #'start-file-process "test3" (current-buffer) command))
(should (processp proc))
- (should (equal (process-status proc) 'run))
+ ;(should (equal (process-status proc) 'run))
(should (equal (process-get proc 'remote-command) command))
(set-process-filter
proc
- (lambda (p s) (with-current-buffer (process-buffer p) (insert s))))
- (process-send-string proc "foo\n")
- (process-send-eof proc)
+ (lambda (p s)
+ (with-current-buffer
+ (process-buffer p)
+ (insert
+ (replace-regexp-in-string
+ (rx bol "foo" (? "\r") eol) "foobar" s)))))
+ (unless (tramp--test-smb-p)
+ (process-send-string proc "foo\n")
+ (process-send-eof proc))
;; Read output.
(with-timeout (10 (tramp--test-timeout-handler))
- (while (< (- (point-max) (point-min)) (length "foo"))
+ (while (not (string-match-p "foobar" (buffer-string)))
(while (accept-process-output proc 0 nil t))))
- (should (string-match-p "foo" (buffer-string))))
+ (should (string-match-p "foobar" (buffer-string))))
;; Cleanup.
(ignore-errors (delete-process proc)))
@@ -5668,36 +5717,39 @@ If UNSTABLE is non-nil, the test is tagged as
`:unstable'."
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((default-directory ert-remote-temporary-file-directory)
(tmp-name (tramp--test-make-temp-name nil quoted))
+ (inhibit-message (not (ignore-errors (edebug-mode))))
kill-buffer-query-functions command proc)
(should-not (apply #'make-process nil)) ; Use `apply' to avoid warnings.
;; Simple process.
- (unwind-protect
- (with-temp-buffer
- (setq command '("cat")
- proc
- (make-process
- :name "test1" :buffer (current-buffer) :command command
- :file-handler t))
- (should (processp proc))
- (should (equal (process-status proc) 'run))
- (should (equal (process-get proc 'remote-command) command))
- (process-send-string proc "foo\n")
- (process-send-eof proc)
- ;; Read output.
- (with-timeout (10 (tramp--test-timeout-handler))
- (while (< (- (point-max) (point-min)) (length "foo"))
- (while (accept-process-output proc 0 nil t))))
- ;; Some `cat' implementations do not support the `cat -'
- ;; call. We skip then.
- (skip-unless
- (not
- (string-match-p (rx "cat: -: input file is output file\n")
- (buffer-string))))
- (should (string-match-p "foo" (buffer-string))))
+ ;; The "smb" method does not support stdin redirection.
+ (unless (tramp--test-smb-p)
+ (unwind-protect
+ (with-temp-buffer
+ (setq command '("cat")
+ proc
+ (make-process
+ :name "test1" :buffer (current-buffer) :command command
+ :file-handler t))
+ (should (processp proc))
+ (should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
+ (process-send-string proc "foo\n")
+ (process-send-eof proc)
+ ;; Read output.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (< (- (point-max) (point-min)) (length "foo"))
+ (while (accept-process-output proc 0 nil t))))
+ ;; Some `cat' implementations do not support the `cat -'
+ ;; call. We skip then.
+ (skip-unless
+ (not
+ (string-match-p (rx "cat: -: input file is output file\n")
+ (buffer-string))))
+ (should (string-match-p "foo" (buffer-string))))
- ;; Cleanup.
- (ignore-errors (delete-process proc)))
+ ;; Cleanup.
+ (ignore-errors (delete-process proc))))
;; Simple process using a file.
(unwind-protect
@@ -5713,7 +5765,7 @@ If UNSTABLE is non-nil, the test is tagged as
`:unstable'."
(should (equal (process-get proc 'remote-command) command))
;; Read output.
(with-timeout (10 (tramp--test-timeout-handler))
- (while (< (- (point-max) (point-min)) (length "foo"))
+ (while (not (string-match-p "foo" (buffer-string)))
(while (accept-process-output proc 0 nil t))))
(should (string-match-p "foo" (buffer-string))))
@@ -5725,24 +5777,26 @@ If UNSTABLE is non-nil, the test is tagged as
`:unstable'."
;; Process filter.
(unwind-protect
(with-temp-buffer
- (setq command '("cat")
+ (setq command '("echo" "foo")
proc
(make-process
:name "test3" :buffer (current-buffer) :command command
:filter
(lambda (p s)
- (with-current-buffer (process-buffer p) (insert s)))
+ (with-current-buffer
+ (process-buffer p)
+ (insert
+ (replace-regexp-in-string
+ (rx bol "foo" (? "\r") eol) "foobar" s))))
:file-handler t))
(should (processp proc))
- (should (equal (process-status proc) 'run))
+ ;(should (equal (process-status proc) 'run))
(should (equal (process-get proc 'remote-command) command))
- (process-send-string proc "foo\n")
- (process-send-eof proc)
;; Read output.
(with-timeout (10 (tramp--test-timeout-handler))
- (while (not (string-match-p "foo" (buffer-string)))
+ (while (not (string-match-p "foobar" (buffer-string)))
(while (accept-process-output proc 0 nil t))))
- (should (string-match-p "foo" (buffer-string))))
+ (should (string-match-p "foobar" (buffer-string))))
;; Cleanup.
(ignore-errors (delete-process proc)))
@@ -5819,13 +5873,19 @@ If UNSTABLE is non-nil, the test is tagged as
`:unstable'."
(with-current-buffer stderr
(with-timeout (10 (tramp--test-timeout-handler))
(while (not (string-match-p
- "No such file or directory" (buffer-string)))
- (while (accept-process-output
- (get-buffer-process stderr) 0 nil t))))
+ (rx (| "No such file or directory"
+ "Cannot find path"))
+ (buffer-string)))
+ (when-let* ((p (or (get-buffer-process stderr)
+ auto-revert-notify-watch-descriptor))
+ ((processp p)))
+ (while (accept-process-output p 0 nil t)))))
(delete-process proc)
(should
(string-match-p
- (rx "cat:" (* nonl) " No such file or directory")
+ (rx (| (: "cat:" (* nonl) "No such file or directory")
+ ;; MS Windows.
+ (: "cat : Cannot find path")))
(buffer-string)))))
;; Cleanup.
@@ -5845,13 +5905,19 @@ If UNSTABLE is non-nil, the test is tagged as
`:unstable'."
(should (equal (process-get proc 'remote-command) command))
;; Read stderr.
(with-timeout (10 (tramp--test-timeout-handler))
- (while (accept-process-output proc nil nil t)))
+ (let ((remote-file-name-inhibit-cache t))
+ (while
+ (or (not (file-exists-p tmp-name))
+ (zerop
+ (file-attribute-size (file-attributes tmp-name)))))))
(delete-process proc)
(with-temp-buffer
(insert-file-contents tmp-name)
(should
(string-match-p
- (rx "cat:" (* nonl) " No such file or directory")
+ (rx (| (: "cat:" (* nonl) "No such file or directory")
+ ;; MS Windows.
+ (: "cat : Cannot find path")))
(buffer-string)))))
;; Cleanup.
@@ -6093,9 +6159,11 @@ If UNSTABLE is non-nil, the test is tagged as
`:unstable'."
INPUT, if non-nil, is a string sent to the process."
(let ((proc (async-shell-command command output-buffer error-buffer))
(delete-exited-processes t))
- (should (equal (process-get proc 'remote-command)
- (with-connection-local-variables
- `(,shell-file-name ,shell-command-switch ,command))))
+ ;; `tramp-smb-handle-shell-command' modifies the command.
+ (unless (tramp--test-smb-p)
+ (should (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command)))))
(cl-letf (((symbol-function #'shell-command-sentinel) #'ignore))
(when (stringp input)
(process-send-string proc input))
@@ -6139,7 +6207,9 @@ INPUT, if non-nil, is a string sent to the process."
(should (file-exists-p tmp-name))
(funcall
this-shell-command
- (format "ls %s" (file-name-nondirectory tmp-name))
+ (format
+ (if (tramp--test-smb-p) "(ls %s).Name" "ls %s")
+ (file-name-nondirectory tmp-name))
(current-buffer))
;; "ls" could produce colorized output.
(goto-char (point-min))
@@ -6154,7 +6224,8 @@ INPUT, if non-nil, is a string sent to the process."
(ignore-errors (delete-file tmp-name)))
;; Test `{async-}shell-command' with error buffer.
- (unless (tramp-direct-async-process-p)
+ ;; Method "smb" does not support ">&2" construct.
+ (unless (or (tramp--test-smb-p) (tramp-direct-async-process-p))
(let ((stderr (generate-new-buffer "*stderr*")))
(unwind-protect
(with-temp-buffer
@@ -6170,7 +6241,8 @@ INPUT, if non-nil, is a string sent to the process."
(ignore-errors (kill-buffer stderr))))))
;; Test sending string to `async-shell-command'.
- (when (tramp--test-asynchronous-processes-p)
+ (when (and (not (tramp--test-smb-p))
+ (tramp--test-asynchronous-processes-p))
(unwind-protect
(with-temp-buffer
(write-region "foo" nil tmp-name)
@@ -6550,6 +6622,8 @@ INPUT, if non-nil, is a string sent to the process."
:tags '(:expensive-test :tramp-asynchronous-processes)
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-supports-processes-p))
+ ;; FIXME: Make it work despite if ~/.emacs_powershell.
+ (skip-unless (not (tramp--test-smb-p)))
(let ((default-directory ert-remote-temporary-file-directory)
explicit-shell-file-name kill-buffer-query-functions
@@ -7552,13 +7626,13 @@ This requires restrictions of file name syntax."
(defun tramp--test-supports-processes-p ()
"Return whether the method under test supports external processes."
(unless (tramp--test-crypt-p)
- ;; We use it to enable/disable tests in a given test run, for
- ;; example for remote processes on MS Windows.
- (if (tramp-connection-property-p
- tramp-test-vec "tramp--test-supports-processes-p")
- (tramp-get-connection-property
- tramp-test-vec "tramp--test-supports-processes-p")
- (or (tramp--test-adb-p) (tramp--test-sh-p) (tramp--test-sshfs-p)))))
+ (or (tramp--test-adb-p) (tramp--test-sh-p) (tramp--test-sshfs-p)
+ (and (tramp--test-smb-p)
+ (file-writable-p
+ (file-name-concat
+ (file-remote-p ert-remote-temporary-file-directory)
+ ;; We check a directory on the "ADMIN$" share.
+ "ADMIN$" "Boot"))))))
(defun tramp--test-supports-set-file-modes-p ()
"Return whether the method under test supports setting file modes."
@@ -7728,7 +7802,11 @@ This requires restrictions of file name syntax."
;; `default-directory' with special characters. See
;; Bug#53846.
(when (and (tramp--test-expensive-test-p)
- (tramp--test-supports-processes-p))
+ (tramp--test-supports-processes-p)
+ ;; FIXME: tramp-smb.el should implement this.
+ (not (and (tramp--test-smb-p)
+ (string-match-p
+ (rx (or (any "[$") (not ascii))) file1))))
(let ((default-directory file1))
(dolist (this-shell-command
(append
@@ -7988,6 +8066,7 @@ process sentinels. They shall not disturb each other."
(skip-unless (not (tramp--test-telnet-p)))
(skip-unless (not (tramp--test-box-p)))
(skip-unless (not (tramp--test-windows-nt-p)))
+ (skip-unless (not (tramp--test-smb-p)))
(with-timeout
(tramp--test-asynchronous-requests-timeout (tramp--test-timeout-handler))
@@ -8912,7 +8991,10 @@ Since it unloads Tramp, it shall be the last test to
run."
(require 'tramp)
(require 'tramp-archive)
(should (featurep 'tramp))
- (should (featurep 'tramp-archive)))
+ (should (featurep 'tramp-archive))
+
+ ;; Disabled further tests.
+ (setq tramp--test-enabled-checked '(t)))
(defun tramp-test-all (&optional interactive)
"Run all tests for \\[tramp].
@@ -8944,6 +9026,7 @@ If INTERACTIVE is non-nil, the tests are run
interactively."
;; * Implement `tramp-test31-interrupt-process' and
;; `tramp-test31-signal-process' for "adb", "sshfs" and for direct
;; async processes. Check, why they don't run stable.
+;; * Fix the limitations for "smb" in `tramp--test-check-files'.
;; * Check, why `tramp-test45-asynchronous-requests' often fails. The
;; famous reentrant error?
;; * Check, why direct async processes do not work for
diff --git a/texi/tramp.texi b/texi/tramp.texi
index 4334e89e65..f53abb5c22 100644
--- a/texi/tramp.texi
+++ b/texi/tramp.texi
@@ -3176,6 +3176,14 @@ connection cleanup or on Emacs exiting.
@subsection @option{rclone} setup
@cindex rclone setup
+Check, that your @command{rclone} program is compiled with mount
+support. Call @samp{rclone mount} and check for an error message.
+
+Sometimes, the saved configuration expires. In this case, you must
+renew it with the command @samp{rclone config reconnect
+@var{remote}:}, with @var{remote} being the name of your configured
+system storage.
+
The default arguments of the @command{rclone} operations
@command{mount}, @command{copyto}, @command{moveto} and
@command{about} are declared in the variable @code{tramp-methods} as
@@ -4438,7 +4446,7 @@ uid=0(root) gid=0(root) groups=0(root)
@anchor{Running a debugger on a remote host}
@subsection Running a debugger on a remote host
-@cindex @file{gud.el}
+@cindex @file{gud.el} file
@cindex @code{gdb}
@cindex @code{perldb}
@@ -4489,38 +4497,77 @@ Arguments of the program to be debugged must be
literal, can take
relative or absolute paths, but not remote paths.
+@anchor{Running remote processes on MS Windows hosts}
@subsection Running remote processes on MS Windows hosts
@cindex @command{winexe}
@cindex @command{powershell}
-@command{winexe} runs processes on a remote MS Windows host, and
-@value{tramp} can use it for @code{process-file} and
-@code{start-file-process}.
+@strong{Note}: This is an experimental feature.
-@code{tramp-smb-winexe-program} specifies the local @command{winexe}
-command. Powershell V2.0 on the remote host is required to run
-processes triggered from @value{tramp}.
+The program @command{winexe} from the Samba suite runs processes on a
+remote MS Windows host, and @value{tramp} uses it for
+@code{make-process}, @code{process-file} and
+@code{start-file-process}. It does not work for remote Samba servers.
-@code{explicit-shell-file-name} and @code{explicit-*-args} have to
-be set properly so @kbd{M-x shell @key{RET}} can open a proper remote
-shell on a MS Windows host. To open @command{cmd}, set it as follows:
+@c FIXME: Verify powershell version.
+@vindex tramp-smb-winexe-program
+@code{tramp-smb-winexe-program} specifies the local @command{winexe}
+program. Powershell V2.0 on the remote MS Windows host is required to
+run processes triggered from @value{tramp}.
+
+@c https://woshub.com/enable-remote-access-to-admin-shares-in-workgroup/
+The remote user on the remote MS Windows host must be member of the
+local computer Administrators group of that remote MS Windows host.
+Since @command{winexe} uses the administrative share @file{ADMIN$} of
+that remote MS Windows host, the remote MS Windows host must be either
+part of an Active Directory domain, or the Remote UAC (User Account
+Control for remote connections) must be disabled. The latter can be
+achieved by creating the
+@samp{HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\
LocalAccountTokenFilterPolicy}
+parameter in the MS Windows registry as DWORD (32-bit) with the value 1.
+
+Check, that the default remote temporary file directory is usable.
+Otherwise, change it, for example (with adapted @t{"user"} and
+@t{"host"}):
@lisp
-@group
-(setq explicit-shell-file-name "cmd"
- explicit-cmd-args '("/q"))
-@end group
+(add-to-list 'tramp-connection-properties
+ (list (regexp-quote "host")
+ "tmpdir" "/Users/user/AppData/Local/Temp"))
@end lisp
@noindent
-To open @command{powershell} as a remote shell, use this:
+@xref{Predefined connection information}.
-@lisp
-@group
-(setq explicit-shell-file-name "powershell"
- explicit-powershell-args '("-file" "-"))
-@end group
-@end lisp
+Redirection from stdin is not supported.
+
+@vindex auto-revert-remote-files
+If you use a remote asynchronous process with a separate error buffer,
+you must ensure that remote files can be auto-reverted. Set user
+option @code{auto-revert-remote-files} to a non-@code{nil} value.
+
+@vindex tramp-smb-connection-local-powershell-profile
+@vindex tramp-smb-prompt
+@cindex @file{.emacs_powershell} file
+@code{shell} and @code{shell-command} are configured to use
+@command{powershell} on the remote MS Windows host. If you want to
+change this, consider using another connection-local profile but
+@code{tramp-smb-connection-local-powershell-profile}.
+
+If you run a remote @code{shell}, you might consider to add the
+following line to your local @file{~/.emacs_powershell} file:
+
+@smallexample
+function prompt @{ "PS " + ((Get-Location).Path | Convert-Path) + "> " @}
+@end smallexample
+
+@noindent
+Note, that the configured prompt must match @code{tramp-smb-prompt}.
+
+If you run a remote @code{shell-command}, you must use
+@command{powershell} syntax. For example, if you want to run a shell
+command from @code{dired}, use the command @t{"(ls * ).Name"} instead
+of @t{"ls"}.
@subsection Remote process connection type
@@ -5500,12 +5547,12 @@ Disable excessive traces. Set @code{tramp-verbose} to
3 or lower,
default being 3. Increase trace levels temporarily when hunting for
bugs.
-@c @item
-@c Use a package with @value{tramp} specific implementation of high-level
-@c operations. For example, the GNU ELPA package @file{tramp-hlo}
-@c implements specialized versions of @code{dir-locals--all-files},
-@c @code{locate-dominating-file} and @code{dir-locals-find-file} for
-@c @value{tramp}'s @code{tramp-sh} backend (@pxref{New operations}).
+@item
+Use a package with @value{tramp} specific implementation of high-level
+operations. For example, the GNU ELPA package @file{tramp-hlo}
+implements specialized versions of @code{dir-locals--all-files},
+@code{locate-dominating-file} and @code{dir-locals-find-file} for
+@value{tramp}'s @code{tramp-sh} backend (@pxref{New operations}).
@end itemize
@@ -6855,6 +6902,12 @@ Shell scripts intended for the @code{tramp-sh} backend
are used as a
format string. They must observe the restrictions for format
specifiers, as documented in @code{tramp-expand-script}.
+An example implementing this mechanism is the GNU ELPA package
+@file{tramp-hlo}. It implements specialized versions of
+@code{dir-locals--all-files}, @code{locate-dominating-file} and
+@code{dir-locals-find-file} for @value{tramp}'s @code{tramp-sh}
+backend.
+
@node Traces and Profiles
@chapter How to Customize Traces
diff --git a/texi/trampver.texi b/texi/trampver.texi
index da53b5c62d..ee4d5b2a35 100644
--- a/texi/trampver.texi
+++ b/texi/trampver.texi
@@ -7,7 +7,7 @@
@c In the Tramp GIT, the version number and the bug report address
@c are auto-frobbed from configure.ac.
-@set trampver 2.8.0.5
+@set trampver 2.8.1
@set trampurl https://www.gnu.org/software/tramp/
@set tramp-bug-report-address tramp-devel@@gnu.org
@set emacsver 28.1
diff --git a/tramp-adb.el b/tramp-adb.el
index 5d6c053868..99fcacd8de 100644
--- a/tramp-adb.el
+++ b/tramp-adb.el
@@ -266,11 +266,7 @@ arguments to pass to the OPERATION."
(with-parsed-tramp-file-name filename nil
(tramp-convert-file-attributes v localname id-format
(and
- (tramp-adb-send-command-and-check
- v (format "(%s -d -l %s; echo tramp_exit_status $?) | cat"
- (tramp-adb-get-ls-command v)
- (tramp-shell-quote-argument localname))
- nil t)
+ (tramp-adb-do-ls v "-d -l" localname)
(with-current-buffer (tramp-get-buffer v)
(tramp-adb-sh-fix-ls-output)
(cdar (tramp-do-parse-file-attributes-with-ls v)))))))
@@ -320,26 +316,21 @@ arguments to pass to the OPERATION."
(tramp-skeleton-directory-files-and-attributes
directory full match nosort id-format count
(with-current-buffer (tramp-get-buffer v)
- (when (tramp-adb-send-command-and-check
- v (format "(%s -a -l %s; echo tramp_exit_status $?) | cat"
- (tramp-adb-get-ls-command v)
- (tramp-shell-quote-argument localname))
- nil t)
- ;; We insert also filename/. and filename/.., because "ls"
- ;; doesn't on some file systems, like "sdcard".
- (unless (search-backward-regexp (rx "." eol) nil t)
- (narrow-to-region (point-max) (point-max))
- (tramp-adb-send-command
- v (format "%s -d -a -l %s %s | cat"
- (tramp-adb-get-ls-command v)
- (tramp-shell-quote-argument
- (file-name-concat localname "."))
- (tramp-shell-quote-argument
- (file-name-concat localname ".."))))
- (replace-regexp-in-region
- (rx (literal (file-name-unquote (file-name-as-directory localname))))
- "" (point-min))
- (widen)))
+ (save-restriction
+ (when (tramp-adb-do-ls v "-a -l" localname)
+ ;; We insert also filename/. and filename/.., because "ls"
+ ;; doesn't on some file systems, like "sdcard".
+ (goto-char (point-max))
+ (unless (search-backward-regexp (rx "." eol) nil t)
+ (narrow-to-region (point-max) (point-max))
+ (when (tramp-adb-do-ls
+ v "-d -a -l"
+ (file-name-concat localname ".")
+ (file-name-concat localname ".."))
+ (replace-regexp-in-region
+ (rx
+ (literal (file-name-unquote (file-name-as-directory
localname))))
+ "" (point-min))))))
(tramp-adb-sh-fix-ls-output)
(tramp-do-parse-file-attributes-with-ls v))))
@@ -366,6 +357,24 @@ arguments to pass to the OPERATION."
"ls --color=never")
(t "ls"))))
+;; "ls" returns exit code 1 for permission problems and alike. Ignore
+;; those messages. (Bug#80054)
+(defun tramp-adb-do-ls (vec switches &rest filenames)
+ "Call \"ls\" on a remote adb device with SWITCHES.
+Return non-il if the call was successful. Ignore return code 1 stderr
+output."
+ (ignore-errors
+ (and-let*
+ ((ret (tramp-adb-send-command-and-check
+ vec (format
+ "(%s %s %s 2>%s; echo tramp_exit_status $?) | cat"
+ (tramp-adb-get-ls-command vec) switches
+ (mapconcat #'tramp-shell-quote-argument filenames " ")
+ (tramp-get-remote-null-device vec))
+ t t))
+ ((natnump ret))
+ ((<= ret 1))))))
+
(defun tramp-adb-sh-fix-ls-output (&optional sort-by-time)
"Insert dummy 0 in empty size columns.
Android's \"ls\" command doesn't insert size column for directories:
@@ -446,22 +455,17 @@ Emacs dired can't find files."
filename
(with-parsed-tramp-file-name (expand-file-name directory) nil
(with-tramp-file-property v localname "file-name-all-completions"
- (unless (tramp-adb-send-command-and-check
- v (format "(%s -a %s; echo tramp_exit_status $?) | cat"
- (tramp-adb-get-ls-command v)
- (tramp-shell-quote-argument localname))
- nil t)
- (erase-buffer))
- (mapcar
- (lambda (f)
- (if (file-directory-p (expand-file-name f directory))
- (file-name-as-directory f)
- f))
- (with-current-buffer (tramp-get-buffer v)
- (mapcar
- (lambda (l)
- (and (not (string-match-p (rx bol (* blank) eol) l)) l))
- (split-string (buffer-string) "\n" 'omit)))))))))
+ (when (tramp-adb-do-ls v "-a" localname)
+ (mapcar
+ (lambda (f)
+ (if (file-directory-p (expand-file-name f directory))
+ (file-name-as-directory f)
+ f))
+ (with-current-buffer (tramp-get-buffer v)
+ (mapcar
+ (lambda (l)
+ (and (not (string-match-p (rx bol (* blank) eol) l)) l))
+ (split-string (buffer-string) "\n" 'omit))))))))))
(defun tramp-adb-handle-file-local-copy (filename)
"Like `file-local-copy' for Tramp files."
@@ -756,6 +760,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are
completely ignored."
(with-current-buffer outbuf
(insert-buffer-substring (tramp-get-connection-buffer v)))
(when (and display (get-buffer-window outbuf t)) (redisplay))))
+
;; When the user did interrupt, we should do it also. We use
;; return code -1 as marker.
(quit
diff --git a/tramp-sh.el b/tramp-sh.el
index 5ed3e91da2..488f7e4919 100644
--- a/tramp-sh.el
+++ b/tramp-sh.el
@@ -3369,6 +3369,7 @@ will be used."
(insert
(tramp-get-buffer-string (tramp-get-connection-buffer v))))
(when (and display (get-buffer-window outbuf t)) (redisplay))))
+
;; When the user did interrupt, we should do it also. We use
;; return code -1 as marker.
(quit
@@ -5229,7 +5230,7 @@ If there is a modified buffer, retry it after 60 seconds."
(and-let* (((or (buffer-modified-p buf)
(with-current-buffer buf
;; We don't know whether autorevert.el has
- ;; been loaded alreaddy.
+ ;; been loaded already.
(tramp-compat-funcall 'auto-revert-active-p))))
(bfn (buffer-file-name buf))
(v (tramp-ensure-dissected-file-name bfn))
diff --git a/tramp-smb.el b/tramp-smb.el
index fdda945f12..2013c3980d 100644
--- a/tramp-smb.el
+++ b/tramp-smb.el
@@ -239,6 +239,7 @@ See `tramp-actions-before-shell' for more info.")
. tramp-handle-directory-files-and-attributes)
(dired-compress-file . ignore)
(dired-uncache . tramp-handle-dired-uncache)
+ ;; TODO: Add implementation.
(exec-path . ignore)
(expand-file-name . tramp-smb-handle-expand-file-name)
(file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
@@ -286,7 +287,7 @@ See `tramp-actions-before-shell' for more info.")
(make-directory-internal . ignore)
(make-lock-file-name . tramp-handle-make-lock-file-name)
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
- (make-process . ignore)
+ (make-process . tramp-smb-handle-make-process)
(make-symbolic-link . tramp-smb-handle-make-symbolic-link)
(memory-info . ignore)
(process-attributes . ignore)
@@ -297,8 +298,8 @@ See `tramp-actions-before-shell' for more info.")
(set-file-selinux-context . ignore)
(set-file-times . tramp-smb-handle-set-file-times)
(set-visited-file-modtime . tramp-handle-set-visited-file-modtime)
- (shell-command . tramp-handle-shell-command)
- (start-file-process . tramp-smb-handle-start-file-process)
+ (shell-command . tramp-smb-handle-shell-command)
+ (start-file-process . tramp-handle-start-file-process)
(substitute-in-file-name . tramp-smb-handle-substitute-in-file-name)
(temporary-file-directory . tramp-handle-temporary-file-directory)
(tramp-get-home-directory . tramp-smb-handle-get-home-directory)
@@ -1266,6 +1267,121 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are
completely ignored."
(unless (file-directory-p dir)
(tramp-error v 'file-error "Couldn't make directory %s" dir))))
+(defvar tramp-smb-matching-line nil
+ "Regexp to delete from current buffer.")
+
+(defun tramp-smb-delete-matching-lines (string)
+ "Delete matching lines in current buffer.
+Remove this function from `comint-preoutput-filter-functions'."
+ (save-excursion
+ (goto-char (point-min))
+ (unless
+ (zerop (delete-matching-lines tramp-smb-matching-line))
+ (setq tramp-smb-matching-line nil)
+ (remove-hook 'comint-preoutput-filter-functions
+ #'tramp-smb-delete-matching-lines 'local))
+ string))
+
+;; We use BUFFER also as connection buffer during setup. Because of
+;; this, its original contents must be saved, and restored once
+;; connection has been setup.
+(defun tramp-smb-handle-make-process (&rest args)
+ "Like `make-process' for Tramp files.
+If method parameter `tramp-direct-async' and connection-local variable
+`tramp-direct-async-process' are non-nil, an alternative implementation
+will be used."
+ (if (tramp-direct-async-process-p args)
+ (apply #'tramp-handle-make-process args)
+ (tramp-skeleton-make-process args nil t
+ (let* ((command (string-join command " "))
+ ;; STDERR can also be a file name.
+ (tmpstderr
+ (and stderr
+ (tramp-unquote-file-local-name
+ (if (stringp stderr)
+ stderr (tramp-make-tramp-temp-name v)))))
+ (remote-tmpstderr
+ (and tmpstderr (tramp-make-tramp-file-name v tmpstderr)))
+ (bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
+ p)
+ (if tmpstderr
+ (setq command (format "%s 2>//%s%s" command host tmpstderr)))
+
+ ;; Handle error buffer.
+ (when (bufferp stderr)
+ (make-empty-file remote-tmpstderr)
+ (with-current-buffer stderr
+ (setq buffer-read-only nil
+ default-directory (file-name-directory remote-tmpstderr))
+ (setq-local buffer-file-name remote-tmpstderr
+ auto-revert-notify-exclude-dir-regexp
+ "nothing-to-be-excluded"
+ create-lockfiles t)
+ (set-visited-file-modtime)
+ (set-buffer-modified-p nil)
+ (auto-save-mode -1)
+ (auto-save-visited-mode -1)
+ (auto-revert-tail-mode 1)))
+
+ (with-tramp-saved-connection-properties
+ v '(" process-name" " process-buffer")
+ (unwind-protect
+ (save-excursion
+ (save-restriction
+ ;; Set the new process properties.
+ (tramp-set-connection-property v " process-name" name)
+ (tramp-set-connection-property v " process-buffer" buffer)
+ ;; Activate narrowing in order to save BUFFER contents.
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (let ((buffer-undo-list t))
+ (narrow-to-region (point-max) (point-max))
+ (tramp-smb-call-winexe v)
+ (tramp-message v 6 "%s" command)
+ (tramp-send-string v command)
+ (setq
+ tramp-smb-matching-line (rx bol (literal command) eol))
+ (add-hook 'comint-preoutput-filter-functions
+ #'tramp-smb-delete-matching-lines nil 'local)))
+ (setq p (tramp-get-connection-process v))
+ ;; Set sentinel and filter.
+ (when sentinel
+ (set-process-sentinel p sentinel))
+ (when filter
+ (set-process-filter p filter))
+ (process-put p 'remote-command orig-command)
+ ;; Set query flag and process marker for this
+ ;; process. We ignore errors, because the process
+ ;; could have finished already.
+ (ignore-errors
+ (set-process-query-on-exit-flag p (null noquery))
+ (set-marker (process-mark p) (point)))
+ ;; We must flush them here already; otherwise
+ ;; `delete-file' will fail.
+ (tramp-flush-connection-property v " process-name")
+ (tramp-flush-connection-property v " process-buffer")
+ ;; Stop auto-revert. Delete stderr file.
+ (when (bufferp stderr)
+ (add-function
+ :after (process-sentinel p)
+ (lambda (_proc _msg)
+ (with-current-buffer stderr
+ (auto-revert-tail-mode -1)
+ (let ((remote-file-name-inhibit-locks t))
+ (revert-buffer nil 'noconfirm)))
+ (ignore-errors
+ (delete-file remote-tmpstderr)))))
+ ;; Return value.
+ p))
+
+ ;; Save exit.
+ ;; FIXME: Does `tramp-get-connection-buffer' return the proper
value?
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (if (string-search tramp-temp-buffer-name (buffer-name))
+ (progn
+ (set-process-buffer (tramp-get-connection-process v) nil)
+ (kill-buffer (current-buffer)))
+ (set-buffer-modified-p bmp)))))))))
+
(defun tramp-smb-handle-make-symbolic-link
(target linkname &optional ok-if-already-exists)
"Like `make-symbolic-link' for Tramp files."
@@ -1286,120 +1402,66 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are
completely ignored."
(defun tramp-smb-handle-process-file
(program &optional infile destination display &rest args)
"Like `process-file' for Tramp files."
- ;; The implementation is not complete yet.
- (when (and (numberp destination) (zerop destination))
- (error "Implementation does not handle immediate return"))
-
- (with-parsed-tramp-file-name (expand-file-name default-directory) nil
- (let* ((name (file-name-nondirectory program))
- (name1 name)
- (i 0)
- input tmpinput outbuf command ret)
-
- ;; Determine input.
- (when infile
- (setq infile (file-name-unquote (expand-file-name infile)))
- (if (tramp-equal-remote default-directory infile)
- ;; INFILE is on the same remote host.
- (setq input (tramp-unquote-file-local-name infile))
- ;; INFILE must be copied to remote host.
- (setq input (tramp-make-tramp-temp-file v)
- tmpinput (tramp-make-tramp-file-name v input))
- (copy-file infile tmpinput t))
- ;; Transform input into a filename powershell does understand.
- (setq input (format "//%s%s" host input)))
-
- ;; Determine output.
- (cond
- ;; Just a buffer.
- ((bufferp destination)
- (setq outbuf destination))
- ;; A buffer name.
- ((stringp destination)
- (setq outbuf (get-buffer-create destination)))
- ;; (REAL-DESTINATION ERROR-DESTINATION)
- ((consp destination)
- ;; output.
- (cond
- ((bufferp (car destination))
- (setq outbuf (car destination)))
- ((stringp (car destination))
- (setq outbuf (get-buffer-create (car destination))))
- ((car destination)
- (setq outbuf (current-buffer))))
- ;; stderr.
- (tramp-warning v "%s" "STDERR not supported"))
- ;; 't
- (destination
- (setq outbuf (current-buffer))))
+ (tramp-skeleton-process-file program infile destination display args
+ (let ((name
+ (string-replace "*tramp" "*tramp process" (tramp-buffer-name v))))
+ ;; Transform input and stderr into a filename powershell does understand.
+ (when input
+ (setq input
+ (and (not (string-equal input (tramp-get-remote-null-device v)))
+ (format
+ "//%s%s" host (tramp-smb-shell-quote-argument input)))))
+ (when stderr
+ (setq stderr
+ (and (not (string-equal stderr (tramp-get-remote-null-device v)))
+ (format
+ "//%s%s" host (tramp-smb-shell-quote-argument stderr)))))
;; Construct command.
(setq command (string-join (cons program args) " ")
+ command (if stderr
+ (format "%s 2>%s" command stderr)
+ command)
command (if input
- (format
- "get-content %s | & %s"
- (tramp-smb-shell-quote-argument input) command)
- (format "& %s" command)))
-
- (while (get-process name1)
- ;; NAME must be unique as process name.
- (setq i (1+ i)
- name1 (format "%s<%d>" name i)))
+ (format "Get-Content %s | & %s" input command)
+ command))
;; Call it.
(condition-case nil
(with-tramp-saved-connection-properties
v '(" process-name" " process-buffer")
;; Set the new process properties.
- (tramp-set-connection-property v " process-name" name1)
+ (tramp-set-connection-property v " process-name" name)
(tramp-set-connection-property
- v " process-buffer"
- (or outbuf (generate-new-buffer tramp-temp-buffer-name)))
- (tramp-flush-connection-property v " process-exit-status")
+ ;; v " process-buffer"
+ ;; (or outbuf (generate-new-buffer tramp-temp-buffer-name)))
+ v " process-buffer" (generate-new-buffer tramp-temp-buffer-name))
(with-current-buffer (tramp-get-connection-buffer v)
;; Preserve buffer contents.
(narrow-to-region (point-max) (point-max))
(tramp-smb-call-winexe v)
- (when (tramp-smb-get-share v)
- (tramp-smb-send-command
- v (format "cd //%s%s" host
- (tramp-smb-shell-quote-argument
- (file-name-directory localname)))))
- (tramp-smb-send-command v command)
- ;; Preserve command output.
- (narrow-to-region (point-max) (point-max))
- (let ((p (tramp-get-connection-process v)))
- (tramp-smb-send-command v "exit $lasterrorcode")
- (while (process-live-p p)
- (sleep-for 0.1)
- (setq ret (process-exit-status p))))
- (delete-region (point-min) (point-max))
- (widen)))
+ (tramp-flush-connection-property v " process-exit-status")
+ (tramp-smb-send-command
+ v (format "%s; exit -not $?" command))
+ (while (not (setq ret (tramp-get-connection-property
+ v " process-exit-status")))
+ (sleep-for 0.1))
+ (unless (natnump ret) (setq ret 1))
+ ;; We should add the output anyway.
+ (when outbuf
+ (with-current-buffer outbuf
+ (insert-buffer-substring (tramp-get-connection-buffer v)))
+ (when (and display (get-buffer-window outbuf t)) (redisplay)))))
;; When the user did interrupt, we should do it also. We use
;; return code -1 as marker.
(quit
+ (kill-buffer (tramp-get-connection-buffer v))
(setq ret -1))
;; Handle errors.
(error
- (setq ret 1)))
-
- ;; We should redisplay the output.
- (when (and display outbuf (get-buffer-window outbuf t)) (redisplay))
-
- ;; Cleanup. We remove all file cache values for the connection,
- ;; because the remote process could have changed them.
- (when tmpinput (delete-file tmpinput))
- ;; FIXME: Does connection-property " process-buffer" still exist?
- (unless outbuf
- (kill-buffer (tramp-get-connection-property v " process-buffer")))
- (when process-file-side-effects
- (tramp-flush-directory-properties v "/"))
-
- ;; Return exit status.
- (if (equal ret -1)
- (keyboard-quit)
- ret))))
+ (kill-buffer (tramp-get-connection-buffer v))
+ (setq ret 1))))))
(defun tramp-smb-handle-rename-file
(filename newname &optional ok-if-already-exists)
@@ -1543,62 +1605,18 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are
completely ignored."
(tramp-smb-shell-quote-localname v)
(format-time-string "%Y:%m:%d-%H:%M:%S" (tramp-defined-time time))))))
-;; We use BUFFER also as connection buffer during setup. Because of
-;; this, its original contents must be saved, and restored once
-;; connection has been setup.
-(defun tramp-smb-handle-start-file-process (name buffer program &rest args)
- "Like `start-file-process' for Tramp files."
- (with-parsed-tramp-file-name default-directory nil
- (let* ((buffer
- (if buffer
- (get-buffer-create buffer)
- ;; BUFFER can be nil. We use a temporary buffer.
- (generate-new-buffer tramp-temp-buffer-name)))
- (command (string-join (cons program args) " "))
- (bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
- (name1 name)
- (i 0)
- p)
- (unwind-protect
- (with-tramp-saved-connection-properties
- v '(" process-name" " process-buffer")
- (save-excursion
- (save-restriction
- (while (get-process name1)
- ;; NAME must be unique as process name.
- (setq i (1+ i)
- name1 (format "%s<%d>" name i)))
- ;; Set the new process properties.
- (tramp-set-connection-property v " process-name" name1)
- (tramp-set-connection-property v " process-buffer" buffer)
- ;; Activate narrowing in order to save BUFFER contents.
- (with-current-buffer (tramp-get-connection-buffer v)
- (let ((buffer-undo-list t))
- (narrow-to-region (point-max) (point-max))
- (tramp-smb-call-winexe v)
- (when (tramp-smb-get-share v)
- (tramp-smb-send-command
- v (format
- "cd //%s%s"
- host
- (tramp-smb-shell-quote-argument
- (file-name-directory localname)))))
- (tramp-message v 6 "(%s); exit" command)
- (tramp-send-string v command)))
- (setq p (tramp-get-connection-process v))
- (when program
- (process-put p 'remote-command (cons program args)))
- ;; Return value.
- p)))
-
- ;; Save exit.
- ;; FIXME: Does `tramp-get-connection-buffer' return the proper value?
- (with-current-buffer (tramp-get-connection-buffer v)
- (if (string-search tramp-temp-buffer-name (buffer-name))
- (progn
- (set-process-buffer (tramp-get-connection-process v) nil)
- (kill-buffer (current-buffer)))
- (set-buffer-modified-p bmp)))))))
+(defun tramp-smb-handle-shell-command
+ (command &optional output-buffer error-buffer)
+ "Like `shell-command' for Tramp files."
+
+ (let* (;; "& wait" is added by `dired-shell-stuff-it'.
+ (asynchronous
+ (string-match-p
+ (rx (? (* blank) "& wait") (* blank) "&" (* blank) eos) command))
+ (command (substring command 0 asynchronous))
+ (command (string-join `("\"" "&" "{" ,command "}" "\"") " "))
+ (command (if asynchronous (concat command "; exit &") command)))
+ (tramp-handle-shell-command command output-buffer error-buffer)))
(defun tramp-smb-handle-substitute-in-file-name (filename)
"Like `substitute-in-file-name' for Tramp files.
@@ -1661,25 +1679,28 @@ VEC or USER, or if there is no home directory, return
nil."
(when (string-match (rx bol (? "/") (group (+ (not "/"))) "/") localname)
(match-string 1 localname)))))
-(defun tramp-smb-get-localname (vec)
+(defun tramp-smb-get-localname (vec &optional share)
"Return the file name of LOCALNAME.
+If SHARE is non-nil, include the share name.
If VEC has no cifs capabilities, exchange \"/\" by \"\\\\\"."
(save-match-data
(let ((localname (tramp-file-name-unquote-localname vec)))
- (setq
- localname
- (if (string-match
- (rx bol (? "/") (+ (not "/")) (group "/" (* nonl))) localname)
- ;; There is a share, separated by "/".
- (if (not (tramp-smb-get-cifs-capabilities vec))
- (mapconcat
- (lambda (x) (if (equal x ?/) "\\" (char-to-string x)))
- (match-string 1 localname) "")
- (match-string 1 localname))
- ;; There is just a share.
- (if (string-match (rx bol (? "/") (group (+ (not "/"))) eol) localname)
- (match-string 1 localname)
- "")))
+ (unless share
+ (setq
+ localname
+ (if (string-match
+ (rx bol (? "/") (+ (not "/")) (group "/" (* nonl))) localname)
+ ;; There is a share, separated by "/".
+ (if (not (tramp-smb-get-cifs-capabilities vec))
+ (mapconcat
+ (lambda (x) (if (equal x ?/) "\\" (char-to-string x)))
+ (match-string 1 localname) "")
+ (match-string 1 localname))
+ ;; There is just a share.
+ (if (string-match
+ (rx bol (? "/") (group (+ (not "/"))) eol) localname)
+ (match-string 1 localname)
+ ""))))
;; Sometimes we have discarded `substitute-in-file-name'.
(when (string-match (rx (group "$$") (| "/" eol)) localname)
@@ -1939,7 +1960,13 @@ function waits for output unless NOOUTPUT is set."
(tramp-smb-maybe-open-connection vec)
(tramp-message vec 6 "%s" command)
(tramp-send-string vec command)
- (unless nooutput (tramp-smb-wait-for-output vec)))
+ (unless nooutput
+ (prog1
+ (tramp-smb-wait-for-output vec)
+ (with-current-buffer (tramp-get-connection-buffer vec)
+ (save-excursion
+ (goto-char (point-min))
+ (delete-matching-lines (rx bol (literal command) eol)))))))
(defun tramp-smb-maybe-open-connection (vec &optional argument)
"Maybe open a connection to HOST, log in as USER, using `tramp-smb-program'.
@@ -2047,6 +2074,11 @@ If ARGUMENT is non-nil, use it as argument for
(let* (coding-system-for-read
(process-connection-type tramp-process-connection-type)
+ ;; There might be some unfortunate values of
+ ;; `tramp-smb-connection-local-default-system-variables'.
+ ;(path-separator (default-value 'path-separator))
+ ;(null-device (default-value 'null-device))
+ ;(exec-suffixes (default-value 'exec-suffixes))
(p (apply #'tramp-start-process vec
(tramp-get-connection-name vec)
(tramp-get-connection-buffer vec)
@@ -2054,6 +2086,10 @@ If ARGUMENT is non-nil, use it as argument for
tramp-smb-winexe-program tramp-smb-program)
args)))
+ ;; Set sentinel. Initialize variables.
+ (set-process-sentinel p #'tramp-process-sentinel)
+ (setq tramp-current-connection (cons vec (current-time)))
+
;; Set connection-local variables.
(tramp-set-connection-local-variables vec)
@@ -2104,7 +2140,9 @@ Removes smb prompt. Returns nil if an error message has
appeared."
(inhibit-read-only t))
;; Read pending output.
- (while (not (search-forward-regexp tramp-smb-prompt nil t))
+ (tramp-accept-process-output p)
+ (while (and (process-live-p p)
+ (not (search-forward-regexp tramp-smb-prompt nil t)))
(while (tramp-accept-process-output p))
(goto-char (point-min)))
(tramp-message vec 6 "%S\n%s" p (buffer-string))
@@ -2138,6 +2176,10 @@ Removes smb prompt. Returns nil if an error message has
appeared."
(when (tramp-file-name-port vec)
(tramp-error vec 'file-error "Port not supported for remote processes"))
+ ;; Check share.
+ (unless (tramp-smb-get-share vec)
+ (tramp-error vec 'file-error "Default directory must contain a share."))
+
;; In case of "NT_STATUS_RPC_SS_CONTEXT_MISMATCH", the remote server
;; is a Samba server. winexe cannot install the respective service there.
(tramp-smb-maybe-open-connection
@@ -2150,26 +2192,29 @@ Removes smb prompt. Returns nil if an error message
has appeared."
;; Suppress "^M". Shouldn't we specify utf8?
(set-process-coding-system (tramp-get-connection-process vec) 'raw-text-dos)
-
- ;; Set width to 128 ($bufsize.Width) or 102 ($winsize.Width),
- ;; respectively. $winsize.Width cannot be larger. This avoids
- ;; mixing prompt and long error messages.
+ ;; Enable UTF-8 encoding. Suppress "^M".
+ ;; (set-process-coding-system (tramp-get-connection-process vec) 'utf-8-dos)
+ ;; (tramp-smb-send-command vec "$PSDefaultParameterValues['*:Encoding'] =
'utf8'")
+ ;; This avoids mixing prompt and long error messages.
(tramp-smb-send-command vec "$rawui = (Get-Host).UI.RawUI")
- (tramp-smb-send-command vec "$bufsize = $rawui.BufferSize")
- (tramp-smb-send-command vec "$winsize = $rawui.WindowSize")
- (tramp-smb-send-command vec "$bufsize.Width = 128")
- (tramp-smb-send-command vec "$winsize.Width = 102")
- (tramp-smb-send-command vec "$rawui.BufferSize = $bufsize")
- (tramp-smb-send-command vec "$rawui.WindowSize = $winsize"))
+ (tramp-smb-send-command vec "$rawui.WindowSize = $rawui.MaxWindowSize")
+ (tramp-smb-send-command vec "$rawui.BufferSize.Width = 1024")
+ ;; Goto `default-directory'.
+ (tramp-smb-send-command
+ vec (format
+ "cd //%s%s"
+ (tramp-file-name-host vec)
+ (tramp-smb-shell-quote-localname vec 'share))))
(defun tramp-smb-shell-quote-argument (s)
"Similar to `shell-quote-argument', but uses Windows cmd syntax."
(let ((system-type 'ms-dos))
(tramp-unquote-shell-quote-argument s)))
-(defun tramp-smb-shell-quote-localname (vec)
- "Call `tramp-smb-shell-quote-argument' on localname of VEC."
- (tramp-smb-shell-quote-argument (tramp-smb-get-localname vec)))
+(defun tramp-smb-shell-quote-localname (vec &optional share)
+ "Call `tramp-smb-shell-quote-argument' on localname of VEC.
+SHARE will be passed to the call of `tramp-smb-get-localname'."
+ (tramp-smb-shell-quote-argument (tramp-smb-get-localname vec share)))
;;; Default connection-local variables for Tramp.
@@ -2194,6 +2239,57 @@ Removes smb prompt. Returns nil if an error message has
appeared."
`(:application tramp :protocol ,tramp-smb-method)
'tramp-smb-connection-local-default-system-profile)
+;; (defconst tramp-smb-connection-local-bash-variables
+;; '((explicit-shell-file-name . "bash")
+;; (explicit-bash-args . ("--norc" "--noediting" "-i"))
+;; (shell-file-name . "bash")
+;; (shell-command-switch . "-c"))
+;; "Default connection-local bash variables for remote smb connections.")
+
+;; (connection-local-set-profile-variables
+;; 'tramp-smb-connection-local-bash-profile
+;; tramp-smb-connection-local-bash-variables)
+
+(defconst tramp-smb-connection-local-powershell-variables
+ `((explicit-shell-file-name . "powershell")
+ (explicit-powershell-args . ("-file" "-"))
+ (shell-file-name . "powershell")
+ (shell-command-switch . "-command")
+ (shell-history-file-name . t))
+ "Default connection-local powershell variables for remote smb connections.")
+
+(connection-local-set-profile-variables
+ 'tramp-smb-connection-local-powershell-profile
+ tramp-smb-connection-local-powershell-variables)
+
+(defun tramp-smb-shell-prompt ()
+ "Set `comint-prompt-regexp' to a proper value."
+ ;; Used for remote `shell-mode' buffers.
+ (when (tramp-smb-file-name-p default-directory)
+ (setq-local comint-prompt-regexp tramp-smb-prompt)))
+
+;; (defconst tramp-smb-connection-local-cmd-variables
+;; '((explicit-shell-file-name . "cmd")
+;; (explicit-cmd-args . ("/Q"))
+;; (shell-file-name . "cmd")
+;; (shell-command-switch . "/C"))
+;; "Default connection-local cmd variables for remote smb connections.")
+
+;; (connection-local-set-profile-variables
+;; 'tramp-smb-connection-local-cmd-profile
+;; tramp-smb-connection-local-cmd-variables)
+
+(with-eval-after-load 'shell
+ (connection-local-set-profiles
+ `(:application tramp :protocol ,tramp-smb-method)
+ 'tramp-smb-connection-local-powershell-profile)
+ (add-hook 'shell-mode-hook
+ #'tramp-smb-shell-prompt)
+ (add-hook 'tramp-smb-unload-hook
+ (lambda ()
+ (remove-hook 'shell-mode-hook
+ #'tramp-smb-shell-prompt))))
+
(add-hook 'tramp-unload-hook
(lambda ()
(unload-feature 'tramp-smb 'force)))
diff --git a/tramp-sshfs.el b/tramp-sshfs.el
index cbc083a1fe..6e59a877e1 100644
--- a/tramp-sshfs.el
+++ b/tramp-sshfs.el
@@ -253,7 +253,7 @@ arguments to pass to the OPERATION."
(defun tramp-sshfs-handle-process-file
(program &optional infile destination display &rest args)
"Like `process-file' for Tramp files."
- ;; STDERR is not impelmemted.
+ ;; STDERR is not implemented.
(when (consp destination)
(setcdr destination `(,tramp-cache-undefined)))
(tramp-skeleton-process-file program infile destination display args
diff --git a/tramp.el b/tramp.el
index 82a0953ecb..1866c7dad6 100644
--- a/tramp.el
+++ b/tramp.el
@@ -7,7 +7,7 @@
;; Maintainer: Michael Albinus <[email protected]>
;; Keywords: comm, processes
;; Package: tramp
-;; Version: 2.8.0.5
+;; Version: 2.8.1
;; Package-Requires: ((emacs "28.1"))
;; Package-Type: multi
;; URL: https://www.gnu.org/software/tramp/
@@ -785,7 +785,7 @@ The regexp should match at end of buffer."
"Place your finger on the reader again"
"Swipe your finger again"
"Swipe was too short, try again"
- "Your finger was not centred, try swiping your finger again"
+ "Your finger was not centered, try swiping your finger again"
"Remove your finger, and try swiping your finger again")
(* nonl) (* (any "\r\n")))
"Regexp matching fingerprint prompts.
@@ -2545,7 +2545,7 @@ Must be handled by the callers."
res)))
(defun tramp-add-external-operation (operation function backend)
- "Add FUNTION to Tramp BACKEND as handler for OPERATION.
+ "Add FUNCTION to Tramp BACKEND as handler for OPERATION.
OPERATION must not be one of the magic operations listed in Info
node `(elisp) Magic File Names'. FUNCTION must have the same argument
list as OPERATION. BACKEND, a symbol, must be one of the Tramp backend
@@ -2922,7 +2922,9 @@ not in completion mode."
;; check, whether DIRECTORY is "/method:" or "/[method/".
(let ((dir (or directory default-directory "/")))
(cond
- ((file-name-absolute-p filename) filename)
+ ((file-name-absolute-p filename)
+ ;; FILENAME could be like "~/". We must expand this.
+ (tramp-run-real-handler #'expand-file-name (list filename directory)))
((and (eq tramp-syntax 'simplified)
(string-match-p (rx (regexp tramp-postfix-host-regexp) eos) dir))
(concat dir filename))
@@ -3821,8 +3823,8 @@ BODY is the backend specific code."
(defmacro tramp-skeleton-make-process (args null-command stderr-file &rest
body)
"Skeleton for `tramp-*-handle-make-process'.
-NULL-COMMAND indicates a possible empty command. STDERR-FILE means,
-that a stederr file is supported. BODY is the backend specific code."
+NULL-COMMAND indicates a possible empty command. STDERR-FILE means
+that a stderr file is supported. BODY is the backend specific code."
(declare (indent 3) (debug t))
`(when ,args
(with-parsed-tramp-file-name (expand-file-name default-directory) nil
@@ -3978,7 +3980,7 @@ BODY is the backend specific code."
((null (cadr ,destination))
(setq stderr (tramp-get-remote-null-device v)))
((eq (cadr ,destination) tramp-cache-undefined)
- ;; stderr is not impelmemted.
+ ;; stderr is not implemented.
(tramp-warning v "%s" "STDERR not supported"))))
;; t
(,destination
diff --git a/trampver.el b/trampver.el
index 71bb71f0ae..51e04e0a1c 100644
--- a/trampver.el
+++ b/trampver.el
@@ -7,7 +7,7 @@
;; Maintainer: Michael Albinus <[email protected]>
;; Keywords: comm, processes
;; Package: tramp
-;; Version: 2.8.0.5
+;; Version: 2.8.1
;; Package-Requires: ((emacs "28.1"))
;; Package-Type: multi
;; URL: https://www.gnu.org/software/tramp/
@@ -40,7 +40,7 @@
;; ./configure" to change them.
;;;###tramp-autoload
-(defconst tramp-version "2.8.0.5"
+(defconst tramp-version "2.8.1"
"This version of Tramp.")
;;;###tramp-autoload
@@ -76,7 +76,7 @@
;; Check for Emacs version.
(let ((x (if (not (string-version-lessp emacs-version "28.1"))
"ok"
- (format "Tramp 2.8.0.5 is not fit for %s"
+ (format "Tramp 2.8.1 is not fit for %s"
(replace-regexp-in-string "\n" "" (emacs-version))))))
(unless (string-equal "ok" x) (error "%s" x)))