GNU bug report logs - #9879
23.3; making script executable with tramp

Previous Next

Package: emacs;

Reported by: Dan Gildea <gildea <at> pobox.com>

Date: Wed, 26 Oct 2011 19:05:02 UTC

Severity: normal

Found in version 23.3

Done: Michael Albinus <michael.albinus <at> gmx.de>

Bug is archived. No further changes may be made.

Full log


Message #26 received at 9879 <at> debbugs.gnu.org (full text, mbox):

From: Michael Albinus <michael.albinus <at> gmx.de>
To: Daniel Gildea <gildea <at> cs.rochester.edu>
Cc: Glenn Morris <rgm <at> gnu.org>, 9879 <at> debbugs.gnu.org,
	Dan Gildea <gildea <at> pobox.com>
Subject: Re: bug#9879: 23.3; making script executable with tramp
Date: Wed, 16 Nov 2011 20:59:56 +0100
Michael Albinus <michael.albinus <at> gmx.de> writes:

> You are working on "/u/gildea/xx.sh", which is a symlink to
> "/home/vax7/u19/gildea/xx.sh". You have written "/u/gildea/xx.sh". Tramp
> tries to check "/home/vax7/u19/gildea/xx.sh" file properties afterwards,
> and it decides that this file doesn't exist.
>
> This is likely because of Tramp's cache, which hasn't been refreshed
> accordingly for the symlink's target after writing.
>
> I will check how to fix this; unfortunately there is no simple patch. It
> might take a day, or two.

The following two patches shall solve the problem, could you, please
verify?

The patches are for Emacs 23.3, however, the line numbers might be a
little bit different.

--8<---------------cut here---------------start------------->8---
Index: tramp.el
===================================================================
RCS file: /sources/tramp/tramp/lisp/tramp.el,v
retrieving revision 2.814.2.16
diff -c -r2.814.2.16 tramp.el
*** tramp.el	12 Oct 2011 14:56:21 -0000	2.814.2.16
--- tramp.el	16 Nov 2011 19:50:48 -0000
***************
*** 2671,2776 ****
  (defun tramp-handle-file-truename (filename &optional counter prev-dirs)
    "Like `file-truename' for Tramp files."
    (with-parsed-tramp-file-name (expand-file-name filename) nil
!     (with-file-property v localname "file-truename"
!       (let ((result nil))			; result steps in reverse order
! 	(tramp-message v 4 "Finding true name for `%s'" filename)
! 	(cond
! 	 ;; Use GNU readlink --canonicalize-missing where available.
! 	 ((tramp-get-remote-readlink v)
! 	  (setq result
! 		(tramp-send-command-and-read
! 		 v
! 		 (format "echo \"\\\"`%s --canonicalize-missing %s`\\\"\""
! 			 (tramp-get-remote-readlink v)
! 			 (tramp-shell-quote-argument localname)))))
! 
! 	 ;; Use Perl implementation.
! 	 ((and (tramp-get-remote-perl v)
! 	       (tramp-get-connection-property v "perl-file-spec" nil)
! 	       (tramp-get-connection-property v "perl-cwd-realpath" nil))
! 	  (tramp-maybe-send-script
! 	   v tramp-perl-file-truename "tramp_perl_file_truename")
! 	  (setq result
! 		(tramp-send-command-and-read
! 		 v
! 		 (format "tramp_perl_file_truename %s"
! 			 (tramp-shell-quote-argument localname)))))
! 
! 	 ;; Do it yourself.  We bind `directory-sep-char' here for
! 	 ;; XEmacs on Windows, which would otherwise use backslash.
! 	 (t (let* ((directory-sep-char ?/)
! 		   (steps (tramp-compat-split-string localname "/"))
! 		   (localnamedir (tramp-run-real-handler
! 				  'file-name-as-directory (list localname)))
! 		   (is-dir (string= localname localnamedir))
! 		   (thisstep nil)
! 		   (numchase 0)
! 		   ;; Don't make the following value larger than
! 		   ;; necessary.  People expect an error message in a
! 		   ;; timely fashion when something is wrong;
! 		   ;; otherwise they might think that Emacs is hung.
! 		   ;; Of course, correctness has to come first.
! 		   (numchase-limit 20)
! 		   symlink-target)
! 	      (while (and steps (< numchase numchase-limit))
! 		(setq thisstep (pop steps))
! 		(tramp-message
! 		 v 5 "Check %s"
! 		 (mapconcat 'identity
! 			    (append '("") (reverse result) (list thisstep))
! 			    "/"))
! 		(setq symlink-target
! 		      (nth 0 (file-attributes
! 			      (tramp-make-tramp-file-name
! 			       method user host
! 			       (mapconcat 'identity
! 					  (append '("")
! 						  (reverse result)
! 						  (list thisstep))
! 					  "/")))))
! 		(cond ((string= "." thisstep)
! 		       (tramp-message v 5 "Ignoring step `.'"))
! 		      ((string= ".." thisstep)
! 		       (tramp-message v 5 "Processing step `..'")
! 		       (pop result))
! 		      ((stringp symlink-target)
! 		       ;; It's a symlink, follow it.
! 		       (tramp-message v 5 "Follow symlink to %s" symlink-target)
! 		       (setq numchase (1+ numchase))
! 		       (when (file-name-absolute-p symlink-target)
! 			 (setq result nil))
! 		       ;; If the symlink was absolute, we'll get a string like
! 		       ;; "/user <at> host:/some/target"; extract the
! 		       ;; "/some/target" part from it.
! 		       (when (tramp-tramp-file-p symlink-target)
! 			 (unless (tramp-equal-remote filename symlink-target)
! 			   (tramp-error
! 			    v 'file-error
! 			    "Symlink target `%s' on wrong host" symlink-target))
! 			 (setq symlink-target localname))
! 		       (setq steps
! 			     (append (tramp-compat-split-string
! 				      symlink-target "/")
! 				     steps)))
! 		      (t
! 		       ;; It's a file.
! 		       (setq result (cons thisstep result)))))
! 	      (when (>= numchase numchase-limit)
! 		(tramp-error
! 		 v 'file-error
! 		 "Maximum number (%d) of symlinks exceeded" numchase-limit))
! 	      (setq result (reverse result))
! 	      ;; Combine list to form string.
! 	      (setq result
! 		    (if result
! 			(mapconcat 'identity (cons "" result) "/")
! 		      "/"))
! 	      (when (and is-dir (or (string= "" result)
! 				    (not (string= (substring result -1) "/"))))
! 		(setq result (concat result "/"))))))
  
!         (tramp-message v 4 "True name of `%s' is `%s'" filename result)
!         (tramp-make-tramp-file-name method user host result)))))
  
  ;; Basic functions.
  
--- 2671,2780 ----
  (defun tramp-handle-file-truename (filename &optional counter prev-dirs)
    "Like `file-truename' for Tramp files."
    (with-parsed-tramp-file-name (expand-file-name filename) nil
!     (tramp-make-tramp-file-name method user host
!       (with-file-property v localname "file-truename"
! 	(let ((result nil))			; result steps in reverse order
! 	  (tramp-message v 4 "Finding true name for `%s'" filename)
! 	  (cond
! 	   ;; Use GNU readlink --canonicalize-missing where available.
! 	   ((tramp-get-remote-readlink v)
! 	    (setq result
! 		  (tramp-send-command-and-read
! 		   v
! 		   (format "echo \"\\\"`%s --canonicalize-missing %s`\\\"\""
! 			   (tramp-get-remote-readlink v)
! 			   (tramp-shell-quote-argument localname)))))
! 
! 	   ;; Use Perl implementation.
! 	   ((and (tramp-get-remote-perl v)
! 		 (tramp-get-connection-property v "perl-file-spec" nil)
! 		 (tramp-get-connection-property v "perl-cwd-realpath" nil))
! 	    (tramp-maybe-send-script
! 	     v tramp-perl-file-truename "tramp_perl_file_truename")
! 	    (setq result
! 		  (tramp-send-command-and-read
! 		   v
! 		   (format "tramp_perl_file_truename %s"
! 			   (tramp-shell-quote-argument localname)))))
! 
! 	   ;; Do it yourself.  We bind `directory-sep-char' here for
! 	   ;; XEmacs on Windows, which would otherwise use backslash.
! 	   (t (let* ((directory-sep-char ?/)
! 		     (steps (tramp-compat-split-string localname "/"))
! 		     (localnamedir (tramp-run-real-handler
! 				    'file-name-as-directory (list localname)))
! 		     (is-dir (string= localname localnamedir))
! 		     (thisstep nil)
! 		     (numchase 0)
! 		     ;; Don't make the following value larger than
! 		     ;; necessary.  People expect an error message in
! 		     ;; a timely fashion when something is wrong;
! 		     ;; otherwise they might think that Emacs is hung.
! 		     ;; Of course, correctness has to come first.
! 		     (numchase-limit 20)
! 		     symlink-target)
! 		(while (and steps (< numchase numchase-limit))
! 		  (setq thisstep (pop steps))
! 		  (tramp-message
! 		   v 5 "Check %s"
! 		   (mapconcat 'identity
! 			      (append '("") (reverse result) (list thisstep))
! 			      "/"))
! 		  (setq symlink-target
! 			(nth 0 (file-attributes
! 				(tramp-make-tramp-file-name
! 				 method user host
! 				 (mapconcat 'identity
! 					    (append '("")
! 						    (reverse result)
! 						    (list thisstep))
! 					    "/")))))
! 		  (cond ((string= "." thisstep)
! 			 (tramp-message v 5 "Ignoring step `.'"))
! 			((string= ".." thisstep)
! 			 (tramp-message v 5 "Processing step `..'")
! 			 (pop result))
! 			((stringp symlink-target)
! 			 ;; It's a symlink, follow it.
! 			 (tramp-message
! 			  v 5 "Follow symlink to %s" symlink-target)
! 			 (setq numchase (1+ numchase))
! 			 (when (file-name-absolute-p symlink-target)
! 			   (setq result nil))
! 			 ;; If the symlink was absolute, we'll get a
! 			 ;; string like "/user <at> host:/some/target";
! 			 ;; extract the "/some/target" part from it.
! 			 (when (tramp-tramp-file-p symlink-target)
! 			   (unless (tramp-equal-remote filename symlink-target)
! 			     (tramp-error
! 			      v 'file-error
! 			      "Symlink target `%s' on wrong host"
! 			      symlink-target))
! 			   (setq symlink-target localname))
! 			 (setq steps
! 			       (append (tramp-compat-split-string
! 					symlink-target "/")
! 				       steps)))
! 			(t
! 			 ;; It's a file.
! 			 (setq result (cons thisstep result)))))
! 		(when (>= numchase numchase-limit)
! 		  (tramp-error
! 		   v 'file-error
! 		   "Maximum number (%d) of symlinks exceeded" numchase-limit))
! 		(setq result (reverse result))
! 		;; Combine list to form string.
! 		(setq result
! 		      (if result
! 			  (mapconcat 'identity (cons "" result) "/")
! 			"/"))
! 		(when (and is-dir
! 			   (or (string= "" result)
! 			       (not (string= (substring result -1) "/"))))
! 		  (setq result (concat result "/"))))))
  
! 	  (tramp-message v 4 "True name of `%s' is `%s'" filename result)
! 	  result)))))
  
  ;; Basic functions.
  
--8<---------------cut here---------------end--------------->8---

--8<---------------cut here---------------start------------->8---
Index: tramp-cache.el
===================================================================
RCS file: /sources/tramp/tramp/lisp/tramp-cache.el,v
retrieving revision 2.57.2.1
diff -c -r2.57.2.1 tramp-cache.el
*** tramp-cache.el	24 Jan 2011 10:09:40 -0000	2.57.2.1
--- tramp-cache.el	16 Nov 2011 19:54:34 -0000
***************
*** 145,150 ****
--- 145,155 ----
  
  (defun tramp-flush-file-property (vec file)
    "Remove all properties of FILE in the cache context of VEC."
+   ;; Remove file property of symlinks.
+   (let ((truename (tramp-get-file-property vec file "file-truename" nil)))
+     (when (and (stringp truename)
+ 	       (not (string-equal file truename)))
+       (tramp-flush-file-property vec truename)))
    ;; Unify localname.
    (setq vec (copy-sequence vec))
    (aset vec 3 (tramp-run-real-handler 'directory-file-name (list file)))
--8<---------------cut here---------------end--------------->8---

Best regards, Michael.




This bug report was last modified 13 years and 191 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.