Skip to content

Commit 14aef56

Browse files
miss-islingtonsoftinsserhiy-storchaka
authored
[3.12] gh-117467: Add preserving of mailbox owner on flush (GH-117510) (GH-117537)
(cherry picked from commit 3f5bcc8) Co-authored-by: Tony Mountifield <[email protected]> Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent eca377f commit 14aef56

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

Lib/mailbox.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -698,9 +698,13 @@ def flush(self):
698698
_sync_close(new_file)
699699
# self._file is about to get replaced, so no need to sync.
700700
self._file.close()
701-
# Make sure the new file's mode is the same as the old file's
702-
mode = os.stat(self._path).st_mode
703-
os.chmod(new_file.name, mode)
701+
# Make sure the new file's mode and owner are the same as the old file's
702+
info = os.stat(self._path)
703+
os.chmod(new_file.name, info.st_mode)
704+
try:
705+
os.chown(new_file.name, info.st_uid, info.st_gid)
706+
except (AttributeError, OSError):
707+
pass
704708
try:
705709
os.rename(new_file.name, self._path)
706710
except FileExistsError:

Lib/test/test_mailbox.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io
1010
import tempfile
1111
from test import support
12+
from test.support import import_helper
1213
from test.support import os_helper
1314
from test.support import socket_helper
1415
import unittest
@@ -981,6 +982,47 @@ def test_permissions_after_flush(self):
981982

982983
self.assertEqual(os.stat(self._path).st_mode, mode)
983984

985+
@unittest.skipUnless(hasattr(os, 'chown'), 'requires os.chown')
986+
def test_ownership_after_flush(self):
987+
# See issue gh-117467
988+
989+
pwd = import_helper.import_module('pwd')
990+
grp = import_helper.import_module('grp')
991+
st = os.stat(self._path)
992+
993+
for e in pwd.getpwall():
994+
if e.pw_uid != st.st_uid:
995+
other_uid = e.pw_uid
996+
break
997+
else:
998+
self.skipTest("test needs more than one user")
999+
1000+
for e in grp.getgrall():
1001+
if e.gr_gid != st.st_gid:
1002+
other_gid = e.gr_gid
1003+
break
1004+
else:
1005+
self.skipTest("test needs more than one group")
1006+
1007+
try:
1008+
os.chown(self._path, other_uid, other_gid)
1009+
except OSError:
1010+
self.skipTest('test needs root privilege')
1011+
# Change permissions as in test_permissions_after_flush.
1012+
mode = st.st_mode | 0o666
1013+
os.chmod(self._path, mode)
1014+
1015+
self._box.add(self._template % 0)
1016+
i = self._box.add(self._template % 1)
1017+
# Need to remove one message to make flush() create a new file
1018+
self._box.remove(i)
1019+
self._box.flush()
1020+
1021+
st = os.stat(self._path)
1022+
self.assertEqual(st.st_uid, other_uid)
1023+
self.assertEqual(st.st_gid, other_gid)
1024+
self.assertEqual(st.st_mode, mode)
1025+
9841026

9851027
class _TestMboxMMDF(_TestSingleFile):
9861028

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Preserve mailbox ownership when rewriting in :func:`mailbox.mbox.flush`.
2+
Patch by Tony Mountifield.

0 commit comments

Comments
 (0)