From dd8738119bf9228cc718f2f67091efcd428a2970 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 20 Mar 2025 12:57:37 +0100 Subject: [PATCH] logging: try to reopen message log on cyclelogs command When the cyclelogs command is issued, check if the file specified by the -l option is still in its place and if not try opening it again. If that fails (e.g. due to chrony no longer having root privileges), keep the old file handle to avoid losing log messages. --- doc/chronyc.adoc | 7 +++++++ logging.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/doc/chronyc.adoc b/doc/chronyc.adoc index b3692f43..5780e281 100644 --- a/doc/chronyc.adoc +++ b/doc/chronyc.adoc @@ -1467,6 +1467,13 @@ purged. An example of how to do this is shown below. # chronyc cyclelogs # rm /var/log/chrony/measurements1.log ---- ++ +Note that log files enabled by the *log* directive are opened when the first +entry is made. The message log file specified by the *chronyd*'s *-l* option is +opened early on start and closed on the *cyclelogs* command only if opening of +the new file succeeds to avoid losing messages. If *chronyd* is configured to +drop root privileges and the directory containg the log file is not writable +for the specified user, *chronyd* will not be able to open the file again. [[dump]]*dump*:: The *dump* command causes *chronyd* to write its current history of diff --git a/logging.c b/logging.c index 732165e9..db2e6f60 100644 --- a/logging.c +++ b/logging.c @@ -46,6 +46,7 @@ static LOG_Context log_contexts; /* Flag indicating we have initialised */ static int initialised = 0; +static char *file_log_path = NULL; static FILE *file_log = NULL; static int system_log = 0; @@ -92,6 +93,9 @@ LOG_Finalise(void) if (file_log) fclose(file_log); + file_log = NULL; + Free(file_log_path); + file_log_path = NULL; LOG_CycleLogFiles(); @@ -200,27 +204,42 @@ void LOG_Message(LOG_Severity severity, /* ================================================== */ -void -LOG_OpenFileLog(const char *log_file) +static FILE * +open_file_log(const char *log_file, char mode) { FILE *f; if (log_file) { - f = UTI_OpenFile(NULL, log_file, NULL, 'A', 0640); + f = UTI_OpenFile(NULL, log_file, NULL, mode, 0640); } else { f = stderr; } /* Enable line buffering */ - setvbuf(f, NULL, _IOLBF, BUFSIZ); + if (f) + setvbuf(f, NULL, _IOLBF, BUFSIZ); + + return f; +} + +/* ================================================== */ + +void +LOG_OpenFileLog(const char *log_file) +{ + if (file_log_path) + Free(file_log_path); + if (log_file) + file_log_path = Strdup(log_file); + else + file_log_path = NULL; if (file_log && file_log != stderr) fclose(file_log); - file_log = f; + file_log = open_file_log(file_log_path, 'A'); } - /* ================================================== */ void @@ -385,14 +404,29 @@ LOG_FileWrite(LOG_FileID id, const char *format, ...) void LOG_CycleLogFiles(void) { + struct stat st; LOG_FileID i; + FILE *f; + /* The log will be opened later when an entry is logged */ for (i = 0; i < n_filelogs; i++) { if (logfiles[i].file) fclose(logfiles[i].file); logfiles[i].file = NULL; logfiles[i].writes = 0; } + + /* Try to open the log specified by the -l option, but only if nothing is + present at its path to avoid unnecessary error messages. Keep the + original file if that fails (the process might no longer have the + necessary privileges to write in the directory). */ + if (file_log && file_log != stderr && stat(file_log_path, &st) < 0 && errno == ENOENT) { + f = open_file_log(file_log_path, 'a'); + if (f) { + fclose(file_log); + file_log = f; + } + } } /* ================================================== */ -- 2.47.3