Title: shutil.copystat may fail EOPNOTSUPP
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 2.7, Python 2.6
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: tarek Nosy List: barry, jackdied, joerg, kcwu, pitrou, serhiy.storchaka, tarek
Priority: normal Keywords: patch

Created on 2009-12-15 07:31 by kcwu, last changed 2012-10-16 20:00 by pitrou. This issue is now closed.

File name Uploaded Description Edit
copystat.diff kcwu, 2009-12-15 07:31
Messages (8)
msg96427 - (view) Author: Kuang-che Wu (kcwu) Date: 2009-12-15 07:31
"flags" is only supported on certain OS. FreeBSD is one of them.
FreeBSD itself support chflags but not all of its file systems do.

On FreeBSD, copystat() will fail on zfs. The exception is OSError and
errno is EOPNOTSUPP. According to manpage chflags(2), the errno means
"The underlying file system does not support file flags"

If the file system doesn't support flags, we should not call
os.chflags() at first or should not raise exception.

In my patch, I just ignore EOPNOTSUPP exception.
msg99806 - (view) Author: Jack Diederich (jackdied) * (Python committer) Date: 2010-02-22 18:35
This patch looks like the right thing to do.  I'm +1 but I don't have a BSD box to test it on.
msg101234 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-03-17 17:17
For the record, this seems to break Mercurial on NFS-mounted repositories:
msg101235 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-03-17 17:20
Barry, I suppose this doesn't warrant being a release blocker for 2.6.5, but in any case you're welcome to advise.
msg101247 - (view) Author: Joerg Sonnenberger (joerg) Date: 2010-03-17 23:05
A better approach might be to change the function to:

def copystat(src, dst):
  st = os.stat(src)
  st_dst = os.stat(dst)
  mode = stat.S_IMODE(st.st_mode)
  mode_dst = stat.S_IMODE(st_dst.st_mode)
  if hasattr(os, 'utime'):
    if st.st_atime != st_dst.st_atime or st.st_mtime != st_dst.st_mtime
      os.utime(dst, (st.st_atime, st.st_mtime))
  if hasattr(os, 'chmod'):
    if mode != mode_dst:
      os.chmod(dst, mode)
  if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
    if st.st_flags != st_dst.st_flags:
      os.chflags(dst, st.st_flags)

This avoids the system calls for the (common) case of not having to change anything at all. Given that the flags are normally not set, it also avoids the problem with NFS.
msg101530 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-03-22 20:19
I committed the simple patch in r79299 (trunk), r79300 (2.6), r79301 (py3k), r79302 (3.1). Tarek suggested a test could be added for this, assigning the issue to him.
msg173057 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2012-10-16 16:05
Tests added in issue14662. This issue can be closed.
msg173085 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2012-10-16 20:00
Ok, thanks.
Date User Action Args
2012-10-16 20:00:31pitrousetstatus: open -> closed
resolution: accepted -> fixed
messages: + msg173085
2012-10-16 16:05:39serhiy.storchakasetstatus: pending -> open
nosy: + serhiy.storchaka
messages: + msg173057

2010-03-22 20:19:39pitrousetstatus: open -> pending

nosy: + tarek
messages: + msg101530

assignee: pitrou -> tarek
stage: commit review -> resolved
2010-03-17 23:05:12joergsetnosy: + joerg
messages: + msg101247
2010-03-17 17:20:06pitrousetnosy: + barry
messages: + msg101235
2010-03-17 17:17:27pitrousetmessages: + msg101234
2010-03-17 17:14:33pitrousetassignee: pitrou

resolution: accepted
nosy: + pitrou
stage: commit review
2010-02-22 18:35:35jackdiedsetnosy: + jackdied
messages: + msg99806
2009-12-15 07:31:46kcwucreate