This issue is observed in bash with various distributions (SLES12, SLES15,
Debian12, etc). When HISTFILESIZE is set to be less than or equal to
HISTSIZE, the timestamp of the oldest command will be truncated.

To reproduce the issue:

sles12sp5:~ # export HISTSIZE=3
sles12sp5:~ # export HISTFILESIZE=3
sles12sp5:~ # export HISTFILE=/home/history.hlog
sles12sp5:~ # export HISTTIMEFORMAT=${HISTTIMEFORMAT:-"%F %H:%M:%S "}
sles12sp5:~ #
sles12sp5:~ # sleep 1
sles12sp5:~ # sleep 2
sles12sp5:~ # exit
logout

<login>
sles12sp5:~ # cat /home/history.hlog
sleep 1    # missing timestamp
#1750923608
sleep 2
#1750923612
exit

If HISTFILESIZE controls the total number of lines in the history file, the
file should only contain 3 lines. Otherwise, if HISTFILESIZE controls the
total number of history entries (command + timestamp), then the timestamp
of the oldest entry is missing. Either way, we don't get the expected
result.

This proposed fix assumes the latter, i.e., HISTFILESIZE controls the total
number of history entries.

---
 histfile.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/histfile.c b/histfile.c
index 3bfec55..40c5565 100644
--- a/histfile.c
+++ b/histfile.c
@@ -594,7 +594,8 @@ history_truncate_file (const char *fname, int lines)
      both a newline and the history comment character, it should be OK. */
   for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
     {
-      if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
+      /* skips the first iteration */
+      if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0 && bp1 != bp)
        lines--;
       bp1 = bp;
     }
@@ -606,7 +607,7 @@ history_truncate_file (const char *fname, int lines)
      this line until the end of the buffer. */
   for ( ; bp > buffer; bp--)
     {
-      if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
+      if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 1)
         {
          bp++;
          break;
--

Reply via email to