This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: shutil.copy destroys hard links
Type: Stage:
Components: Library (Lib) Versions: Python 2.3
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: jlgijsbers Nosy List: gls62, greg_ball, jlgijsbers
Priority: normal Keywords:

Created on 2003-11-29 12:36 by gls62, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (4)
msg19198 - (view) Author: Gerald Schlueter (gls62) Date: 2003-11-29 12:36
Hi, 
I am using python2.3 on a debian linux (unstable) kernel 
Version 2.4.20. 
 
shell: 
cd /tmp 
cp /etc/passwd a 
ln a b 
cp a b 
*** a and b are the same file *** 
 
python 
import shutil 
shutil.copy("a", "b") 
 
The file is destroyed and cut down to 0 Bytes! 
 
Thank you, 
 
Gerry (gls62) 
msg19199 - (view) Author: Gregory H. Ball (greg_ball) Date: 2003-12-01 17:03
Logged In: YES 
user_id=11365

The problem is in function shutil.copyfile().

Unlike cp, it does not check whether the two filenames actually
link to the same underlying file.  If they do, the act of
opening the dst file for writing destroys the src file. 
This is true for symbolic or hard links.  cp notices the
link and prints a message.

A fix for this would be to replace the lines

    # check for same pathname; all platforms
    _src = os.path.normcase(os.path.abspath(src))
    _dst = os.path.normcase(os.path.abspath(dst))
    if _src == _dst:
        return

with

     # check for same file
    if hasattr(os.path,'samefile'): # Macintosh, Unix. 
        try:
            if os.path.samefile(src,dst):
                return
        except OSError:
            pass
    else:  # check for same pathname; all other platforms
        _src = os.path.normcase(os.path.abspath(src))
        _dst = os.path.normcase(os.path.abspath(dst))
        if _src == _dst:
            return

This should fix the bug under Unix (and Mac, I guess) and
leave other platforms no worse than before (I guess most
other platforms do not have hard or symbolic links anyway?)

I have posted a patch at
http://tane.cfa.harvard.edu/python/shutil.patch

Gerry, could you try it out, then perhaps I can open a patch
item.
I've included some test code.  However, it uses
tempfile.mktemp which I see has now been deprecated, so it
will need a fix for that.  Also, I'm not sure that it
properly cleans up in the event of a failure.  Perhaps this
should be fixed too.

msg19200 - (view) Author: Gerald Schlueter (gls62) Date: 2003-12-02 15:28
Logged In: YES 
user_id=920149

Hi Gregory, 
 
your patch works fine on my system. 
 
greetings, 
Gerry 
msg19201 - (view) Author: Johannes Gijsbers (jlgijsbers) * (Python triager) Date: 2004-08-14 13:33
Logged In: YES 
user_id=469548

Fixed in rev 1.31 of shutil.py using patch at
http://python.org/sf/854853.
History
Date User Action Args
2022-04-11 14:56:01adminsetgithub: 39628
2003-11-29 12:36:35gls62create