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

From: Thierry Volpiatto <[email-masked]>
Date: Sun, 26 Feb 2012 20:48:50 +0100

Hi Michael,

Michael Albinus <[email-masked]> writes:

> Thierry Volpiatto <[email-masked]> writes:
>
>>> Btw, it might be useful if you could add documentation about
>>> `files-equal-p' and `file-subdir-of-p' in doc/lispref/files.texi.
>> I will have a look.
>
> Thanks.
>
> The implementation of `files-equal-p' returns t,

Of course,
(equal nil nil)=>t
where nil and nil are the file-attributes of non--existing files.

> if both FILE1 and FILE2 do not exist. Either it is a bug, or it must
> be documented.

We can fallback to string comparison when one of the file-attributes
return nil.
It would also make file-subdir-of-p working with non--existing dirnames.
(with one optional arg):

--8<---------------cut here---------------start------------->8---
diff --git a/lisp/files.el b/lisp/files.el
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -4991,10 +4991,16 @@
                      (find-file-name-handler file2 'files-equal-p))))
     (if handler
         (funcall handler 'files-equal-p file1 file2)
-      (equal (file-attributes (file-truename file1))
-             (file-attributes (file-truename file2))))))
-
-(defun file-subdir-of-p (dir1 dir2)
+      (let ((f1-attr (file-attributes (file-truename file1)))
+            (f2-attr (file-attributes (file-truename file2))))
+        (if (and f1-attr f2-attr)
+            (equal f1-attr f2-attr)
+          (string= (file-truename
+                    (file-name-as-directory file1))
+                   (file-truename
+                    (file-name-as-directory file2))))))))
+
+(defun file-subdir-of-p (dir1 dir2 &optional noexist)
   "Return non-nil if DIR1 is a subdirectory of DIR2.
 Note that a directory is treated by this function as a subdirectory of itself.
 This function only works when its two arguments already exist,
@@ -5003,8 +5009,9 @@
                      (find-file-name-handler dir2 'file-subdir-of-p))))
     (if handler
         (funcall handler 'file-subdir-of-p dir1 dir2)
-      (when (and (file-directory-p dir1)
-                 (file-directory-p dir2))
+      (when (or noexist
+                (and (file-directory-p dir1)
+                     (file-directory-p dir2)))
         (loop with f1 = (file-truename dir1)
               with f2 = (file-truename dir2)
               with ls1 = (or (split-string f1 "/" t) (list "/"))
--8<---------------cut here---------------end--------------->8---

-- 
  Thierry
Get my Gnupg key:
gpg --keyserver pgp.mit.edu --recv-keys 59F29997