Subject: Re: bug#10489: 24.0.92; dired-do-copy may create infinite directory hierarchy

From: Thierry Volpiatto <[email-masked]>
Date: Fri, 13 Jan 2012 12:00:18 +0100

Hi Michael,

Michael Albinus <[email-masked]> writes:

> Thierry Volpiatto <[email-masked]> writes:
>
>> Here a version of the patch that use `equal' and handle also same error
>> on remotes files.
>> i.e (copy-directory "/sudo:host:/home/user/Test" "/home/user/Test")
>
> Your code seems also to suppress
>
>    (copy-directory "/sssh:remotehost:/home/user/Test" "/home/user/Test")
>
> Why that?
Because I forget to handle this case ;-).
Here the patch modified that handle this.

I want to only suppress the use of:
(copy-directory "/sudo:host:/home/user/Test" "/home/user/Test")
or
(copy-directory "/sudo:host:/home/user/Test" "/sudo:host:/home/user/Test")

-- 
  Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997 
##Merge of all patches applied from revision 118413
## patch-r118414: Fix error when trying to copy directory on itself (bug#10489).
## patch-r118415: * lisp/dired-aux.el (dired-copy-file-recursive): Handle also remote file/dir.
## patch-r118416: "New patch"
## 
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -1264,6 +1264,13 @@
 
 (defun dired-copy-file-recursive (from to ok-flag &optional
 				       preserve-time top recursive)
+  (when (equal (or (and (equal "sudo" (file-remote-p (file-name-as-directory from) 'method))
+                        (file-remote-p (file-name-as-directory from) 'localname))
+                   (file-name-as-directory from))
+               (or (and (equal "sudo" (file-remote-p (file-name-as-directory to) 'method))
+                        (file-remote-p (file-name-as-directory to) 'localname))
+                   (file-name-as-directory to)))
+    (error "Can't copy directory `%s' on itself" from))
   (let ((attrs (file-attributes from)))
     (if (and recursive
 	     (eq t (car attrs))
@@ -1402,7 +1409,7 @@
 newfile's entry, or t to use the current marker character if the
 old file was marked."
   (let (dired-create-files-failures failures
-	skipped (success-count 0) (total (length fn-list)))
+                                    skipped (success-count 0) (total (length fn-list)))
     (let (to overwrite-query
 	     overwrite-backup-query)	; for dired-handle-overwrite
       (dolist (from fn-list)
@@ -1431,7 +1438,28 @@
                          (marker-char (dired-file-marker from)) ; slow
                          (t nil))))
 	    (when (and (file-directory-p from)
-		       (file-directory-p to)
+		       (or
+                        (equal
+                         ;; Test if 'from'
+                         ;; is a remote file localname with sudo method.
+                         (or (and (equal
+                                   "sudo"
+                                   (file-remote-p (file-name-as-directory from)
+                                                  'method))
+                                  (file-remote-p (file-name-as-directory from)
+                                                 'localname))
+                             (file-name-as-directory from))
+                         ;; Test if 'to'
+                         ;; is a remote file localname with sudo method.
+                         (or (and (equal
+                                   "sudo"
+                                   (file-remote-p (file-name-as-directory to)
+                                                  'method))
+                                  (file-remote-p (file-name-as-directory
+                                                  (file-name-directory to))
+                                                 'localname))
+                             (file-name-as-directory (file-name-directory to))))
+                        (file-directory-p to))
 		       (eq file-creator 'dired-copy-file))
 	      (setq to (file-name-directory to)))
             (condition-case err
@@ -1456,21 +1484,21 @@
       (setq failures (nconc failures dired-create-files-failures))
       (dired-log-summary
        (format "%s failed for %d file%s in %d requests"
-		operation (length failures)
-		(dired-plural-s (length failures))
-		total)
+               operation (length failures)
+               (dired-plural-s (length failures))
+               total)
        failures))
      (failures
       (dired-log-summary
        (format "%s failed for %d of %d file%s"
-		operation (length failures)
-		total (dired-plural-s total))
+               operation (length failures)
+               total (dired-plural-s total))
        failures))
      (skipped
       (dired-log-summary
        (format "%s: %d of %d file%s skipped"
-		operation (length skipped) total
-		(dired-plural-s total))
+               operation (length skipped) total
+               (dired-plural-s total))
        skipped))
      (t
       (message "%s: %s file%s"
diff --git a/lisp/files.el b/lisp/files.el
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -4928,6 +4928,13 @@
 	    (format "Copy directory %s to: " dir)
 	    default-directory default-directory nil nil)
 	   current-prefix-arg t nil)))
+  (when (equal (or (and (equal "sudo" (file-remote-p (file-name-as-directory directory) 'method))
+                        (file-remote-p (file-name-as-directory directory) 'localname))
+                   (file-name-as-directory directory))
+               (or (and (equal "sudo" (file-remote-p (file-name-as-directory newname) 'method))
+                        (file-remote-p (file-name-as-directory newname) 'localname))
+                   (file-name-as-directory newname)))
+    (error "Can't copy directory `%s' on itself" directory))
   ;; If default-directory is a remote directory, make sure we find its
   ;; copy-directory handler.
   (let ((handler (or (find-file-name-handler directory 'copy-directory)