gh-117467: Add preserving of mailbox owner on flush (GH-117510)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
Tony Mountifield 2024-04-04 11:32:53 +01:00 committed by GitHub
parent dc54714044
commit 3f5bcc86d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 51 additions and 3 deletions

View file

@ -750,9 +750,13 @@ class _singlefileMailbox(Mailbox):
_sync_close(new_file) _sync_close(new_file)
# self._file is about to get replaced, so no need to sync. # self._file is about to get replaced, so no need to sync.
self._file.close() self._file.close()
# Make sure the new file's mode is the same as the old file's # Make sure the new file's mode and owner are the same as the old file's
mode = os.stat(self._path).st_mode info = os.stat(self._path)
os.chmod(new_file.name, mode) 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: try:
os.rename(new_file.name, self._path) os.rename(new_file.name, self._path)
except FileExistsError: except FileExistsError:

View file

@ -9,6 +9,7 @@ import re
import io import io
import tempfile import tempfile
from test import support from test import support
from test.support import import_helper
from test.support import os_helper from test.support import os_helper
from test.support import refleak_helper from test.support import refleak_helper
from test.support import socket_helper from test.support import socket_helper
@ -1081,6 +1082,47 @@ class _TestSingleFile(TestMailbox):
self.assertEqual(os.stat(self._path).st_mode, mode) 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): class _TestMboxMMDF(_TestSingleFile):

View file

@ -0,0 +1,2 @@
Preserve mailbox ownership when rewriting in :func:`mailbox.mbox.flush`.
Patch by Tony Mountifield.