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

Generated by: LCOV version 2.0-1