]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-66515: Fix locking of an MH mailbox without ".mh_sequences" file (GH-113482)
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 10 Jan 2024 13:31:55 +0000 (15:31 +0200)
committerGitHub <noreply@github.com>
Wed, 10 Jan 2024 13:31:55 +0000 (15:31 +0200)
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.

Lib/mailbox.py
Lib/test/test_mailbox.py

index 0e1d49b399d0776aaa398df91662b7863256aee5..81ea210cf815a48a00667b91bfd5b374aad67c6a 100644 (file)
@@ -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
index 8c350eb02ccc179ffc239a4c18e203c936d90eb0..d84faad0eb340698892cda2e69f0b9a3d03feb51 100644 (file)
@@ -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')