logging/ascii: Atomically create .shadow files using rename()

A logger process being terminated/killed while in the process of creating
a new .shadow file may leave an empty (invalid) one around. This in turn
causes the logger to error and exit during startup.

    $ $ ls -lha .shadow.*
    -rw-r--r-- 1 root root 0 Dec 16 18:48 .shadow.dns.log
    -rw-r--r-- 1 root root 0 Dec 16 18:48 .shadow.packet_filter.log

    $ zeek LogAscii::enable_leftover_log_rotation=T Log::default_rotation_interval=30sec -i wlp0s20f3
    error in <params>, line 1: failed to process leftover log 'dns.log': Found leftover log, 'dns.log', but the associated shadow  file, '.shadow.dns.log', required to process it is invalid
    error in <params>, line 1: failed to process leftover log 'packet_filter.log': Found leftover log, 'packet_filter.log', but the associated shadow  file, '.shadow.packet_filter.log', required to process it is invalid
    $ ...

Prevent creating invalid .shadow files by atomically creating them.
This commit is contained in:
Arne Welzel 2020-12-16 18:42:57 +01:00
parent 206c674cc9
commit ef7206bb99

View file

@ -455,7 +455,8 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const threading::Fiel
if ( use_shadow ) if ( use_shadow )
{ {
auto sfname = shadow_file_prefix + fname; auto sfname = shadow_file_prefix + fname;
auto sfd = open(sfname.data(), O_WRONLY | O_CREAT | O_TRUNC, 0666); auto tmp_sfname = ".tmp" + sfname;
auto sfd = open(tmp_sfname.data(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if ( sfd < 0 ) if ( sfd < 0 )
{ {
@ -474,6 +475,17 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const threading::Fiel
util::safe_write(sfd, "\n", 1); util::safe_write(sfd, "\n", 1);
util::safe_close(sfd); util::safe_close(sfd);
if ( rename(tmp_sfname.data(), sfname.data()) == -1 )
{
Error(Fmt("Unable to rename %s to %s: %s",
tmp_sfname.data(), sfname.data(),
Strerror(errno)));
unlink(tmp_sfname.data());
return false;
}
} }
} }