diff --git a/drivers/syslog/Kconfig b/drivers/syslog/Kconfig index 5f558d325e6..976717bffb5 100644 --- a/drivers/syslog/Kconfig +++ b/drivers/syslog/Kconfig @@ -273,15 +273,18 @@ menuconfig SYSLOG_FILE if SYSLOG_FILE -config SYSLOG_FILE_ROTATE - bool "Log file rotate" - default n +config SYSLOG_FILE_ROTATIONS + int "Log file rotations" + default 0 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. + If enabled (set to a non-zero number), 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. + + The number of rotations specifies the number of old log files to + keep. This option is useful to ensure that log files do not get huge after prolonged periods of system operation. @@ -289,7 +292,7 @@ config SYSLOG_FILE_ROTATE config SYSLOG_FILE_SIZE_LIMIT int "Log file size limit" default 524288 - depends on SYSLOG_FILE_ROTATE + depends on SYSLOG_FILE_ROTATIONS > 0 ---help--- File size limit when the log is rotated automatically. If a log file is found larger than this limit, it will diff --git a/drivers/syslog/syslog_filechannel.c b/drivers/syslog/syslog_filechannel.c index 94ae81dffeb..7263ae27dac 100644 --- a/drivers/syslog/syslog_filechannel.c +++ b/drivers/syslog/syslog_filechannel.c @@ -32,8 +32,10 @@ #include #include #include +#include #include +#include #include "syslog.h" @@ -58,25 +60,24 @@ FAR static struct syslog_channel_s *g_syslog_file_channel; * Private Functions ****************************************************************************/ -#ifdef CONFIG_SYSLOG_FILE_ROTATE +#if CONFIG_SYSLOG_FILE_ROTATIONS > 0 static void log_rotate(FAR const char *log_file) { - int fd; + int i; off_t size; struct stat f_stat; - char *backup_file; + size_t name_size; + FAR char *rotate_to; + FAR char *rotate_from; /* Get the size of the current log file. */ - fd = open(log_file, O_RDONLY); - if (fd < 0) + if (stat(log_file, &f_stat) < 0) { return; } - fstat(fd, &f_stat); size = f_stat.st_size; - close(fd); /* If it does not exceed the limit we are OK. */ @@ -85,28 +86,34 @@ static void log_rotate(FAR const char *log_file) return; } - /* Construct the backup file name. */ + /* Rotated file names. */ - backup_file = malloc(strlen(log_file) + 3); - if (backup_file == NULL) + name_size = strlen(log_file) + 8; + rotate_to = kmm_malloc(name_size); + rotate_from = kmm_malloc(name_size); + if ((rotate_to == NULL) || (rotate_from == NULL)) { - return; + goto end; } - sprintf(backup_file, "%s.0", log_file); + /* Rotate the logs. */ - /* Delete any old backup files. */ - - if (access(backup_file, F_OK) == 0) + for (i = (CONFIG_SYSLOG_FILE_ROTATIONS - 1); i > 0; i--) { - remove(backup_file); + snprintf(rotate_to, name_size, "%s.%d", log_file, i); + snprintf(rotate_from, name_size, "%s.%d", log_file, i - 1); + + rename(rotate_from, rotate_to); } - /* Rotate the log. */ + snprintf(rotate_to, name_size, "%s.0", log_file); - rename(log_file, backup_file); + rename(log_file, rotate_to); - free(backup_file); +end: + + kmm_free(rotate_to); + kmm_free(rotate_from); } #endif @@ -170,7 +177,7 @@ FAR struct syslog_channel_s *syslog_file_channel(FAR const char *devpath) /* Rotate the log file, if needed. */ -#ifdef CONFIG_SYSLOG_FILE_ROTATE +#if CONFIG_SYSLOG_FILE_ROTATIONS > 0 log_rotate(devpath); #endif