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

From: Thierry Volpiatto <[email-masked]>
Date: Sat, 14 Jan 2012 11:25:16 +0100

Eli Zaretskii <[email-masked]> writes:

>> From: Thierry Volpiatto <[email-masked]>
>> Date: Fri, 13 Jan 2012 20:17:43 +0100
>> Cc: [email-masked]
>> 
>>  (defun dired-copy-file-recursive (from to ok-flag &optional
>>  				       preserve-time top recursive)
>> -  (let ((attrs (file-attributes from)))
>> +  (let* ((case-fold-search t)
>> +         (fromname    (file-name-as-directory (file-truename from)))
>> +         (destname    (file-name-as-directory (file-truename to)))
>> +         (rem-dirname (and (equal "sudo" (file-remote-p fromname 'method))
>> +                           (file-remote-p fromname 'localname)))
>> +         (rem-newname (and (equal "sudo" (file-remote-p destname 'method))
>> +                           (file-remote-p destname 'localname)))
>> +         (attrs       (file-attributes from)))
>> +    (when (equal (or rem-dirname fromname)
>> +                 (or rem-newname destname))
>> +      (error "Can't copy directory `%s' on itself" from))
>
> Why is case-fold-search being unconditionally bound to t?  I don't
> think this is TRT on case-sensitive filesystems.  Am I missing
> something?
Ignore, it have no effect, I have changed that.
The last patch use this instead, which avoid duplication of code and is
more readable.

--8<---------------cut here---------------start------------->8---
(defun files-copyable-p (from to)
  "Verify if file FROM is not the same than TO on this system."
  (let* ((fromname     (file-name-as-directory (file-truename from)))
         (destname     (file-name-as-directory (file-truename to)))
         (rem-fromname (and (equal "sudo" (file-remote-p fromname 'method))
                            (string-match (system-name)
                                          (file-remote-p fromname 'host))
                            (file-remote-p fromname 'localname)))
         (rem-newname  (and (equal "sudo" (file-remote-p destname 'method))
                            (string-match (system-name) (file-remote-p destname 'host))
                            (file-remote-p destname 'localname))))
    (not (equal (or rem-fromname fromname)
                (or rem-newname destname)))))
--8<---------------cut here---------------end--------------->8---

This work in these cases:
- usage on local filesystem.
- Copying from a remote filesystem on local filesystem.
- Copying from local filesystem to remote filesystem.
- Copying on a remote filesystem to same remote filesystem with same
method.

This may not work in these cases:
- copying from a remote filesystem to this same remote filesystem with a
different method. (Why one would do that?)
e.g /ssh:host:/foo => /scpc:host:/foo
- Others - please complete (Windows, other tramp use cases, etc...)

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