----------------------------------------------------------------------------------
@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