summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-04-04 10:55:42 (GMT)
committerGitHub <noreply@github.com>2024-04-04 10:55:42 (GMT)
commit14aef56ebbf3788e60427a9bfbd6de4713967ca0 (patch)
tree9a2c1d06c5e17371f4392260d61fbbcdc631a8a1
parenteca377f203c95153f69faf7d435f5e537ad9b59a (diff)
downloadcpython-14aef56ebbf3788e60427a9bfbd6de4713967ca0.zip
cpython-14aef56ebbf3788e60427a9bfbd6de4713967ca0.tar.gz
cpython-14aef56ebbf3788e60427a9bfbd6de4713967ca0.tar.bz2
[3.12] gh-117467: Add preserving of mailbox owner on flush (GH-117510) (GH-117537)
(cherry picked from commit 3f5bcc86d0764b691087e8412941e947554c93fd) Co-authored-by: Tony Mountifield <tony@mountifield.org> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
-rw-r--r--Lib/mailbox.py10
-rw-r--r--Lib/test/test_mailbox.py42
-rw-r--r--Misc/NEWS.d/next/Library/2024-04-03-18-36-53.gh-issue-117467.l6rWlj.rst2
3 files changed, 51 insertions, 3 deletions
diff --git a/Lib/mailbox.py b/Lib/mailbox.py
index c8b3444..c7f060c 100644
--- a/Lib/mailbox.py
+++ b/Lib/mailbox.py
@@ -698,9 +698,13 @@ class _singlefileMailbox(Mailbox):
_sync_close(new_file)
# self._file is about to get replaced, so no need to sync.
self._file.close()
- # Make sure the new file's mode is the same as the old file's
- mode = os.stat(self._path).st_mode
- os.chmod(new_file.name, mode)
+ # Make sure the new file's mode and owner are the same as the old file's
+ info = os.stat(self._path)
+ os.chmod(new_file.name, info.st_mode)
+ try:
+ os.chown(new_file.name, info.st_uid, info.st_gid)
+ except (AttributeError, OSError):
+ pass
try:
os.rename(new_file.name, self._path)
except FileExistsError:
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 9f13d2f..93cf53b 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -9,6 +9,7 @@ import re
import io
import tempfile
from test import support
+from test.support import import_helper
from test.support import os_helper
from test.support import socket_helper
import unittest
@@ -981,6 +982,47 @@ class _TestSingleFile(TestMailbox):
self.assertEqual(os.stat(self._path).st_mode, mode)
+ @unittest.skipUnless(hasattr(os, 'chown'), 'requires os.chown')
+ def test_ownership_after_flush(self):
+ # See issue gh-117467
+
+ pwd = import_helper.import_module('pwd')
+ grp = import_helper.import_module('grp')
+ st = os.stat(self._path)
+
+ for e in pwd.getpwall():
+ if e.pw_uid != st.st_uid:
+ other_uid = e.pw_uid
+ break
+ else:
+ self.skipTest("test needs more than one user")
+
+ for e in grp.getgrall():
+ if e.gr_gid != st.st_gid:
+ other_gid = e.gr_gid
+ break
+ else:
+ self.skipTest("test needs more than one group")
+
+ try:
+ os.chown(self._path, other_uid, other_gid)
+ except OSError:
+ self.skipTest('test needs root privilege')
+ # Change permissions as in test_permissions_after_flush.
+ mode = st.st_mode | 0o666
+ os.chmod(self._path, mode)
+
+ self._box.add(self._template % 0)
+ i = self._box.add(self._template % 1)
+ # Need to remove one message to make flush() create a new file
+ self._box.remove(i)
+ self._box.flush()
+
+ st = os.stat(self._path)
+ self.assertEqual(st.st_uid, other_uid)
+ self.assertEqual(st.st_gid, other_gid)
+ self.assertEqual(st.st_mode, mode)
+
class _TestMboxMMDF(_TestSingleFile):
diff --git a/Misc/NEWS.d/next/Library/2024-04-03-18-36-53.gh-issue-117467.l6rWlj.rst b/Misc/NEWS.d/next/Library/2024-04-03-18-36-53.gh-issue-117467.l6rWlj.rst
new file mode 100644
index 0000000..64ae9ff
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-04-03-18-36-53.gh-issue-117467.l6rWlj.rst
@@ -0,0 +1,2 @@
+Preserve mailbox ownership when rewriting in :func:`mailbox.mbox.flush`.
+Patch by Tony Mountifield.