Stacey Marshall <stacey.marsh...@gmail.com> writes:

Hi Stacey,

Thanks for this exhaustive bug report, and the proper analysis.

> 3. In another terminal session clear up caches, start emacs, and access
>    directory via tramp path
>
>    rm -rf ~/.cache/emacs ~/.emacs.d/tramp
>    emacs -nw -Q --eval '(add-to-list `load-path "~/emacs/tramp/lisp/")' \
>     --eval '(require `tramp)' --eval '(setq tramp-verbose 11)' \
>     --eval '(find-file 
> "/scp:foobar@localhost:/export/home/foobar/tmp/is_it_the_length_of_path_and_not_the_d")'
>
> At this point, if necessary accept the connection and type password
> as required...  And then emacs appears hung.  A C-g (Control-G)
> aborts the transfer.  Switching to the debug buffer
> `(switch-to-buffer "*debug tramp/scp foobar@localhost*")` and
> duplicating it (M-n) (before it gets contaminated/removed).
> It shows some output, though this tends to differ slightly each time!

Yep. According to the debug buffer you've sent, Tramp has sent the
following command:

--8<---------------cut here---------------start------------->8---
16:34:47.760152 tramp-send-command (6) # (if test -h 
"/export/home/foobar/tmp/is_it_the_length_of_path_and_not_the_d/"; then echo t; 
else echo nil; fi) && /usr/bin/readlink --canonicalize-missing 
/export/home/foobar/tmp/is_it_the_length_of_path_and_not_the_d/ 2>/dev/null; 
echo tramp_exit_status $?
--8<---------------cut here---------------end--------------->8---

The "(if test ... tramp_exit_status $?" sequence is 257 characters long,
it seems to exceed the shell line length on Solaris. The problem is,
that the looooongish file name is used twice.

> diff --git a/lisp/tramp-sh.el b/lisp/tramp-sh.el
> index 047d93a5..e0ccc0ce 100644
> --- a/lisp/tramp-sh.el
> +++ b/lisp/tramp-sh.el
> @@ -1292,20 +1292,12 @@ Operations not mentioned here will be handled by the 
> normal Emacs functions.")
>       ;; Use GNU readlink --canonicalize-missing where available.
>       ((tramp-get-remote-readlink v)
>        (tramp-send-command-and-check
> -       v (format
> -         (concat
> -          "(if %s -h \"%s\"; then echo t; else echo nil; fi) && "
> -          "%s --canonicalize-missing %s")
> -         (tramp-get-test-command v)
> -         (tramp-shell-quote-argument localname)
> -         (tramp-get-remote-readlink v)
> -         (tramp-shell-quote-argument localname)))
> +       v (format "%s --canonicalize-missing %s"
> +                (tramp-get-remote-readlink v)
> +                (tramp-shell-quote-argument localname)))
>        (with-current-buffer (tramp-get-connection-buffer v)
>         (goto-char (point-min))
> -       (tramp-set-file-property v localname "file-symlink-marker" (read 
> (current-buffer)))
> -       ;; We cannot call `read', the file name isn't quoted.
> -       (forward-line)
> -       (buffer-substring (point) (line-end-position))))
> +       (buffer-substring (point-min) (line-end-position))))

Yes. But this removes the performance optimization, to return both the
information, whether a give file is a symlink, and its true name. This
optimization avoids one round trip.

> At this point I thought I should raise it with yourselves.

Instead, I've puzzled the attached patch, which uses a shell function
instead. Could you please check?

> Stace

Best regards, Michael.

diff --git a/lisp/tramp-sh.el b/lisp/tramp-sh.el
index 047d93a5..481a3979 100644
--- a/lisp/tramp-sh.el
+++ b/lisp/tramp-sh.el
@@ -648,6 +648,14 @@ we have this shell function.
 Format specifiers are replaced by `tramp-expand-script', percent
 characters need to be doubled.")

+(defconst tramp-readlink-file-truename
+  "if %s -h \"$1\"; then echo t; else echo nil; fi
+%s --canonicalize-missing \"$1\""
+  "Shell script to produce output suitable for use with `file-truename'
+on the remote file system.
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
+
 (defconst tramp-perl-file-truename
   "%p -e '
 use File::Spec;
@@ -1291,14 +1299,12 @@ Operations not mentioned here will be handled by the normal Emacs functions.")
     (cond
      ;; Use GNU readlink --canonicalize-missing where available.
      ((tramp-get-remote-readlink v)
+      (tramp-maybe-send-script
+       v (format tramp-readlink-file-truename
+		 (tramp-get-test-command v) (tramp-get-remote-readlink v))
+       "tramp_readlink_file_truename")
       (tramp-send-command-and-check
-       v (format
-	  (concat
-	   "(if %s -h \"%s\"; then echo t; else echo nil; fi) && "
-	   "%s --canonicalize-missing %s")
-	  (tramp-get-test-command v)
-	  (tramp-shell-quote-argument localname)
-	  (tramp-get-remote-readlink v)
-	  (tramp-shell-quote-argument localname)))
+       v (format "tramp_readlink_file_truename %s"
+		 (tramp-shell-quote-argument localname)))
       (with-current-buffer (tramp-get-connection-buffer v)
 	(goto-char (point-min))
	(tramp-set-file-property v localname "file-symlink-marker" (read (current-buffer)))

Reply via email to