RU.GOLDED --------------- < Пред. | След. > -- < @ > -- < Сообщ. > -- < Эхи > --
 Nп/п : 27 из 100
 От   : Nil A                               2:5015/46         27 фев 26 04:52:06
 К    : Stas Mishchenkov                                      27 фев 26 04:57:01
 Тема : [PATCH] Fix OPUS/MSG: update all users` lastread after deleting *.MSG
----------------------------------------------------------------------------------
                                                                                 
@MSGID: 2:5015/46 69a0f9ba
@REPLY: 2:460/5858 6994cbf0
@CHRS: CP866 2
@TZUTC: 0300
@TID: hpt/lnx 1.9
Hello, Stas!

Tuesday February 17 2026 23:07, from Stas Mishchenkov -> Nil A:

 SM> А, вот, обнаружил я проблему, которую не знаю, как решать пока. Если в
 SM> OPUS Msg Base дед удаляет сообщение, то он не правит ластриды. Если
 SM> ластрид _другого_ пользователя указывает на удалённое сообщение с
 SM> большим номером, чем существующие, то так и останется. Если новые
 SM> сообщения будут тоже с меньшим номером, то они для другого
 SM> пользователя будут считаться прочитанными, а это не правильно и
 SM> чревато. На сколько я понимаю, починить это не трудно.

 ПочиНИЛ. Теперь при удалении сообщения в OPUS/MSG, правятся Lastread
для всех пользователей, плюс если по ошибке lastread указывает за
максимально доступным и не удалённым сообщением, то тоже чинится.
 Я у себя всё аккуратно проверил. Проверяй, и я попрошу тогда
Виталия залить на гитхаб.


From 6f2be3dff66bc57b09c407ec1bd7fb33f6d0b70a Mon Sep 17 00:00:00 2001
From: Nil Alexandrov <nil.alexandrov@gmail.com>
Date: Thu, 26 Feb 2026 20:47:37 -0500
Subject: [PATCH] Fix OPUS/MSG: update all users` lastread after deleting *.MSG

OPUS bases hard-delete message files, leaving other users` lastread
pointers pointing at removed message numbers. This could cause newer
lower-numbered messages to be treated as already read and missed.

After deleting a *.MSG, scan the lastread file and adjust any entries
that point to the deleted message (or exceed the current max) to the
nearest valid existing message number.
-+-
 goldlib/gmb3/gmofido3.cpp |  1 +
 goldlib/gmb3/gmofido4.cpp | 82 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/goldlib/gmb3/gmofido3.cpp b/goldlib/gmb3/gmofido3.cpp
index 7d13a17..fd3207b 100644
--- a/goldlib/gmb3/gmofido3.cpp
+++ b/goldlib/gmb3/gmofido3.cpp
@@ -36,6 +36,7 @@

 int FidoArea::load_message(int __mode, gmsg* __msg, FidoHdr& __hdr)
 {
+    GFTRK("FidoLoadMessage");

     // Build message filename
     Path _msgfile;
diff --git a/goldlib/gmb3/gmofido4.cpp b/goldlib/gmb3/gmofido4.cpp
index 6c04e41..8c4a72b 100644
--- a/goldlib/gmb3/gmofido4.cpp
+++ b/goldlib/gmb3/gmofido4.cpp
@@ -62,6 +62,7 @@ void FidoArea::unlock()

 void FidoArea::save_message(int __mode, gmsg* __msg, FidoHdr& __hdr)
 {
+    GFTRK("FidoSaveMessage");

     // Build message filename
     Path _msgfile;
@@ -264,9 +265,88 @@ void FidoArea::del_msg(gmsg* __msg)

     FidoHdr _hdr;
     save_message(GMSG_HDR | GMSG_DELETE, __msg, _hdr);
-}

+    // Determine the highest remaining message number and the highest
+    // remaining message number that is lower than the deleted message
+    uint32_t _deleted_msgno = __msg->msgno;
+    word _max_msgno = 0;
+    word _prev_msgno = 0;
+    uint _count = Msgn->Count();
+
+    if (_count > 0) {
+        _max_msgno = (word)Msgn->at(_count - 1);
+        if (_max_msgno == _deleted_msgno) {
+            _max_msgno = (word)((_count > 1) ? Msgn->at(_count - 2) : 0);
+        }
+
 + // Binary search for the largest message number less than
_deleted_msgno
+        int left = 0, right = _count - 1;
+        while (left <= right) {
+            int mid = left + (right - left) / 2;
+            uint32_t val = Msgn->at(mid);
+            if (val < _deleted_msgno) {
+                _prev_msgno = (word)val;
+                left = mid + 1;
+            } else {
+                right = mid - 1;
+            }
+        }
+    }
+
+    // Update lastread pointers for all users in the lastread file.
 + int _fh = ::sopen(AddPath(real_path(), wide->fidolastread),
O_RDWR|O_BINARY, WideSharemode, S_STDRW);
+    if(_fh != -1)
+    {
+        // Get the file size to determine how many user entries exist
+        long _filesize = filelength(_fh);
+        long _numusers = _filesize / (long)sizeof(word);
+
+        if(_numusers > 0)
+        {
+            word* _lr_array = new word[_numusers];

+            // Read the entire lastread file into memory
+            lseekset(_fh, 0);
 + if(read(_fh, _lr_array, _numusers * sizeof(word)) == (int)(_numusers
* sizeof(word)))
+            {
+                bool _changed = false;
+
+                // Scan through all user entries
+                for(long _u = 0; _u < _numusers; _u++)
+                {
+                    // If this user`s lastread points to the deleted message,
+                    // update it to the next lower existing message number.
+                    if(_lr_array[_u] == (word)_deleted_msgno)
+                    {
+                        _lr_array[_u] = _prev_msgno;
+                        _changed = true;
+                    }
+
+                    // If a user`s lastread pointer is higher than the maximum
 + // available message (e.g., due to corruption), set it to max.
+                    if(_lr_array[_u] > _max_msgno)
+                    {
+                        _lr_array[_u] = _max_msgno;
+                        _changed = true;
+                    }
+                }
+
+                // If any pointers were updated, write the array back to disk
+                if(_changed)
+                {
+                    lseekset(_fh, 0);
+                    write(_fh, _lr_array, _numusers * sizeof(word));
+                }
+            }
+
+            delete[] _lr_array;
+        }
+
+        ::close(_fh);
+    }
+
+    GFTRK(0);
+}
 //  ------------------------------------------------------------------

 void FidoArea::new_msgno(gmsg* __msg)
--
2.53.0

=== Конец патчика.

Best Regards, Nil
--- GoldED+/LNX 1.1.5-b20250409
 * Origin: Gemini can make mistakes, so double-check it (2:5015/46)
SEEN-BY: 46/49 50/109 104/117 221/6 240/1120 301/1
341/66 451/31 452/28 166
SEEN-BY: 455/19 460/58 463/68 4500/1 5000/111
5015/42 46 255 5019/40 400
SEEN-BY: 5020/101 113 545 620 715 830 846 848
1042 2992 4441 12000 5022/128
SEEN-BY: 5029/32 5030/49 115 1081 1474 5049/1 3
5050/151 5053/51 58 5054/89
SEEN-BY: 5058/104 5060/900 5061/133 5068/45 5083/1
444 6078/80 6090/1
@PATH: 5015/46 5020/1042 4441



   GoldED+ VK   │                                                 │   09:55:30    
                                                                                
В этой области больше нет сообщений.

Остаться здесь
Перейти к списку сообщений
Перейти к списку эх