From 216194d31bee3b6bc1fa3d9b5c56f3e307b750d2 Mon Sep 17 00:00:00 2001 From: Fotis Panagiotopoulos Date: Thu, 3 Jun 2021 16:51:10 +0300 Subject: [PATCH] Added automatic log rotation, when log file is opened. --- drivers/syslog/Kconfig | 34 ++++++++++++++- drivers/syslog/syslog_filechannel.c | 66 +++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/drivers/syslog/Kconfig b/drivers/syslog/Kconfig index 760883098c..5f558d325e 100644 --- a/drivers/syslog/Kconfig +++ b/drivers/syslog/Kconfig @@ -13,6 +13,8 @@ config ARCH_SYSLOG # Selected if the SYSLOG device supports multi-byte write operations +comment "SYSLOG options" + config SYSLOG_MAX_CHANNELS int "Maximum SYSLOG channels" default 1 @@ -105,6 +107,8 @@ config SYSLOG_INTBUFSIZE ---help--- The size of the interrupt buffer in bytes. +comment "Formatting options" + config SYSLOG_TIMESTAMP bool "Prepend timestamp to syslog message" default n @@ -188,6 +192,8 @@ config SYSLOG_COLOR_OUTPUT ---help--- Enables colored output in syslog, according to message priority. +comment "SYSLOG channels" + if !ARCH_SYSLOG config SYSLOG_CHAR bool "Log to a character device" @@ -251,7 +257,7 @@ config SYSLOG_RPMSG_SERVER ---help--- Use rpmsg to receive message from remote proc. -config SYSLOG_FILE +menuconfig SYSLOG_FILE bool "Syslog file output" default n ---help--- @@ -265,6 +271,32 @@ config SYSLOG_FILE NOTE interrupt level SYSLOG output will be lost in this case unless the interrupt buffer is used. +if SYSLOG_FILE + +config SYSLOG_FILE_ROTATE + bool "Log file rotate" + default n + depends on SYSLOG_FILE + ---help--- + If enabled, the log file size will be checked before opening. + If it is larger than the specified limit it will be "rotated", + i.e. the old file will be kept as a backup, and a new empty + file will be created. + + This option is useful to ensure that log files do not get + huge after prolonged periods of system operation. + +config SYSLOG_FILE_SIZE_LIMIT + int "Log file size limit" + default 524288 + depends on SYSLOG_FILE_ROTATE + ---help--- + File size limit when the log is rotated automatically. + If a log file is found larger than this limit, it will + be rotated. + +endif # SYSLOG_FILE + config CONSOLE_SYSLOG bool "Use SYSLOG for /dev/console" default n diff --git a/drivers/syslog/syslog_filechannel.c b/drivers/syslog/syslog_filechannel.c index 98e7e2f2a5..94ae81dffe 100644 --- a/drivers/syslog/syslog_filechannel.c +++ b/drivers/syslog/syslog_filechannel.c @@ -25,9 +25,13 @@ #include #include +#include #include #include #include +#include +#include +#include #include @@ -50,6 +54,62 @@ FAR static struct syslog_channel_s *g_syslog_file_channel; +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_SYSLOG_FILE_ROTATE +static void log_rotate(FAR const char *log_file) +{ + int fd; + off_t size; + struct stat f_stat; + char *backup_file; + + /* Get the size of the current log file. */ + + fd = open(log_file, O_RDONLY); + if (fd < 0) + { + return; + } + + fstat(fd, &f_stat); + size = f_stat.st_size; + close(fd); + + /* If it does not exceed the limit we are OK. */ + + if (size < CONFIG_SYSLOG_FILE_SIZE_LIMIT) + { + return; + } + + /* Construct the backup file name. */ + + backup_file = malloc(strlen(log_file) + 3); + if (backup_file == NULL) + { + return; + } + + sprintf(backup_file, "%s.0", log_file); + + /* Delete any old backup files. */ + + if (access(backup_file, F_OK) == 0) + { + remove(backup_file); + } + + /* Rotate the log. */ + + rename(log_file, backup_file); + + free(backup_file); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -108,6 +168,12 @@ FAR struct syslog_channel_s *syslog_file_channel(FAR const char *devpath) syslog_dev_uninitialize(g_syslog_file_channel); } + /* Rotate the log file, if needed. */ + +#ifdef CONFIG_SYSLOG_FILE_ROTATE + log_rotate(devpath); +#endif + /* Then initialize the file interface */ g_syslog_file_channel = syslog_dev_initialize(devpath, OPEN_FLAGS,