[Python-checkins] bpo-24538: Fix bug in shutil involving the copying of xattrs to read-only files. (PR-13212) (#13234)

Giampaolo Rodola webhook-mailer at python.org
Tue May 14 01:30:29 EDT 2019


https://github.com/python/cpython/commit/0a5b88e7f23b671d63896619b13148b0e4e2b5dd
commit: 0a5b88e7f23b671d63896619b13148b0e4e2b5dd
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: Giampaolo Rodola <g.rodola at gmail.com>
date: 2019-05-14T13:30:22+08:00
summary:

bpo-24538: Fix bug in shutil involving the copying of xattrs to read-only files. (PR-13212) (#13234)

Extended attributes can only be set on user-writeable files, but shutil previously
first chmod()ed the destination file to the source's permissions and then tried to
copy xattrs. This will cause failures if attempting to copy read-only files with
xattrs, as occurs with Git clones on Lustre FS.
(cherry picked from commit 79efbb719383386051c72f2ee932eeca8e033e6b)

Co-authored-by: Olexa Bilaniuk <obilaniu at users.noreply.github.com>

files:
A Misc/NEWS.d/next/Library/2019-05-09-08-35-18.bpo-24538.WK8Y-k.rst
M Lib/shutil.py
M Lib/test/test_shutil.py
M Misc/ACKS

diff --git a/Lib/shutil.py b/Lib/shutil.py
index b0a53dba3a34..4c6fdd7d33d4 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -203,6 +203,9 @@ def lookup(name):
     mode = stat.S_IMODE(st.st_mode)
     lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
         follow_symlinks=follow)
+    # We must copy extended attributes before the file is (potentially)
+    # chmod()'ed read-only, otherwise setxattr() will error with -EACCES.
+    _copyxattr(src, dst, follow_symlinks=follow)
     try:
         lookup("chmod")(dst, mode, follow_symlinks=follow)
     except NotImplementedError:
@@ -226,7 +229,6 @@ def lookup(name):
                     break
             else:
                 raise
-    _copyxattr(src, dst, follow_symlinks=follow)
 
 def copy(src, dst, *, follow_symlinks=True):
     """Copy data and mode bits ("cp src dst"). Return the file's destination.
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
index 197dd130a964..ef9323962cae 100644
--- a/Lib/test/test_shutil.py
+++ b/Lib/test/test_shutil.py
@@ -464,12 +464,20 @@ def _raise_on_src(fname, *, follow_symlinks=True):
 
         # test that shutil.copystat copies xattrs
         src = os.path.join(tmp_dir, 'the_original')
+        srcro = os.path.join(tmp_dir, 'the_original_ro')
         write_file(src, src)
+        write_file(srcro, srcro)
         os.setxattr(src, 'user.the_value', b'fiddly')
+        os.setxattr(srcro, 'user.the_value', b'fiddly')
+        os.chmod(srcro, 0o444)
         dst = os.path.join(tmp_dir, 'the_copy')
+        dstro = os.path.join(tmp_dir, 'the_copy_ro')
         write_file(dst, dst)
+        write_file(dstro, dstro)
         shutil.copystat(src, dst)
+        shutil.copystat(srcro, dstro)
         self.assertEqual(os.getxattr(dst, 'user.the_value'), b'fiddly')
+        self.assertEqual(os.getxattr(dstro, 'user.the_value'), b'fiddly')
 
     @support.skip_unless_symlink
     @support.skip_unless_xattr
diff --git a/Misc/ACKS b/Misc/ACKS
index 4581f32dd5f8..8998c7bf6b61 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -147,6 +147,7 @@ Stephen Bevan
 Ron Bickers
 Natalia B. Bidart
 Adrian von Bidder
+Olexa Bilaniuk
 David Binger
 Dominic Binks
 Philippe Biondi
diff --git a/Misc/NEWS.d/next/Library/2019-05-09-08-35-18.bpo-24538.WK8Y-k.rst b/Misc/NEWS.d/next/Library/2019-05-09-08-35-18.bpo-24538.WK8Y-k.rst
new file mode 100644
index 000000000000..e799f931bcec
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-05-09-08-35-18.bpo-24538.WK8Y-k.rst
@@ -0,0 +1,3 @@
+In `shutil.copystat()`, first copy extended file attributes and then file
+permissions, since extended attributes can only be set on the destination
+while it is still writeable.



More information about the Python-checkins mailing list