@@ -353,13 +353,14 @@ static int template_output(FILE *fp, struct flb_time *tm, msgpack_object *obj,
353353 return 0 ;
354354}
355355
356- static int plain_output (FILE * fp , msgpack_object * obj , size_t alloc_size )
356+ static int plain_output (FILE * fp , msgpack_object * obj , size_t alloc_size , int escape_unicode )
357357{
358358 char * buf ;
359359
360- buf = flb_msgpack_to_json_str (alloc_size , obj );
360+ buf = flb_msgpack_to_json_str (alloc_size , obj , escape_unicode );
361361 if (buf ) {
362- fprintf (fp , "%s" NEWLINE , buf );
362+ fprintf (fp , "%s" NEWLINE ,
363+ buf );
363364 flb_free (buf );
364365 }
365366 return 0 ;
@@ -750,6 +751,62 @@ static int rotate_file(struct flb_logrotate_conf *ctx, const char *filename)
750751 return 0 ;
751752}
752753
754+ /* Function to validate if a filename matches the rotation pattern format
755+ * Valid formats:
756+ * - base_filename.YYYYMMDD_HHMMSS (15 chars after pattern)
757+ * - base_filename.YYYYMMDD_HHMMSS.gz (18 chars after pattern)
758+ */
759+ static int is_valid_rotation_filename (const char * filename , const char * pattern )
760+ {
761+ size_t pattern_len = strlen (pattern );
762+ size_t filename_len = strlen (filename );
763+ const char * suffix ;
764+ size_t suffix_len ;
765+ int i ;
766+
767+ /* Check that filename starts with pattern */
768+ if (strncmp (filename , pattern , pattern_len ) != 0 ) {
769+ return 0 ;
770+ }
771+
772+ /* Get the suffix after the pattern */
773+ suffix = filename + pattern_len ;
774+ suffix_len = filename_len - pattern_len ;
775+
776+ /* Must be exactly 15 or 18 characters */
777+ if (suffix_len != 15 && suffix_len != 18 ) {
778+ return 0 ;
779+ }
780+
781+ /* For 18 characters, must end with .gz */
782+ if (suffix_len == 18 ) {
783+ if (strcmp (suffix + 15 , ".gz" ) != 0 ) {
784+ return 0 ;
785+ }
786+ }
787+
788+ /* Validate timestamp format: YYYYMMDD_HHMMSS
789+ * - 8 digits (YYYYMMDD)
790+ * - underscore at position 8
791+ * - 6 digits (HHMMSS)
792+ */
793+ for (i = 0 ; i < 8 ; i ++ ) {
794+ if (suffix [i ] < '0' || suffix [i ] > '9' ) {
795+ return 0 ;
796+ }
797+ }
798+ if (suffix [8 ] != '_' ) {
799+ return 0 ;
800+ }
801+ for (i = 9 ; i < 15 ; i ++ ) {
802+ if (suffix [i ] < '0' || suffix [i ] > '9' ) {
803+ return 0 ;
804+ }
805+ }
806+
807+ return 1 ;
808+ }
809+
753810/* Function to clean up old rotated files */
754811static int cleanup_old_files (struct flb_logrotate_conf * ctx , const char * directory , const char * base_filename )
755812{
@@ -772,7 +829,7 @@ static int cleanup_old_files(struct flb_logrotate_conf *ctx, const char *directo
772829
773830 /* Count matching files */
774831 while ((entry = readdir (dir )) != NULL ) {
775- if (strncmp (entry -> d_name , pattern , strlen ( pattern )) == 0 ) {
832+ if (is_valid_rotation_filename (entry -> d_name , pattern ) ) {
776833 file_count ++ ;
777834 }
778835 }
@@ -793,7 +850,7 @@ static int cleanup_old_files(struct flb_logrotate_conf *ctx, const char *directo
793850 rewinddir (dir );
794851 i = 0 ;
795852 while ((entry = readdir (dir )) != NULL && i < file_count ) {
796- if (strncmp (entry -> d_name , pattern , strlen ( pattern )) == 0 ) {
853+ if (is_valid_rotation_filename (entry -> d_name , pattern ) ) {
797854 snprintf (full_path , PATH_MAX - 1 , "%s" FLB_PATH_SEPARATOR "%s" ,
798855 directory , entry -> d_name );
799856 files [i ] = flb_strdup (full_path );
@@ -853,6 +910,7 @@ static void cb_logrotate_flush(struct flb_event_chunk *event_chunk,
853910 char out_file [PATH_MAX ];
854911 char * buf ;
855912 long file_pos ;
913+ bool have_directory ;
856914
857915 char * out_file_copy ;
858916 char directory [PATH_MAX ];
@@ -885,6 +943,8 @@ static void cb_logrotate_flush(struct flb_event_chunk *event_chunk,
885943
886944 /* Check if file needs rotation based on current size counter */
887945 if (should_rotate_file (ctx )) {
946+ have_directory = false;
947+ directory [0 ] = '\0' ;
888948 /* Extract directory and base filename for cleanup */
889949 out_file_copy = flb_strdup (out_file );
890950 if (out_file_copy ) {
@@ -897,6 +957,7 @@ static void cb_logrotate_flush(struct flb_event_chunk *event_chunk,
897957 directory [PATH_MAX - 1 ] = '\0' ;
898958#endif
899959 flb_free (out_file_copy );
960+ have_directory = true;
900961 }
901962
902963 /* Get base filename for cleanup */
@@ -913,7 +974,9 @@ static void cb_logrotate_flush(struct flb_event_chunk *event_chunk,
913974 /* Reset file size counter after rotation */
914975 ctx -> current_file_size = 0 ;
915976 /* Clean up old rotated files */
916- cleanup_old_files (ctx , directory , base_filename );
977+ if (have_directory ) {
978+ cleanup_old_files (ctx , directory , base_filename );
979+ }
917980 }
918981 }
919982
@@ -1008,7 +1071,8 @@ static void cb_logrotate_flush(struct flb_event_chunk *event_chunk,
10081071
10091072 switch (ctx -> format ){
10101073 case FLB_OUT_LOGROTATE_FMT_JSON :
1011- buf = flb_msgpack_to_json_str (alloc_size , log_event .body );
1074+ buf = flb_msgpack_to_json_str (alloc_size , log_event .body ,
1075+ config -> json_escape_unicode );
10121076 if (buf ) {
10131077 fprintf (fp , "%s: [%" PRIu64 ".%09lu, %s]" NEWLINE ,
10141078 event_chunk -> tag ,
0 commit comments