LCOV - code coverage report
Current view: top level - offlinelogstorage - dlt_offline_logstorage_behavior.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 78.1 % 507 396
Test Date: 2026-10-08 05:11:40 Functions: 100.0 % 20 20

            Line data    Source code
       1              : /**
       2              :  * Copyright (C) 2015  Advanced Driver Information Technology.
       3              :  * This code is developed by Advanced Driver Information Technology.
       4              :  * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
       5              :  *
       6              :  * DLT offline log storage functionality source file.
       7              :  *
       8              :  * \copyright
       9              :  * This Source Code Form is subject to the terms of the
      10              :  * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
      11              :  * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      12              :  *
      13              :  *
      14              :  * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
      15              :  * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2015
      16              :  *
      17              :  * \file: dlt_offline_logstorage_behavior.c
      18              :  * For further information see http://www.covesa.org/.
      19              :  */
      20              : 
      21              : #include <syslog.h>
      22              : #include <limits.h>
      23              : #include <dirent.h>
      24              : #include <string.h>
      25              : #include <sys/types.h>
      26              : #include <sys/stat.h>
      27              : #include <unistd.h>
      28              : #include <stdlib.h>
      29              : #include <errno.h>
      30              : #include <libgen.h>
      31              : 
      32              : #include "dlt_log.h"
      33              : #include "dlt_offline_logstorage.h"
      34              : #include "dlt_offline_logstorage_behavior.h"
      35              : #include "dlt_offline_logstorage_behavior_internal.h"
      36              : 
      37              : unsigned int g_logstorage_cache_size;
      38              : 
      39              : /**
      40              :  * dlt_logstorage_concat
      41              :  *
      42              :  * Concatenates two strings but keeps the size of the result less than dst_size.
      43              :  *
      44              :  * @param dst       The destination string
      45              :  * @param src       The source string to concat
      46              :  */
      47           67 : DLT_STATIC void dlt_logstorage_concat_logfile_name(char* log_file_name, const char* append)
      48              : {
      49           67 :     size_t dst_len = strnlen(log_file_name, DLT_MOUNT_PATH_MAX);
      50           67 :     size_t src_len = strlen(append);
      51              : 
      52           67 :     if (dst_len < DLT_MOUNT_PATH_MAX) {
      53           67 :         size_t rem_len = DLT_MOUNT_PATH_MAX - dst_len + 1;
      54              :         strncat(log_file_name, append, rem_len);
      55              :     } else {
      56            0 :         dlt_vlog(LOG_ERR, "Log file name reached max len: %s [%d]\n", log_file_name, DLT_MOUNT_PATH_MAX);
      57              :     }
      58              : 
      59           67 :     if (src_len + dst_len >= DLT_MOUNT_PATH_MAX) {
      60            0 :         dlt_vlog(LOG_ERR, "Log file path too long. Truncated: %s", log_file_name);
      61              :     }
      62           67 : }
      63              : 
      64              : /**
      65              :  * dlt_logstorage_log_file_name
      66              :  *
      67              :  * Create log file name in the form configured by the user
      68              :  *      \<filename\>\<delimiter\>\<index\>\<delimiter\>\<timestamp\>.dlt
      69              :  *
      70              :  *      filename:       given in configuration file
      71              :  *      delimiter:      Punctuation characters (configured in dlt.conf)
      72              :  *      timestamp:      yyyy-mm-dd-hh-mm-ss (enabled/disabled in dlt.conf)
      73              :  *      index:          Index len depends on wrap around value in dlt.conf
      74              :  *                      ex: wrap around = 99, index will 01..99
      75              :  *                      (enabled/disabled in dlt.conf)
      76              :  *
      77              :  * @param[out] log_file_name     target buffer for the complete logfile name.
      78              :  *                               it needs to fit DLT_MOUNT_PATH_MAX chars
      79              :  * @param[in]  file_config       User configurations for log file
      80              :  * @param[in]  name              file name given in configuration file
      81              :  * @param[in]  num_files         max files given in configuration file
      82              :  * @param[in]  idx               continous index of log files
      83              :  * @ return                 None
      84              :  */
      85           32 : void dlt_logstorage_log_file_name(
      86              :     char* log_file_name, DltLogStorageUserConfig* file_config, const DltLogStorageFilterConfig* filter_config,
      87              :     const char* name, const int num_files, const int idx)
      88              : {
      89           32 :     if ((log_file_name == NULL) || (file_config == NULL) || (filter_config == NULL))
      90              :         return;
      91              : 
      92           31 :     const char delim = file_config->logfile_delimiter;
      93           31 :     int index_width = (int)file_config->logfile_counteridxlen;
      94              : 
      95           31 :     if (file_config->logfile_maxcounter == UINT_MAX) {
      96              :         index_width = 0;
      97              :     }
      98              : 
      99           31 :     const char* suffix = filter_config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON ? ".dlt.gz" : ".dlt";
     100           31 :     const size_t smax = (size_t)DLT_MOUNT_PATH_MAX - strlen(suffix) - 1;
     101              :     size_t spos = 0;
     102           31 :     log_file_name[spos] = '\0';
     103              :     int rt;
     104              : 
     105              :     /* Append file name */
     106           31 :     spos += strlen(name);
     107           31 :     dlt_logstorage_concat_logfile_name(log_file_name, filter_config->file_name);
     108              : 
     109              :     /* Append index */
     110              :     /* Do not append if there is only one file and optional index mode is true*/
     111           31 :     if (!(num_files == 1 && file_config->logfile_optional_counter)) {
     112           30 :         rt = snprintf(log_file_name + spos, smax - spos, "%c%0*d", delim, index_width, idx);
     113           30 :         if ((size_t)rt >= smax - spos) {
     114            0 :             dlt_vlog(LOG_WARNING, "%s: snprintf truncation %s\n", __func__, log_file_name);
     115              :             spos = smax;
     116           30 :         } else if (rt < 0) {
     117            0 :             dlt_vlog(LOG_ERR, "%s: snprintf error rt=%d\n", __func__, rt);
     118              :             const char* fmt_err = "fmt_err";
     119              :             memcpy(log_file_name, fmt_err, strlen(fmt_err) + 1);
     120              :             spos = strlen(fmt_err) + 1;
     121              :         } else {
     122              :             spos += (size_t)rt;
     123              :         }
     124              :     }
     125              : 
     126              :     /* Add time stamp if user has configured */
     127           31 :     if (file_config->logfile_timestamp) {
     128            5 :         char stamp[DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1] = {0};
     129            5 :         time_t t = time(NULL);
     130              :         struct tm tm_info;
     131              :         ssize_t n = 0;
     132            5 :         tzset();
     133            5 :         localtime_r(&t, &tm_info);
     134            5 :         n = snprintf(
     135              :             stamp, DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1, "%c%04d%02d%02d-%02d%02d%02d", delim,
     136            5 :             1900 + tm_info.tm_year, 1 + tm_info.tm_mon, tm_info.tm_mday, tm_info.tm_hour, tm_info.tm_min,
     137              :             tm_info.tm_sec);
     138            5 :         if (n < 0 || (size_t)n > (DLT_OFFLINE_LOGSTORAGE_TIMESTAMP_LEN + 1)) {
     139            0 :             dlt_vlog(LOG_WARNING, "%s: snprintf truncation %s\n", __func__, stamp);
     140              :         }
     141            5 :         dlt_logstorage_concat_logfile_name(log_file_name, stamp);
     142              :     }
     143              : 
     144           31 :     dlt_logstorage_concat_logfile_name(log_file_name, ".dlt");
     145           31 :     if (filter_config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON) {
     146            0 :         dlt_logstorage_concat_logfile_name(log_file_name, ".gz");
     147              :     }
     148              : }
     149              : 
     150              : /**
     151              :  * dlt_logstorage_sort_file_name
     152              :  *
     153              :  * Sort the filenames with index based ascending order (bubble sort)
     154              :  *
     155              :  * @param head              Log filename list
     156              :  * @ return                 The last (biggest) index
     157              :  */
     158           49 : unsigned int dlt_logstorage_sort_file_name(DltLogStorageFileList** head)
     159              : {
     160              :     int done = 0;
     161              :     unsigned int max_idx = 0;
     162              : 
     163           49 :     if ((head == NULL) || (*head == NULL) || ((*head)->next == NULL))
     164              :         return 0;
     165              : 
     166           27 :     while (!done) {
     167              :         /* "source" of the pointer to the current node in the list struct */
     168              :         DltLogStorageFileList** pv = head;
     169           15 :         DltLogStorageFileList* nd = *head;         /* local iterator pointer */
     170           15 :         DltLogStorageFileList* nx = (*head)->next; /* local next pointer */
     171              : 
     172              :         done = 1;
     173              : 
     174           37 :         while (nx) {
     175           22 :             max_idx = nx->idx;
     176           22 :             if (nd->idx > nx->idx) {
     177              :                 max_idx = nd->idx;
     178            4 :                 nd->next = nx->next;
     179            4 :                 nx->next = nd;
     180            4 :                 *pv = nx;
     181              : 
     182              :                 done = 0;
     183              :             }
     184              : 
     185           22 :             pv = &nd->next;
     186              :             nd = nx;
     187           22 :             nx = nx->next;
     188              :         }
     189              :     }
     190              : 
     191              :     return max_idx;
     192              : }
     193              : 
     194              : /**
     195              :  * dlt_logstorage_rearrange_file_name
     196              :  *
     197              :  * Rearrange the filenames in the order of latest and oldest
     198              :  *
     199              :  * @param head              Log filename list
     200              :  * @ return                 None
     201              :  */
     202            3 : void dlt_logstorage_rearrange_file_name(DltLogStorageFileList** head)
     203              : {
     204              :     DltLogStorageFileList* n_prev = NULL;
     205              :     DltLogStorageFileList* tail = NULL;
     206              :     DltLogStorageFileList* wrap_pre = NULL;
     207              :     DltLogStorageFileList* wrap_post = NULL;
     208              :     DltLogStorageFileList* n = NULL;
     209              : 
     210            3 :     if ((head == NULL) || (*head == NULL) || ((*head)->next == NULL))
     211              :         return;
     212              : 
     213            2 :     if ((*head)->idx != 1) {
     214              :         /* Do not sort */
     215              :         return;
     216              :     }
     217              : 
     218            4 :     for (n = *head; n != NULL; n = n->next) {
     219              :         /* Compare the diff between n->idx and n_prev->idx only if
     220              :          * wrap_post and wrap_pre are not set yet. Otherwise continue the loop
     221              :          * until the tail */
     222            3 :         if (n && n_prev && !wrap_post && !wrap_pre) {
     223            1 :             if ((n->idx - n_prev->idx) != 1) {
     224              :                 wrap_post = n;
     225              :                 wrap_pre = n_prev;
     226              :             }
     227              :         }
     228              : 
     229              :         n_prev = n;
     230              :     }
     231              : 
     232              :     tail = n_prev;
     233              : 
     234            1 :     if (wrap_post && wrap_pre) {
     235            1 :         wrap_pre->next = NULL;
     236            1 :         tail->next = *head;
     237            1 :         *head = wrap_post;
     238              :     }
     239              : }
     240              : 
     241              : /**
     242              :  * dlt_logstorage_get_idx_of_log_file
     243              :  *
     244              :  * Extract index of log file name passed as input argument
     245              :  *
     246              :  * @param file_config   User configurations for log file
     247              :  * @param config        Filter configurations for log file
     248              :  * @param file          file name to extract the index from
     249              :  * @return index on success, -1 if no index is found
     250              :  */
     251           58 : unsigned int dlt_logstorage_get_idx_of_log_file(
     252              :     DltLogStorageUserConfig* file_config, DltLogStorageFilterConfig* config, char* file)
     253              : {
     254           58 :     if (file_config == NULL || config == NULL || file == NULL)
     255              :         return (unsigned int)-1;
     256              : 
     257              :     long idx = 0;
     258              :     size_t basename_len;
     259              :     char *sptr, *eptr;
     260              : 
     261              :     /* Find the next delimiter after the first one:
     262              :      * Eg. base-log-name_<idx>_<timestamp>.dlt
     263              :      *                   ^    ^
     264              :      *                   |    |
     265              :      *       From here --+    +--- To this position
     266              :      */
     267           57 :     basename_len = strlen(config->file_name);
     268           57 :     sptr = file + basename_len + 1;
     269           57 :     eptr = strchr(sptr, file_config->logfile_delimiter);
     270           57 :     idx = strtol(sptr, &eptr, 10);
     271              : 
     272           57 :     if (idx == 0)
     273            0 :         dlt_log(LOG_ERR, "Unable to calculate index from log file name. Reset to 001.\n");
     274              : 
     275           57 :     return (unsigned int)idx;
     276              : }
     277              : 
     278              : /**
     279              :  * dlt_logstorage_storage_dir_info
     280              :  *
     281              :  * Read file names of storage directory.
     282              :  * Update the file list, arrange it in order of latest and oldest
     283              :  *
     284              :  * @param file_config   User configurations for log file
     285              :  * @param path          Path to storage directory
     286              :  * @param  config       DltLogStorageFilterConfig
     287              :  * @return              0 on success, -1 on error
     288              :  */
     289           48 : int dlt_logstorage_storage_dir_info(DltLogStorageUserConfig* file_config, char* path, DltLogStorageFilterConfig* config)
     290              : {
     291              :     int check = 0;
     292              :     int i = 0;
     293              :     int cnt = 0;
     294              :     int ret = 0;
     295              :     unsigned int max_idx = 0;
     296           48 :     struct dirent** files = {0};
     297              :     unsigned int current_idx = 0;
     298              :     DltLogStorageFileList* n = NULL;
     299              :     DltLogStorageFileList* n1 = NULL;
     300           48 :     char storage_path[DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN + 1] = {'\0'};
     301           48 :     char file_name[DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN + 1] = {'\0'};
     302              :     char* dir = NULL;
     303              : 
     304           48 :     if ((config == NULL) || (file_config == NULL) || (path == NULL) || (config->file_name == NULL))
     305              :         return -1;
     306              : 
     307              :     strncpy(storage_path, path, DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN);
     308              : 
     309           47 :     if (strstr(config->file_name, "/") != NULL) {
     310              :         /* Append directory path */
     311            0 :         char tmpdir[DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN + 1] = {'\0'};
     312            0 :         char tmpfile[DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN + 1] = {'\0'};
     313              :         char* file;
     314              :         strncpy(tmpdir, config->file_name, DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN);
     315              :         strncpy(tmpfile, config->file_name, DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN);
     316            0 :         dir = dirname(tmpdir);
     317            0 :         file = basename(tmpfile);
     318            0 :         if ((strlen(path) + strlen(dir)) > DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN) {
     319            0 :             dlt_vlog(LOG_ERR, "%s: Directory name [%s] is too long to store (file name [%s])\n", __func__, dir, file);
     320            0 :             return -1;
     321              :         }
     322            0 :         strncat(storage_path, dir, DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN - strlen(storage_path));
     323              :         strncpy(file_name, file, DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN);
     324              :     } else {
     325              :         strncpy(file_name, config->file_name, DLT_OFFLINE_LOGSTORAGE_MAX_FILE_NAME_LEN);
     326              :     }
     327              : 
     328           47 :     cnt = scandir(storage_path, &files, 0, alphasort);
     329              : 
     330           47 :     if (cnt < 0) {
     331            0 :         dlt_vlog(LOG_ERR, "%s: Failed to scan directory [%s] for file name [%s]\n", __func__, storage_path, file_name);
     332            0 :         return -1;
     333              :     }
     334              : 
     335           47 :     dlt_vlog(LOG_DEBUG, "%s: Scanned [%d] files from %s\n", __func__, cnt, storage_path);
     336              : 
     337              :     /* In order to have a latest status of file list,
     338              :      * the existing records must be deleted before updating
     339              :      */
     340           47 :     n = config->records;
     341           47 :     if (config->records) {
     342           66 :         while (n) {
     343              :             n1 = n;
     344           38 :             n = n->next;
     345           38 :             free(n1->name);
     346              :             n1->name = NULL;
     347           38 :             free(n1);
     348              :             n1 = NULL;
     349              :         }
     350           28 :         config->records = NULL;
     351              :     }
     352              : 
     353           47 :     char* suffix = config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON ? ".dlt.gz" : ".dlt";
     354              : 
     355         1113 :     for (i = 0; i < cnt; i++) {
     356         1066 :         size_t len = strlen(file_name);
     357              : 
     358         1066 :         dlt_vlog(
     359         1066 :             LOG_DEBUG, "%s: Scanned file name=[%s], filter file name=[%s]\n", __func__, files[i]->d_name, file_name);
     360         1066 :         if (strncmp(files[i]->d_name, file_name, len) == 0) {
     361           70 :             if (config->num_files == 1 && file_config->logfile_optional_counter) {
     362              :                 /* <filename>.dlt or <filename>_<tmsp>.dlt */
     363            0 :                 if ((files[i]->d_name[len] == suffix[0])
     364            0 :                     || (file_config->logfile_timestamp && (files[i]->d_name[len] == file_config->logfile_delimiter))) {
     365              :                     current_idx = 1;
     366              :                 } else {
     367           28 :                     continue;
     368              :                 }
     369              :             } else {
     370              :                 /* <filename>_idx.dlt or <filename>_idx_<tmsp>.dlt */
     371           70 :                 if (files[i]->d_name[len] == file_config->logfile_delimiter) {
     372           42 :                     current_idx = dlt_logstorage_get_idx_of_log_file(file_config, config, files[i]->d_name);
     373              :                 } else {
     374           28 :                     continue;
     375              :                 }
     376              :             }
     377              : 
     378              :             DltLogStorageFileList** tmp = NULL;
     379              : 
     380           42 :             if (config->records == NULL) {
     381           31 :                 config->records = malloc(sizeof(DltLogStorageFileList));
     382              : 
     383           31 :                 if (config->records == NULL) {
     384              :                     ret = -1;
     385            0 :                     dlt_log(LOG_ERR, "Memory allocation failed\n");
     386            0 :                     break;
     387              :                 }
     388              : 
     389           31 :                 tmp = &config->records;
     390              :             } else {
     391           11 :                 tmp = &config->records;
     392              : 
     393           22 :                 while (*(tmp) != NULL)
     394           11 :                     tmp = &(*tmp)->next;
     395              : 
     396           11 :                 *tmp = malloc(sizeof(DltLogStorageFileList));
     397              : 
     398           11 :                 if (*tmp == NULL) {
     399              :                     ret = -1;
     400            0 :                     dlt_log(LOG_ERR, "Memory allocation failed\n");
     401            0 :                     break;
     402              :                 }
     403              :             }
     404              : 
     405           42 :             char tmpfile[DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN + 1] = {'\0'};
     406              :             size_t needed = 0;
     407           42 :             if (dir != NULL) {
     408              :                 /* Append directory path */
     409            0 :                 needed = strlen(dir) + 1 + strlen(files[i]->d_name);
     410              :             } else {
     411           42 :                 needed = strlen(files[i]->d_name);
     412              :             }
     413              : 
     414           42 :             if (needed >= sizeof(tmpfile)) {
     415            0 :                 dlt_vlog(
     416              :                     LOG_ERR, "%s: File path too long (dir=[%s], file=[%s]), skipping\n", __func__, dir ? dir : "",
     417            0 :                     files[i]->d_name);
     418            0 :                 free(*tmp);
     419            0 :                 *tmp = NULL;
     420              :                 ret = -1;
     421            0 :                 break;
     422              :             }
     423              : 
     424           42 :             if (dir != NULL) {
     425            0 :                 size_t pos = strlen(dir);
     426              :                 memcpy(tmpfile, dir, pos);
     427            0 :                 tmpfile[pos++] = '/';
     428            0 :                 memcpy(tmpfile + pos, files[i]->d_name, strlen(files[i]->d_name) + 1);
     429              :             } else {
     430           42 :                 memcpy(tmpfile, files[i]->d_name, strlen(files[i]->d_name) + 1);
     431              :             }
     432           42 :             (*tmp)->name = strdup(tmpfile);
     433           42 :             (*tmp)->idx = current_idx;
     434           42 :             (*tmp)->next = NULL;
     435           42 :             check++;
     436              :         }
     437              :     }
     438              : 
     439           47 :     dlt_vlog(LOG_DEBUG, "%s: After dir scan: [%d] files of [%s]\n", __func__, check, file_name);
     440              : 
     441           47 :     if (ret == 0) {
     442           47 :         max_idx = dlt_logstorage_sort_file_name(&config->records);
     443              : 
     444              :         /* Fault tolerance:
     445              :          * In case there are some log files are removed but
     446              :          * the index is still not reaching maxcounter, no need
     447              :          * to perform rearrangement of filename.
     448              :          * This would help the log keeps growing until maxcounter is reached and
     449              :          * the maximum number of log files could be obtained.
     450              :          */
     451           47 :         if (max_idx == file_config->logfile_maxcounter)
     452            0 :             dlt_logstorage_rearrange_file_name(&config->records);
     453              :     }
     454              : 
     455              :     /* free scandir result */
     456         1113 :     for (i = 0; i < cnt; i++)
     457         1066 :         free(files[i]);
     458              : 
     459           47 :     free(files);
     460              : 
     461           47 :     return ret;
     462              : }
     463              : 
     464              : /**
     465              :  * dlt_logstorage_open_log_output_file
     466              :  *
     467              :  * Open a handle to the logfile
     468              :  *
     469              :  * @param config    A pointer to the current DltLogStorageFilterConfig
     470              :  * @param fpath     The file path
     471              :  * @param mode      The mode to open the file with
     472              :  */
     473           33 : DLT_STATIC void dlt_logstorage_open_log_output_file(
     474              :     DltLogStorageFilterConfig* config, const char* fpath, const char* mode)
     475              : {
     476           33 :     FILE* file = fopen(fpath, mode);
     477           33 :     if (file == NULL) {
     478            0 :         dlt_vlog(LOG_DEBUG, "%s: could not open configuration file\n", __func__);
     479            0 :         return;
     480              :     }
     481           33 :     config->fd = fileno(file);
     482           33 :     if (config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON) {
     483              : #ifdef DLT_LOGSTORAGE_USE_GZIP
     484              :         dlt_vlog(LOG_DEBUG, "%s: Opening GZIP log file\n", __func__);
     485              :         config->gzlog = gzdopen(config->fd, mode);
     486              : #endif
     487              :     } else {
     488           33 :         dlt_vlog(LOG_DEBUG, "%s: Opening log file\n", __func__);
     489           33 :         config->log = file;
     490              :     }
     491              : }
     492              : 
     493              : /**
     494              :  * dlt_logstorage_open_log_file
     495              :  *
     496              :  * Open a log file. Check storage directory for already created files and open
     497              :  * the oldest if there is enough space to store at least msg_size.
     498              :  * Otherwise create a new file, but take configured max number of files into
     499              :  * account and remove the oldest file if needed.
     500              :  *
     501              :  * @param  config    DltLogStorageFilterConfig
     502              :  * @param  file_config   User configurations for log file
     503              :  * @param  dev_path      Storage device path
     504              :  * @param  msg_size  Size of incoming message
     505              :  * @param  is_update_required   The file list needs to be updated
     506              :  * @return 0 on succes, -1 on error
     507              :  */
     508           47 : int dlt_logstorage_open_log_file(
     509              :     DltLogStorageFilterConfig* config, DltLogStorageUserConfig* file_config, char* dev_path, int msg_size,
     510              :     bool is_update_required, bool is_sync)
     511              : {
     512              :     int ret = 0;
     513           47 :     char absolute_file_path[DLT_OFFLINE_LOGSTORAGE_MAX_PATH_LEN + 1] = {'\0'};
     514           47 :     char storage_path[DLT_MOUNT_PATH_MAX + 1] = {'\0'};
     515           47 :     char file_name[DLT_OFFLINE_LOGSTORAGE_MAX_LOG_FILE_LEN + 1] = {'\0'};
     516              :     unsigned int num_log_files = 0;
     517              :     struct stat s;
     518              :     memset(&s, 0, sizeof(struct stat));
     519              :     DltLogStorageFileList** tmp = NULL;
     520              :     DltLogStorageFileList** newest = NULL;
     521              : 
     522           47 :     if (config == NULL)
     523              :         return -1;
     524              : 
     525           46 :     if (strlen(dev_path) > DLT_MOUNT_PATH_MAX) {
     526            0 :         dlt_vlog(LOG_ERR, "device path '%s' is too long to store\n", dev_path);
     527            0 :         return -1;
     528              :     }
     529              : 
     530           46 :     size_t dev_path_len = strnlen(dev_path, DLT_MOUNT_PATH_MAX - 2);
     531           46 :     if (dev_path_len + 2 > DLT_MOUNT_PATH_MAX) {
     532            0 :         dlt_vlog(LOG_ERR, "device path too long for storage_path buffer\n");
     533            0 :         return -1;
     534              :     }
     535              :     int written = snprintf(storage_path, DLT_MOUNT_PATH_MAX, "%s/", dev_path);
     536           46 :     if (written < 0 || (size_t)written >= DLT_MOUNT_PATH_MAX) {
     537            0 :         dlt_vlog(LOG_ERR, "snprintf truncated storage_path\n");
     538            0 :         return -1;
     539              :     }
     540              : 
     541              :     /* check if there are already files stored */
     542           46 :     if (config->records == NULL || is_update_required) {
     543           46 :         if (dlt_logstorage_storage_dir_info(file_config, storage_path, config) != 0)
     544              :             return -1;
     545              :     }
     546              : 
     547              :     /* obtain locations of newest, current file names, file count */
     548           46 :     tmp = &config->records;
     549              : 
     550           88 :     while (*(tmp) != NULL) {
     551           42 :         num_log_files += 1;
     552              : 
     553           42 :         if ((*tmp)->next == NULL)
     554              :             newest = tmp;
     555              : 
     556           42 :         tmp = &(*tmp)->next;
     557              :     }
     558              : 
     559              :     /* need new file*/
     560           46 :     if (num_log_files == 0) {
     561           15 :         dlt_logstorage_log_file_name(file_name, file_config, config, config->file_name, (int)config->num_files, 1);
     562              : 
     563              :         /* concatenate path and file and open absolute path */
     564              :         strcat(absolute_file_path, storage_path);
     565              :         strcat(absolute_file_path, file_name);
     566           15 :         config->working_file_name = strdup(file_name);
     567           15 :         dlt_logstorage_open_log_output_file(config, absolute_file_path, "a");
     568              : 
     569              :         /* Add file to file list */
     570           15 :         *tmp = malloc(sizeof(DltLogStorageFileList));
     571              : 
     572           15 :         if (*tmp == NULL) {
     573            0 :             dlt_log(LOG_ERR, "Memory allocation for file name failed\n");
     574            0 :             return -1;
     575              :         }
     576              : 
     577           15 :         (*tmp)->name = strdup(file_name);
     578           15 :         (*tmp)->idx = 1;
     579           15 :         (*tmp)->next = NULL;
     580              :     } else {
     581              :         strcat(absolute_file_path, storage_path);
     582              : 
     583              :         /* newest file available
     584              :          * Since the working file is already updated from newest file info
     585              :          * So if there is already wrap-up, the newest file will be the working file
     586              :          */
     587           31 :         if ((config->wrap_id == 0) || (config->working_file_name == NULL)) {
     588           29 :             if (config->working_file_name != NULL) {
     589           28 :                 free(config->working_file_name);
     590           28 :                 config->working_file_name = NULL;
     591              :             }
     592           29 :             config->working_file_name = strdup((*newest)->name);
     593              :         }
     594           31 :         size_t abs_len = strnlen(absolute_file_path, sizeof(absolute_file_path));
     595           31 :         size_t name_len = strnlen(config->working_file_name, sizeof(absolute_file_path) - abs_len - 1);
     596           31 :         if (abs_len + name_len >= sizeof(absolute_file_path)) {
     597            0 :             dlt_vlog(LOG_ERR, "absolute_file_path too small for working_file_name\n");
     598            0 :             return -1;
     599              :         }
     600           31 :         snprintf(absolute_file_path + abs_len, sizeof(absolute_file_path) - abs_len, "%s", config->working_file_name);
     601              : 
     602           31 :         dlt_vlog(
     603              :             LOG_DEBUG, "%s: Number of log files-newest file-wrap_id [%u]-[%s]-[%u]\n", __func__, num_log_files,
     604              :             config->working_file_name, config->wrap_id);
     605              : 
     606           31 :         ret = stat(absolute_file_path, &s);
     607              : 
     608              :         /* if file stats is read and, either
     609              :          * is_sync is true and (other than ON_MSG sync behavior and current size is less than configured size) or
     610              :          * msg_size fit into the size (ON_MSG or par of cache needs to be written into new file), open it */
     611           31 :         if ((ret == 0)
     612           31 :             && ((is_sync && (s.st_size < (long)config->file_size))
     613           13 :                 || (!is_sync && (s.st_size + msg_size <= (long)config->file_size)))) {
     614           18 :             dlt_logstorage_open_log_output_file(config, absolute_file_path, "a");
     615           18 :             config->current_write_file_offset = (unsigned int)s.st_size;
     616              :         } else {
     617              :             /* no space in file or file stats cannot be read */
     618              :             unsigned int idx = 0;
     619              : 
     620              :             /* get index of newest log file */
     621           13 :             if (config->num_files == 1 && file_config->logfile_optional_counter) {
     622              :                 idx = 1;
     623              :             } else {
     624           13 :                 idx = dlt_logstorage_get_idx_of_log_file(file_config, config, config->working_file_name);
     625              :             }
     626              : 
     627              :             /* Check if file logging shall be stopped */
     628           13 :             if (config->overwrite == DLT_LOGSTORAGE_OVERWRITE_DISCARD_NEW) {
     629            5 :                 dlt_vlog(
     630              :                     LOG_DEBUG, "%s: num_files=%d, current_idx=%d (filename=%s)\n", __func__, config->num_files, idx,
     631              :                     config->file_name);
     632              : 
     633            5 :                 if (config->num_files == idx) {
     634            2 :                     dlt_vlog(
     635              :                         LOG_INFO, "%s: logstorage limit reached, stopping capture for filter: %s\n", __func__,
     636              :                         config->file_name);
     637            2 :                     config->skip = 1;
     638            2 :                     return 0;
     639              :                 }
     640              :             }
     641              : 
     642           11 :             idx += 1;
     643              : 
     644              :             /* wrap around if max index is reached or an error occurred
     645              :              * while calculating index from file name */
     646           11 :             if ((idx > file_config->logfile_maxcounter) || (idx == 0)) {
     647              :                 idx = 1;
     648            2 :                 config->wrap_id += 1;
     649              :             }
     650              : 
     651           11 :             dlt_logstorage_log_file_name(
     652           11 :                 file_name, file_config, config, config->file_name, (int)config->num_files, (int)idx);
     653              : 
     654              :             /* concatenate path and file and open absolute path */
     655              :             memset(absolute_file_path, 0, sizeof(absolute_file_path) / sizeof(char));
     656              :             strcat(absolute_file_path, storage_path);
     657              :             strcat(absolute_file_path, file_name);
     658              : 
     659           11 :             if (config->working_file_name) {
     660           11 :                 free(config->working_file_name);
     661           11 :                 config->working_file_name = strdup(file_name);
     662              :             }
     663              : 
     664              :             /* If there is already wrap-up, check the existence of file
     665              :              * remove it and reopen it.
     666              :              * In this case number of log file won't be increased*/
     667           11 :             if (config->wrap_id && stat(absolute_file_path, &s) == 0) {
     668            1 :                 remove(absolute_file_path);
     669            1 :                 num_log_files -= 1;
     670            1 :                 dlt_vlog(
     671              :                     LOG_DEBUG, "%s: Remove '%s' (num_log_files: %u, config->num_files:%u)\n", __func__,
     672              :                     absolute_file_path, num_log_files, config->num_files);
     673              :             }
     674              : 
     675           11 :             config->log = fopen(absolute_file_path, "w+");
     676              : 
     677           11 :             dlt_vlog(LOG_DEBUG, "%s: Filename and Index after updating [%s]-[%u]\n", __func__, file_name, idx);
     678              : 
     679              :             /* Add file to file list */
     680           11 :             *tmp = malloc(sizeof(DltLogStorageFileList));
     681              : 
     682           11 :             if (*tmp == NULL) {
     683            0 :                 dlt_log(LOG_ERR, "Memory allocation for file name failed\n");
     684            0 :                 return -1;
     685              :             }
     686              : 
     687           11 :             (*tmp)->name = strdup(file_name);
     688           11 :             (*tmp)->idx = idx;
     689           11 :             (*tmp)->next = NULL;
     690              : 
     691           11 :             num_log_files += 1;
     692              : 
     693              :             /* check if number of log files exceeds configured max value */
     694           11 :             if (num_log_files > config->num_files) {
     695            5 :                 if (!(config->num_files == 1 && file_config->logfile_optional_counter)) {
     696              :                     /* delete oldest */
     697              :                     DltLogStorageFileList** head = &config->records;
     698            5 :                     DltLogStorageFileList* n = *head;
     699              :                     memset(absolute_file_path, 0, sizeof(absolute_file_path) / sizeof(char));
     700              :                     strcat(absolute_file_path, storage_path);
     701            5 :                     size_t abs_len2 = strnlen(absolute_file_path, sizeof(absolute_file_path));
     702            5 :                     size_t head_name_len = strnlen((*head)->name, sizeof(absolute_file_path) - abs_len2 - 1);
     703            5 :                     if (abs_len2 + head_name_len >= sizeof(absolute_file_path)) {
     704            0 :                         dlt_vlog(LOG_ERR, "absolute_file_path too small for head->name\n");
     705            0 :                         return -1;
     706              :                     }
     707            5 :                     snprintf(absolute_file_path + abs_len2, sizeof(absolute_file_path) - abs_len2, "%s", (*head)->name);
     708            5 :                     dlt_vlog(
     709              :                         LOG_DEBUG, "%s: Remove '%s' (num_log_files: %d, config->num_files:%d, file_name:%s)\n",
     710              :                         __func__, absolute_file_path, num_log_files, config->num_files, config->file_name);
     711            5 :                     if (remove(absolute_file_path) != 0)
     712            0 :                         dlt_log(LOG_ERR, "Could not remove file\n");
     713              : 
     714            5 :                     free((*head)->name);
     715            5 :                     (*head)->name = NULL;
     716            5 :                     *head = n->next;
     717              :                     n->next = NULL;
     718            5 :                     free(n);
     719              :                 }
     720              :             }
     721              :         }
     722              :     }
     723              : 
     724              : #ifdef DLT_LOGSTORAGE_USE_GZIP
     725              :     if (config->gzlog == NULL && config->log == NULL) {
     726              : #else
     727           44 :     if (config->log == NULL) {
     728              : #endif
     729            0 :         if (*tmp != NULL) {
     730            0 :             if ((*tmp)->name != NULL) {
     731            0 :                 free((*tmp)->name);
     732            0 :                 (*tmp)->name = NULL;
     733              :             }
     734            0 :             free(*tmp);
     735            0 :             *tmp = NULL;
     736              :         }
     737              : 
     738            0 :         if (config->working_file_name != NULL) {
     739            0 :             free(config->working_file_name);
     740            0 :             config->working_file_name = NULL;
     741              :         }
     742              : 
     743            0 :         dlt_vlog(LOG_ERR, "%s: Unable to open log file.\n", __func__);
     744            0 :         return -1;
     745              :     }
     746              : 
     747              :     return ret;
     748              : }
     749              : 
     750              : /**
     751              :  * dlt_logstorage_find_dlt_header
     752              :  *
     753              :  * search for dlt header in cache
     754              :  *
     755              :  * @param ptr         cache starting position
     756              :  * @param offset      offset
     757              :  * @param cnt         count
     758              :  * @return index on success, -1 on error
     759              :  */
     760           36 : DLT_STATIC int dlt_logstorage_find_dlt_header(void* ptr, unsigned int offset, unsigned int cnt)
     761              : {
     762           36 :     const char magic[] = {'D', 'L', 'T', 0x01};
     763           36 :     const char* cache = (char*)ptr + offset;
     764              : 
     765              :     unsigned int i;
     766           50 :     for (i = 0; i < cnt; i++) {
     767           48 :         if ((cache[i] == 'D') && (strncmp(&cache[i], magic, 4) == 0))
     768           34 :             return (int)i;
     769              :     }
     770              : 
     771              :     return -1;
     772              : }
     773              : 
     774              : /**
     775              :  * dlt_logstorage_find_last_dlt_header
     776              :  *
     777              :  * search for last dlt header in cache
     778              :  *
     779              :  * @param ptr         cache starting position
     780              :  * @param offset      offset
     781              :  * @param cnt         count
     782              :  * @return index on success, -1 on error
     783              :  */
     784            8 : DLT_STATIC int dlt_logstorage_find_last_dlt_header(void* ptr, unsigned int offset, unsigned int cnt)
     785              : {
     786            8 :     const char magic[] = {'D', 'L', 'T', 0x01};
     787            8 :     const char* cache = (char*)ptr + offset;
     788              : 
     789              :     int i;
     790          452 :     for (i = (int)cnt - (DLT_ID_SIZE - 1); i > 0; i--) {
     791          448 :         if ((cache[i] == 'D') && (strncmp(&cache[i], magic, 4) == 0))
     792            4 :             return i;
     793              :     }
     794              : 
     795              :     return -1;
     796              : }
     797              : 
     798              : /**
     799              :  * dlt_logstorage_write_to_log
     800              :  *
     801              :  * Write logdata to log storage file
     802              :  *
     803              :  * @param ptr       A pointer to the data to write
     804              :  * @param size      The size of the data blocks
     805              :  * @param nmemb     The number of blocks to write
     806              :  * @param config    A pointer to DltLogStorageFilterConfig
     807              :  */
     808            5 : DLT_STATIC int dlt_logstorage_write_to_log(void* ptr, size_t size, size_t nmemb, DltLogStorageFilterConfig* config)
     809              : {
     810              : #ifdef DLT_LOGSTORAGE_USE_GZIP
     811              :     if (config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON) {
     812              :         return (int)gzfwrite(ptr, size, nmemb, config->gzlog);
     813              :     } else {
     814              :         return (int)fwrite(ptr, size, nmemb, config->log);
     815              :     }
     816              : #else
     817            5 :     return (int)fwrite(ptr, size, nmemb, config->log);
     818              : #endif
     819              : }
     820              : 
     821              : /**
     822              :  * dlt_logstorage_check_write_ret
     823              :  *
     824              :  * check the return value of fwrite/gzfwrite
     825              :  *
     826              :  * @param config      DltLogStorageFilterConfig
     827              :  * @param ret         return value of fwrite/gzfwrite call
     828              :  */
     829           29 : DLT_STATIC void dlt_logstorage_check_write_ret(DltLogStorageFilterConfig* config, int ret)
     830              : {
     831           29 :     if (config == NULL) {
     832            0 :         dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__);
     833            0 :         return;
     834              :     }
     835              : 
     836           29 :     if (ret <= 0) {
     837            0 :         if (config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON) {
     838              : #ifdef DLT_LOGSTORAGE_USE_GZIP
     839              :             const char* msg = gzerror(config->gzlog, &ret);
     840              :             if (msg != NULL) {
     841              :                 dlt_vlog(LOG_ERR, "%s: failed to write cache into log file: %s\n", __func__, msg);
     842              :             }
     843              : #endif
     844              :         } else {
     845            0 :             if (ferror(config->log) != 0)
     846            0 :                 dlt_vlog(LOG_ERR, "%s: failed to write cache into log file\n", __func__);
     847              :         }
     848              :     } else {
     849              :         /* force sync */
     850           29 :         if (config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON) {
     851              : #ifdef DLT_LOGSTORAGE_USE_GZIP
     852              :             if (gzflush(config->gzlog, Z_SYNC_FLUSH) != 0)
     853              :                 dlt_vlog(LOG_ERR, "%s: failed to gzflush log file\n", __func__);
     854              : #endif
     855              :         } else {
     856           29 :             if (fflush(config->log) != 0)
     857            0 :                 dlt_vlog(LOG_ERR, "%s: failed to flush log file\n", __func__);
     858              :         }
     859              : 
     860           29 :         if (fsync(config->fd) != 0) {
     861              :             /* some filesystem doesn't support fsync() */
     862            0 :             if (errno != ENOSYS) {
     863            0 :                 dlt_vlog(LOG_ERR, "%s: failed to sync log file\n", __func__);
     864              :             }
     865              :         }
     866              :     }
     867              : }
     868              : 
     869              : /**
     870              :  * dlt_logstorage_close_file
     871              :  *
     872              :  * Close open file handles if any exist in the provided
     873              :  * DltLogStorageFilterConfig
     874              :  *
     875              :  * @param config    The DltLogStorageFilterConfig to operate on
     876              :  */
     877            4 : DLT_STATIC void dlt_logstorage_close_file(DltLogStorageFilterConfig* config)
     878              : {
     879              : #ifdef DLT_LOGSTORAGE_USE_GZIP
     880              :     if (config->gzlog) {
     881              :         gzclose(config->gzlog);
     882              :         config->gzlog = NULL;
     883              :     }
     884              : #endif
     885           19 :     if (config->log) {
     886           37 :         fclose(config->log);
     887           37 :         config->log = NULL;
     888              :     }
     889            4 : }
     890              : 
     891              : /**
     892              :  * dlt_logstorage_sync_to_file
     893              :  *
     894              :  * Write the log message to log file
     895              :  *
     896              :  * @param config        DltLogStorageFilterConfig
     897              :  * @param file_config   DltLogStorageUserConfig
     898              :  * @param dev_path      Storage device mount point path
     899              :  * @param footer        DltLogStorageCacheFooter
     900              :  * @param start_offset  Start offset of the cache
     901              :  * @param end_offset    End offset of the cache
     902              :  * @return 0 on success, -1 on error
     903              :  */
     904           29 : DLT_STATIC int dlt_logstorage_sync_to_file(
     905              :     DltLogStorageFilterConfig* config, DltLogStorageUserConfig* file_config, char* dev_path,
     906              :     DltLogStorageCacheFooter* footer, unsigned int start_offset, unsigned int end_offset)
     907              : {
     908              :     int ret = 0;
     909              :     int start_index = 0;
     910              :     int end_index = 0;
     911              :     int count = 0;
     912              :     unsigned int remain_file_size = 0;
     913              : 
     914           29 :     if ((config == NULL) || (file_config == NULL) || (dev_path == NULL) || (footer == NULL)) {
     915            1 :         dlt_vlog(LOG_ERR, "%s: cannot retrieve config information\n", __func__);
     916            1 :         return -1;
     917              :     }
     918              : 
     919           28 :     count = (int)(end_offset - start_offset);
     920              : 
     921              :     /* In case of cached-based strategy, the newest file information
     922              :      * must be updated everytime of synchronization.
     923              :      */
     924            2 :     dlt_logstorage_close_file(config);
     925           28 :     config->current_write_file_offset = 0;
     926              : 
     927           28 :     if (dlt_logstorage_open_log_file(config, file_config, dev_path, count, true, true) != 0) {
     928            0 :         dlt_vlog(LOG_ERR, "%s: failed to open log file\n", __func__);
     929            0 :         return -1;
     930              :     }
     931              : 
     932           28 :     if (config->skip == 1) {
     933            0 :         dlt_logstorage_close_file(config);
     934            0 :         return 0;
     935              :     }
     936              : 
     937           28 :     remain_file_size = (unsigned int)(config->file_size - config->current_write_file_offset);
     938              : 
     939           28 :     if ((unsigned int)count > remain_file_size) {
     940              :         /* Check if more than one message can fit into the remaining file */
     941            6 :         start_index = dlt_logstorage_find_dlt_header(config->cache, start_offset, remain_file_size);
     942            6 :         end_index = dlt_logstorage_find_last_dlt_header(
     943              :             config->cache, (unsigned int)start_offset + (unsigned int)start_index,
     944            6 :             remain_file_size - (unsigned int)start_index);
     945            6 :         count = (int)(end_index - start_index);
     946              : 
     947            6 :         if ((start_index >= 0) && (end_index > start_index) && (count > 0)
     948            3 :             && ((unsigned int)count <= remain_file_size)) {
     949            3 :             ret = dlt_logstorage_write_to_log(
     950            3 :                 (uint8_t*)config->cache + start_offset + start_index, (size_t)count, 1, config);
     951            3 :             dlt_logstorage_check_write_ret(config, ret);
     952              : 
     953              :             /* Close log file */
     954            0 :             dlt_logstorage_close_file(config);
     955            3 :             config->current_write_file_offset = 0;
     956              : 
     957            3 :             footer->last_sync_offset = (unsigned int)start_offset + (unsigned int)count;
     958            3 :             start_offset = footer->last_sync_offset;
     959              :         } else {
     960              :             /* Close log file */
     961            0 :             dlt_logstorage_close_file(config);
     962            3 :             config->current_write_file_offset = 0;
     963              :         }
     964              :     }
     965              : 
     966           28 :     start_index = dlt_logstorage_find_dlt_header(config->cache, start_offset, (unsigned int)count);
     967           28 :     count = (int)(end_offset - start_offset - (unsigned int)start_index);
     968              : 
     969           28 :     if ((start_index >= 0) && (count > 0)) {
     970              :         /* Prepare log file */
     971              : #ifdef DLT_LOGSTORAGE_USE_GZIP
     972              :         if (config->log == NULL && config->gzlog == NULL)
     973              : #else
     974           27 :         if (config->log == NULL)
     975              : #endif
     976              :         {
     977            6 :             if (dlt_logstorage_open_log_file(config, file_config, dev_path, count, true, false) != 0) {
     978            0 :                 dlt_vlog(LOG_ERR, "%s: failed to open log file\n", __func__);
     979            0 :                 dlt_logstorage_close_file(config);
     980            0 :                 return -1;
     981              :             }
     982              : 
     983            6 :             if (config->skip == 1) {
     984            0 :                 dlt_logstorage_close_file(config);
     985            1 :                 return 0;
     986              :             }
     987              :         }
     988              : 
     989              :         ret =
     990           26 :             dlt_logstorage_write_to_log((uint8_t*)config->cache + start_offset + start_index, (size_t)count, 1, config);
     991           26 :         dlt_logstorage_check_write_ret(config, ret);
     992              : 
     993           26 :         config->current_write_file_offset += (unsigned int)count;
     994           26 :         footer->last_sync_offset = (unsigned int)end_offset;
     995              :     }
     996              : 
     997           27 :     footer->wrap_around_cnt = 0;
     998            2 :     dlt_logstorage_close_file(config);
     999            2 :     return 0;
    1000              : }
    1001              : 
    1002              : /**
    1003              :  * dlt_logstorage_prepare_on_msg
    1004              :  *
    1005              :  * Prepare the log file for a certain filer. If log file not open or log
    1006              :  * files max size reached, open a new file.
    1007              :  *
    1008              :  * @param config        DltLogStorageFilterConfig
    1009              :  * @param file_config   User configurations for log file
    1010              :  * @param dev_path      Storage device path
    1011              :  * @param log_msg_size  Size of log message
    1012              :  * @param newest_file_info   Info of newest file for corresponding filename
    1013              :  * @return 0 on success, -1 on error
    1014              :  */
    1015           56 : int dlt_logstorage_prepare_on_msg(
    1016              :     DltLogStorageFilterConfig* config, DltLogStorageUserConfig* file_config, char* dev_path, int log_msg_size,
    1017              :     DltNewestFileName* newest_file_info)
    1018              : {
    1019              :     int ret = 0;
    1020              :     struct stat s;
    1021              : 
    1022           56 :     if ((config == NULL) || (file_config == NULL) || (dev_path == NULL) || (newest_file_info == NULL)) {
    1023            1 :         dlt_vlog(LOG_INFO, "%s: Wrong paratemters\n", __func__);
    1024            1 :         return -1;
    1025              :     }
    1026              : 
    1027              :     /* This is for ON_MSG/UNSET strategy */
    1028              :     /* Handle log file open for ON_MSG/UNSET strategy */
    1029              : #ifdef DLT_LOGSTORAGE_USE_GZIP
    1030              :     if (config->log == NULL && config->gzlog == NULL) {
    1031              : #else
    1032           55 :     if (config->log == NULL) {
    1033              : #endif
    1034              :         /* Sync the wrap id and working file name before opening log file */
    1035            6 :         if (config->wrap_id < newest_file_info->wrap_id) {
    1036            2 :             config->wrap_id = newest_file_info->wrap_id;
    1037            2 :             if (config->working_file_name) {
    1038            1 :                 free(config->working_file_name);
    1039            1 :                 config->working_file_name = NULL;
    1040              :             }
    1041            2 :             config->working_file_name = strdup(newest_file_info->newest_file);
    1042              :         }
    1043              : 
    1044              :         /* open a new log file */
    1045            6 :         ret = dlt_logstorage_open_log_file(config, file_config, dev_path, log_msg_size, true, false);
    1046              :     } else { /* already open, check size and create a new file if needed */
    1047           49 :         ret = fstat(config->fd, &s);
    1048              : 
    1049           49 :         if (ret == 0) {
    1050              :             /* Check if adding new data do not exceed max file size
    1051              :              *
    1052              :              * This is inaccurate for gz compressed files but as long as log
    1053              :              * messages aren't gigantic it should be negligeble
    1054              :              *
    1055              :              * Also check if wrap id needs to be updated */
    1056           44 :             if ((s.st_size + log_msg_size > (int)config->file_size)
    1057           40 :                 || (strcmp(config->working_file_name, newest_file_info->newest_file) != 0)
    1058           40 :                 || (config->wrap_id < newest_file_info->wrap_id)) {
    1059              :                 /* Sync only if on_msg */
    1060            4 :                 if ((config->sync == DLT_LOGSTORAGE_SYNC_ON_MSG) || (config->sync == DLT_LOGSTORAGE_SYNC_UNSET)) {
    1061              : #ifdef DLT_LOGSTORAGE_USE_GZIP
    1062              :                     if (config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON) {
    1063              :                         if (fsync(config->fd) != 0) {
    1064              :                             if (errno != ENOSYS) {
    1065              :                                 dlt_vlog(LOG_ERR, "%s: failed to sync gzip log file\n", __func__);
    1066              :                             }
    1067              :                         }
    1068              :                     } else
    1069              : #endif
    1070              :                     {
    1071            4 :                         if (fsync(fileno(config->log)) != 0) {
    1072            0 :                             if (errno != ENOSYS) {
    1073            0 :                                 dlt_vlog(LOG_ERR, "%s: failed to sync log file\n", __func__);
    1074              :                             }
    1075              :                         }
    1076              :                     }
    1077              :                 }
    1078              : 
    1079            0 :                 dlt_logstorage_close_file(config);
    1080              : 
    1081              :                 /* Sync the wrap id and working file name before opening log file */
    1082            4 :                 if (config->wrap_id <= newest_file_info->wrap_id) {
    1083            4 :                     config->wrap_id = newest_file_info->wrap_id;
    1084            4 :                     if (config->working_file_name) {
    1085            4 :                         free(config->working_file_name);
    1086            4 :                         config->working_file_name = NULL;
    1087              :                     }
    1088            4 :                     config->working_file_name = strdup(newest_file_info->newest_file);
    1089              :                 }
    1090              : 
    1091            4 :                 ret = dlt_logstorage_open_log_file(config, file_config, dev_path, log_msg_size, true, false);
    1092              :             } else { /*everything is prepared */
    1093              :                 ret = 0;
    1094              :             }
    1095              :         } else {
    1096            5 :             dlt_vlog(LOG_ERR, "%s: stat() failed.\n", __func__);
    1097              :             ret = -1;
    1098              :         }
    1099              :     }
    1100              : 
    1101              :     return ret;
    1102              : }
    1103              : 
    1104              : /**
    1105              :  * dlt_logstorage_write_on_msg
    1106              :  *
    1107              :  * Write the log message.
    1108              :  *
    1109              :  * @param config        DltLogStorageFilterConfig
    1110              :  * @param file_config   DltLogStorageUserConfig
    1111              :  * @param dev_path      Path to device
    1112              :  * @param data1         header
    1113              :  * @param size1         header size
    1114              :  * @param data2         storage header
    1115              :  * @param size2         storage header size
    1116              :  * @param data3         payload
    1117              :  * @param size3         payload size
    1118              :  * @return 0 on success, -1 on error
    1119              :  */
    1120           47 : int dlt_logstorage_write_on_msg(
    1121              :     DltLogStorageFilterConfig* config, DltLogStorageUserConfig* file_config, char* dev_path, unsigned char* data1,
    1122              :     int size1, unsigned char* data2, int size2, unsigned char* data3, int size3)
    1123              : {
    1124              :     int ret;
    1125              : 
    1126           47 :     if ((config == NULL) || (data1 == NULL) || (data2 == NULL) || (data3 == NULL) || (file_config == NULL)
    1127           46 :         || (dev_path == NULL)) {
    1128              :         return -1;
    1129              :     }
    1130              : 
    1131           46 :     ret = dlt_logstorage_write_to_log(data1, 1, (size_t)size1, config);
    1132              : 
    1133           46 :     if (ret != size1)
    1134            0 :         dlt_log(LOG_WARNING, "Wrote less data than specified\n");
    1135              : 
    1136           46 :     ret = dlt_logstorage_write_to_log(data2, 1, (size_t)size2, config);
    1137           46 :     if (ret != size2)
    1138            0 :         dlt_log(LOG_WARNING, "Wrote less data than specified\n");
    1139              : 
    1140           46 :     ret = dlt_logstorage_write_to_log(data3, 1, (size_t)size3, config);
    1141           46 :     if (ret != size3)
    1142            0 :         dlt_log(LOG_WARNING, "Wrote less data than specified\n");
    1143              : 
    1144              : #ifdef DLT_LOGSTORAGE_USE_GZIP
    1145              :     if (config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON) {
    1146              :         gzerror(config->gzlog, &ret);
    1147              :         return ret;
    1148              :     } else {
    1149              :         return ferror(config->log);
    1150              :     }
    1151              : #else
    1152           46 :     return ferror(config->log);
    1153              : #endif
    1154              : }
    1155              : 
    1156              : /**
    1157              :  * dlt_logstorage_sync_on_msg
    1158              :  *
    1159              :  * sync data to disk.
    1160              :  *
    1161              :  * @param config        DltLogStorageFilterConfig
    1162              :  * @param file_config   User configurations for log file
    1163              :  * @param dev_path      Storage device path
    1164              :  * @param status        Strategy flag
    1165              :  * @return 0 on success, -1 on error
    1166              :  */
    1167          103 : int dlt_logstorage_sync_on_msg(
    1168              :     DltLogStorageFilterConfig* config, DltLogStorageUserConfig* file_config, char* dev_path, int status)
    1169              : {
    1170              :     (void)file_config; /* satisfy compiler */
    1171              :     (void)dev_path;
    1172              : 
    1173          103 :     if (config == NULL)
    1174              :         return -1;
    1175              : 
    1176          102 :     if (status == DLT_LOGSTORAGE_SYNC_ON_MSG) { /* sync on every message */
    1177           46 :         if (config->gzip_compression == DLT_LOGSTORAGE_GZIP_ON) {
    1178              : #ifdef DLT_LOGSTORAGE_USE_GZIP
    1179              :             if (gzflush(config->gzlog, Z_SYNC_FLUSH) != 0)
    1180              :                 dlt_vlog(LOG_ERR, "%s: failed to gzflush log file\n", __func__);
    1181              : #endif
    1182              :         } else {
    1183           46 :             if (fflush(config->log) != 0)
    1184            0 :                 dlt_vlog(LOG_ERR, "%s: failed to flush log file\n", __func__);
    1185              :         }
    1186              :     }
    1187              : 
    1188              :     return 0;
    1189              : }
    1190              : 
    1191              : /**
    1192              :  * dlt_logstorage_prepare_msg_cache
    1193              :  *
    1194              :  * Prepare the log file for a certain filer. If log file not open or log
    1195              :  * files max size reached, open a new file.
    1196              :  * Create a memory area to cache data.
    1197              :  *
    1198              :  * @param config        DltLogStorageFilterConfig
    1199              :  * @param file_config   User configurations for log file
    1200              :  * @param dev_path      Storage device path
    1201              :  * @param log_msg_size  Size of log message
    1202              :  * @param newest_file_info   Info of newest files for corresponding filename
    1203              :  * @return 0 on success, -1 on error
    1204              :  */
    1205          199 : int dlt_logstorage_prepare_msg_cache(
    1206              :     DltLogStorageFilterConfig* config, DltLogStorageUserConfig* file_config, char* dev_path, int log_msg_size,
    1207              :     DltNewestFileName* newest_file_info)
    1208              : {
    1209          199 :     if ((config == NULL) || (file_config == NULL) || (dev_path == NULL) || (newest_file_info == NULL))
    1210              :         return -1;
    1211              : 
    1212              :     /* check if newest file info is available
    1213              :      * + working file name is NULL => update directly to newest file
    1214              :      * + working file name is not NULL: check if
    1215              :      * ++ wrap_ids are different from each other or
    1216              :      * ++ newest file name <> working file name
    1217              :      */
    1218          198 :     if (newest_file_info->newest_file) {
    1219           60 :         if (config->working_file_name
    1220           59 :             && ((config->wrap_id != newest_file_info->wrap_id)
    1221           59 :                 || (strcmp(newest_file_info->newest_file, config->working_file_name) != 0))) {
    1222            0 :             free(config->working_file_name);
    1223            0 :             config->working_file_name = NULL;
    1224              :         }
    1225           60 :         if (config->working_file_name == NULL) {
    1226            1 :             config->working_file_name = strdup(newest_file_info->newest_file);
    1227            1 :             config->wrap_id = newest_file_info->wrap_id;
    1228              :         }
    1229              :     }
    1230              : 
    1231              :     /* Combinations allowed: on Daemon_Exit with on Demand,File_Size with Daemon_Exit
    1232              :      *  File_Size with on Demand, Specific_Size with Daemon_Exit,Specific_Size with on Demand
    1233              :      * Combination not allowed : File_Size with Specific_Size
    1234              :      */
    1235              :     /* check for combinations of specific_size and file_size strategy */
    1236          198 :     if ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0)
    1237           43 :         && ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE)) > 0)) {
    1238            0 :         dlt_log(LOG_WARNING, "wrong combination of sync strategies \n");
    1239            0 :         return -1;
    1240              :     }
    1241              : 
    1242              :     (void)log_msg_size; /* satisfy compiler */
    1243              : 
    1244              :     /* check specific size is smaller than file size */
    1245          198 :     if ((DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0)
    1246           43 :         && (config->specific_size > config->file_size)) {
    1247            0 :         dlt_log(
    1248              :             LOG_ERR,
    1249              :             "Cache size is larger than file size. "
    1250              :             "Cannot prepare log file for ON_SPECIFIC_SIZE sync\n");
    1251            0 :         return -1;
    1252              :     }
    1253              : 
    1254          198 :     if (config->cache == NULL) {
    1255              :         unsigned int cache_size = 0;
    1256              :         size_t total_size = 0;
    1257              : 
    1258              :         /* check for sync_specific_size strategy */
    1259           11 :         if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) {
    1260            2 :             cache_size = config->specific_size;
    1261              :         } else /* other cache strategies */
    1262              :         {
    1263            9 :             cache_size = config->file_size;
    1264              :         }
    1265              : 
    1266              :         /* validate cache_size to prevent integer overflow on 32-bit targets */
    1267           11 :         if (cache_size == 0) {
    1268            0 :             dlt_vlog(
    1269              :                 LOG_ERR, "%s: Invalid cache size 0. (ApId=[%s] CtId=[%s])\n", __func__, config->apids, config->ctids);
    1270            0 :             return -1;
    1271              :         }
    1272              : 
    1273              :         /* use size_t to avoid 32-bit overflow when adding footer size */
    1274           11 :         total_size = (size_t)cache_size + sizeof(DltLogStorageCacheFooter);
    1275              : 
    1276              :         /* check for overflow: if total_size wrapped or exceeds max, reject */
    1277              :         if (total_size < (size_t)cache_size) {
    1278              :             dlt_vlog(
    1279              :                 LOG_ERR, "%s: Cache size overflow detected. (ApId=[%s] CtId=[%s])\n", __func__, config->apids,
    1280              :                 config->ctids);
    1281              :             return -1;
    1282              :         }
    1283              : 
    1284              :         /* check total logstorage cache size */
    1285           11 :         if ((g_logstorage_cache_size + cache_size + sizeof(DltLogStorageCacheFooter)) > g_logstorage_cache_max) {
    1286            0 :             dlt_vlog(
    1287              :                 LOG_ERR, "%s: Max size of Logstorage Cache already used. (ApId=[%s] CtId=[%s]) \n", __func__,
    1288              :                 config->apids, config->ctids);
    1289            0 :             return -1;
    1290              :         } else {
    1291           11 :             dlt_vlog(
    1292              :                 LOG_DEBUG, "%s: Logstorage total: %d , requested cache size: %d, max: %d (ApId=[%s] CtId=[%s])\n",
    1293              :                 __func__, g_logstorage_cache_size, cache_size, g_logstorage_cache_max, config->apids, config->ctids);
    1294              :         }
    1295              : 
    1296              :         /* create cache */
    1297           11 :         config->cache = calloc(1, total_size);
    1298              : 
    1299           11 :         if (config->cache == NULL) {
    1300            0 :             dlt_log(LOG_CRIT, "Cannot allocate memory for filter ring buffer\n");
    1301              :         } else {
    1302              :             /* update current used cache size */
    1303           11 :             g_logstorage_cache_size += (unsigned int)(cache_size + sizeof(DltLogStorageCacheFooter));
    1304              :         }
    1305              :     }
    1306              : 
    1307              :     return 0;
    1308              : }
    1309              : 
    1310              : /**
    1311              :  * dlt_logstorage_write_msg_cache
    1312              :  *
    1313              :  * Write the log message.
    1314              :  *
    1315              :  * @param config        DltLogStorageFilterConfig
    1316              :  * @param file_config   User configurations for log file
    1317              :  * @param dev_path      Storage device path
    1318              :  * @param data1         header
    1319              :  * @param size1         header size
    1320              :  * @param data2         storage header
    1321              :  * @param size2         storage header size
    1322              :  * @param data3         payload
    1323              :  * @param size3         payload size
    1324              :  * @return 0 on success, -1 on error
    1325              :  */
    1326          199 : int dlt_logstorage_write_msg_cache(
    1327              :     DltLogStorageFilterConfig* config, DltLogStorageUserConfig* file_config, char* dev_path, unsigned char* data1,
    1328              :     int size1, unsigned char* data2, int size2, unsigned char* data3, int size3)
    1329              : {
    1330              :     DltLogStorageCacheFooter* footer = NULL;
    1331              :     int msg_size;
    1332              :     int remain_cache_size;
    1333              :     uint8_t* curr_write_addr = NULL;
    1334              :     int ret = 0;
    1335              :     unsigned int cache_size;
    1336              : 
    1337          199 :     if ((config == NULL) || (data1 == NULL) || (size1 < 0) || (data2 == NULL) || (size2 < 0) || (data3 == NULL)
    1338          198 :         || (size3 < 0) || (config->cache == NULL) || (file_config == NULL) || (dev_path == NULL)) {
    1339              :         return -1;
    1340              :     }
    1341              : 
    1342          198 :     if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) {
    1343           43 :         cache_size = config->specific_size;
    1344              :     } else {
    1345          155 :         cache_size = config->file_size;
    1346              :     }
    1347              : 
    1348              :     /* validate cache_size to prevent out-of-bounds access */
    1349          198 :     if (cache_size == 0) {
    1350              :         return -1;
    1351              :     }
    1352              : 
    1353          198 :     footer = (DltLogStorageCacheFooter*)((uint8_t*)config->cache + cache_size);
    1354          198 :     msg_size = size1 + size2 + size3;
    1355          198 :     remain_cache_size = (int)(cache_size - footer->offset);
    1356              : 
    1357          198 :     if (msg_size <= remain_cache_size) /* add at current position */
    1358              :     {
    1359          177 :         curr_write_addr = (uint8_t*)config->cache + footer->offset;
    1360          177 :         footer->offset += (unsigned int)msg_size;
    1361          177 :         if (footer->wrap_around_cnt < 1) {
    1362          143 :             footer->end_sync_offset = footer->offset;
    1363              :         }
    1364              : 
    1365              :         /* write data to cache */
    1366          177 :         memcpy(curr_write_addr, data1, (size_t)size1);
    1367          177 :         curr_write_addr += size1;
    1368          177 :         memcpy(curr_write_addr, data2, (size_t)size2);
    1369          177 :         curr_write_addr += size2;
    1370          177 :         memcpy(curr_write_addr, data3, (size_t)size3);
    1371              :     }
    1372              : 
    1373              :     /*
    1374              :      * In case the msg_size is equal to remaining cache size,
    1375              :      * the message is still written in cache.
    1376              :      * Then whole cache data is synchronized to file.
    1377              :      */
    1378          198 :     if (msg_size >= remain_cache_size) {
    1379              :         /*check for message size exceeds cache size for specific_size strategy */
    1380           21 :         if ((unsigned int)msg_size > cache_size) {
    1381            0 :             dlt_log(LOG_WARNING, "Message is larger than cache. Discard.\n");
    1382            0 :             return -1;
    1383              :         }
    1384              : 
    1385              :         /*sync to file for specific_size or file_size  */
    1386           21 :         if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) > 0) {
    1387            4 :             ret = config->dlt_logstorage_sync(config, file_config, dev_path, DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE);
    1388            4 :             if (ret != 0) {
    1389            0 :                 dlt_log(LOG_ERR, "dlt_logstorage_sync: Unable to sync.\n");
    1390            0 :                 return -1;
    1391              :             }
    1392           17 :         } else if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) {
    1393           13 :             ret = config->dlt_logstorage_sync(config, file_config, dev_path, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE);
    1394           13 :             if (ret != 0) {
    1395            0 :                 dlt_log(LOG_ERR, "dlt_logstorage_sync: Unable to sync.\n");
    1396            0 :                 return -1;
    1397              :             }
    1398            4 :         } else if (
    1399            4 :             (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_DEMAND) > 0)
    1400            3 :             || (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_DAEMON_EXIT) > 0)) {
    1401            4 :             footer->wrap_around_cnt += 1;
    1402              :         }
    1403              : 
    1404           21 :         if (msg_size > remain_cache_size) {
    1405              :             /* start writing from beginning */
    1406           21 :             footer->end_sync_offset = footer->offset;
    1407           21 :             curr_write_addr = config->cache;
    1408           21 :             footer->offset = (unsigned int)msg_size;
    1409              : 
    1410              :             /* write data to cache */
    1411           21 :             memcpy(curr_write_addr, data1, (size_t)size1);
    1412           21 :             curr_write_addr += size1;
    1413           21 :             memcpy(curr_write_addr, data2, (size_t)size2);
    1414           21 :             curr_write_addr += size2;
    1415           21 :             memcpy(curr_write_addr, data3, (size_t)size3);
    1416              :         }
    1417              :     }
    1418              : 
    1419              : 
    1420              :     return 0;
    1421              : }
    1422              : 
    1423              : /**
    1424              :  * dlt_logstorage_sync_msg_cache
    1425              :  *
    1426              :  * sync data to disk.
    1427              :  *
    1428              :  * @param config        DltLogStorageFilterConfig
    1429              :  * @param file_config   User configurations for log file
    1430              :  * @param dev_path      Storage device path
    1431              :  * @param status        Strategy flag
    1432              :  * @return 0 on success, -1 on error
    1433              :  */
    1434          234 : int dlt_logstorage_sync_msg_cache(
    1435              :     DltLogStorageFilterConfig* config, DltLogStorageUserConfig* file_config, char* dev_path, int status)
    1436              : {
    1437              :     unsigned int cache_size;
    1438              : 
    1439              :     DltLogStorageCacheFooter* footer = NULL;
    1440              : 
    1441          234 :     if ((config == NULL) || (file_config == NULL) || (dev_path == NULL)) {
    1442              :         return -1;
    1443              :     }
    1444              : 
    1445              :     /* sync only, if given strategy is set */
    1446          233 :     if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, status) > 0) {
    1447           24 :         if (config->cache == NULL) {
    1448            0 :             dlt_log(LOG_ERR, "Cannot copy cache to file. Cache is NULL\n");
    1449            0 :             return -1;
    1450              :         }
    1451              : 
    1452           24 :         if (DLT_OFFLINE_LOGSTORAGE_IS_STRATEGY_SET(config->sync, DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) > 0) {
    1453           13 :             cache_size = config->specific_size;
    1454              :         } else {
    1455           11 :             cache_size = config->file_size;
    1456              :         }
    1457              : 
    1458              :         /* validate cache_size to prevent out-of-bounds access */
    1459           24 :         if (cache_size == 0) {
    1460            0 :             dlt_log(LOG_ERR, "Cannot sync cache. Invalid cache size 0\n");
    1461            0 :             return -1;
    1462              :         }
    1463              : 
    1464           24 :         footer = (DltLogStorageCacheFooter*)((uint8_t*)config->cache + cache_size);
    1465              : 
    1466              :         /* sync cache data to file */
    1467           24 :         if (footer->wrap_around_cnt < 1) {
    1468              :             /* Sync whole cache */
    1469           21 :             dlt_logstorage_sync_to_file(
    1470              :                 config, file_config, dev_path, footer, footer->last_sync_offset, footer->offset);
    1471              : 
    1472            3 :         } else if ((footer->wrap_around_cnt == 1) && (footer->offset < footer->last_sync_offset)) {
    1473              :             /* sync (1) footer->last_sync_offset to footer->end_sync_offset,
    1474              :              * and (2) footer->last_sync_offset (= 0) to footer->offset */
    1475            0 :             dlt_logstorage_sync_to_file(
    1476              :                 config, file_config, dev_path, footer, footer->last_sync_offset, footer->end_sync_offset);
    1477            0 :             footer->last_sync_offset = 0;
    1478            0 :             dlt_logstorage_sync_to_file(
    1479              :                 config, file_config, dev_path, footer, footer->last_sync_offset, footer->offset);
    1480              :         } else {
    1481              :             /* sync (1) footer->offset + index to footer->end_sync_offset,
    1482              :              * and (2) footer->last_sync_offset (= 0) to footer->offset */
    1483            3 :             dlt_logstorage_sync_to_file(config, file_config, dev_path, footer, footer->offset, footer->end_sync_offset);
    1484            3 :             footer->last_sync_offset = 0;
    1485            3 :             dlt_logstorage_sync_to_file(
    1486              :                 config, file_config, dev_path, footer, footer->last_sync_offset, footer->offset);
    1487              :         }
    1488              : 
    1489              :         /* Initialize cache if needed */
    1490           24 :         if ((status == DLT_LOGSTORAGE_SYNC_ON_SPECIFIC_SIZE) || (status == DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE)) {
    1491              :             /* clean ring buffer and reset footer information */
    1492           17 :             memset(config->cache, 0, cache_size + sizeof(DltLogStorageCacheFooter));
    1493              :         }
    1494              : 
    1495           17 :         if (status == DLT_LOGSTORAGE_SYNC_ON_FILE_SIZE) {
    1496              :             /* Close log file */
    1497            0 :             dlt_logstorage_close_file(config);
    1498            4 :             config->current_write_file_offset = 0;
    1499              :         }
    1500              :     }
    1501              :     return 0;
    1502              : }
        

Generated by: LCOV version 2.0-1