summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2024-01-10 13:31:55 (GMT)
committerGitHub <noreply@github.com>2024-01-10 13:31:55 (GMT)
commitbe5e65fdf67b1817e173e73443564c7c146b09a4 (patch)
tree31a8b1454d36d03a2a8919b1d8b9685907708539
parent89cee94b315c88d3cd4c9ffc051e7abd6a5f2196 (diff)
downloadcpython-be5e65fdf67b1817e173e73443564c7c146b09a4.zip
cpython-be5e65fdf67b1817e173e73443564c7c146b09a4.tar.gz
cpython-be5e65fdf67b1817e173e73443564c7c146b09a4.tar.bz2
gh-66515: Fix locking of an MH mailbox without ".mh_sequences" file (GH-113482)
Guarantee that it either open an existing ".mh_sequences" file or create a new ".mh_sequences" file, but do not replace existing ".mh_sequences" file.
-rw-r--r--Lib/mailbox.py19
-rw-r--r--Lib/test/test_mailbox.py9
2 files changed, 26 insertions, 2 deletions
diff --git a/Lib/mailbox.py b/Lib/mailbox.py
index 0e1d49b..81ea210 100644
--- a/Lib/mailbox.py
+++ b/Lib/mailbox.py
@@ -1141,10 +1141,24 @@ class MH(Mailbox):
"""Return a count of messages in the mailbox."""
return len(list(self.iterkeys()))
+ def _open_mh_sequences_file(self, text):
+ mode = '' if text else 'b'
+ kwargs = {'encoding': 'ASCII'} if text else {}
+ path = os.path.join(self._path, '.mh_sequences')
+ while True:
+ try:
+ return open(path, 'r+' + mode, **kwargs)
+ except FileNotFoundError:
+ pass
+ try:
+ return open(path, 'x+' + mode, **kwargs)
+ except FileExistsError:
+ pass
+
def lock(self):
"""Lock the mailbox."""
if not self._locked:
- self._file = open(os.path.join(self._path, '.mh_sequences'), 'rb+')
+ self._file = self._open_mh_sequences_file(text=False)
_lock_file(self._file)
self._locked = True
@@ -1225,8 +1239,9 @@ class MH(Mailbox):
def set_sequences(self, sequences):
"""Set sequences using the given name-to-key-list dictionary."""
- f = open(os.path.join(self._path, '.mh_sequences'), 'w', encoding='ASCII')
+ f = self._open_mh_sequences_file(text=True)
try:
+ os.close(os.open(f.name, os.O_WRONLY | os.O_TRUNC))
for name, keys in sequences.items():
if len(keys) == 0:
continue
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 8c350eb..d84faad 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -1360,6 +1360,15 @@ class TestMH(TestMailbox, unittest.TestCase):
box.set_sequences({})
self.assertEqual(os.listdir(path), ['.mh_sequences'])
+ def test_lock_unlock_no_dot_mh_sequences_file(self):
+ path = os.path.join(self._path, 'foo.bar')
+ os.mkdir(path)
+ box = self._factory(path)
+ self.assertEqual(os.listdir(path), [])
+ box.lock()
+ box.unlock()
+ self.assertEqual(os.listdir(path), ['.mh_sequences'])
+
def test_issue2625(self):
msg0 = mailbox.MHMessage(self._template % 0)
msg0.add_sequence('foo')