LCOV - code coverage report
Current view: top level - shared - dlt_common.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 62.5 % 1623 1014
Test Date: 2025-12-12 09:13:23 Functions: 85.3 % 95 81

            Line data    Source code
       1              : /*
       2              :  * SPDX license identifier: MPL-2.0
       3              :  *
       4              :  * Copyright (C) 2011-2015, BMW AG
       5              :  *
       6              :  * This file is part of COVESA Project DLT - Diagnostic Log and Trace.
       7              :  *
       8              :  * This Source Code Form is subject to the terms of the
       9              :  * Mozilla Public License (MPL), v. 2.0.
      10              :  * If a copy of the MPL was not distributed with this file,
      11              :  * You can obtain one at http://mozilla.org/MPL/2.0/.
      12              :  *
      13              :  * For further information see http://www.covesa.org/.
      14              :  */
      15              : 
      16              : /*!
      17              :  * \author
      18              :  * Alexander Wenzel <alexander.aw.wenzel@bmw.de>
      19              :  * Markus Klein <Markus.Klein@esk.fraunhofer.de>
      20              :  * Mikko Rapeli <mikko.rapeli@bmw.de>
      21              :  *
      22              :  * \copyright Copyright © 2011-2015 BMW AG. \n
      23              :  * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
      24              :  *
      25              :  * \file dlt_common.c
      26              :  */
      27              : 
      28              : #include <stdio.h>
      29              : #include <stdlib.h>   /* for malloc(), free() */
      30              : #include <string.h>   /* for strlen(), memcmp(), memmove() */
      31              : #include <time.h>     /* for localtime_r(), strftime() */
      32              : #include <limits.h>   /* for NAME_MAX */
      33              : #include <inttypes.h> /* for PRI formatting macro */
      34              : #include <stdarg.h>   /* va_list, va_start */
      35              : #include <err.h>
      36              : 
      37              : #include <errno.h>
      38              : #include <sys/stat.h> /* for mkdir() */
      39              : #include <sys/wait.h>
      40              : 
      41              : #include "dlt_user_shared.h"
      42              : #include "dlt_common.h"
      43              : #include "dlt_common_cfg.h"
      44              : #include "dlt_multiple_files.h"
      45              : 
      46              : #include "dlt_version.h"
      47              : 
      48              : #if defined (__WIN32__) || defined (_MSC_VER)
      49              : #   include <winsock2.h> /* for socket(), connect(), send(), and recv() */
      50              : #else
      51              : #   include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
      52              : #   include <syslog.h>
      53              : #   include <time.h> /* for clock_gettime() */
      54              : #   ifndef CLOCK_MONOTONIC
      55              : #      define CLOCK_MONOTONIC 1
      56              : #   endif
      57              : #endif
      58              : 
      59              : #if defined (_MSC_VER)
      60              : #   include <io.h>
      61              : #else
      62              : #   include <unistd.h>  /* for read(), close() */
      63              : #   include <fcntl.h>
      64              : #   include <sys/time.h> /* for gettimeofday() */
      65              : #endif
      66              : 
      67              : #if defined (__MSDOS__) || defined (_MSC_VER)
      68              : #   pragma warning(disable : 4996) /* Switch off C4996 warnings */
      69              : #   include <windows.h>
      70              : #   include <winbase.h>
      71              : #endif
      72              : 
      73              : const char dltSerialHeader[DLT_ID_SIZE] = { 'D', 'L', 'S', 1 };
      74              : char dltSerialHeaderChar[DLT_ID_SIZE] = { 'D', 'L', 'S', 1 };
      75              : 
      76              : #if defined DLT_DAEMON_USE_FIFO_IPC || defined DLT_LIB_USE_FIFO_IPC
      77              : char dltFifoBaseDir[DLT_PATH_MAX] = "/tmp";
      78              : #endif
      79              : 
      80              : #ifdef DLT_SHM_ENABLE
      81              : char dltShmName[NAME_MAX + 1] = "/dlt-shm";
      82              : #endif
      83              : 
      84              : static bool print_with_attributes = false;
      85              : 
      86              : char *message_type[] = { "log", "app_trace", "nw_trace", "control", "", "", "", "" };
      87              : char *log_info[] = { "", "fatal", "error", "warn", "info", "debug", "verbose", "", "", "", "", "", "", "", "", "" };
      88              : char *trace_type[] = { "", "variable", "func_in", "func_out", "state", "vfb", "", "", "", "", "", "", "", "", "", "" };
      89              : char *nw_trace_type[] = { "", "ipc", "can", "flexray", "most", "vfb", "", "", "", "", "", "", "", "", "", "" };
      90              : char *control_type[] = { "", "request", "response", "time", "", "", "", "", "", "", "", "", "", "", "", "" };
      91              : static char *service_id_name[] =
      92              : { "", "set_log_level", "set_trace_status", "get_log_info", "get_default_log_level", "store_config",
      93              :   "reset_to_factory_default",
      94              :   "set_com_interface_status", "set_com_interface_max_bandwidth", "set_verbose_mode",
      95              :   "set_message_filtering", "set_timing_packets",
      96              :   "get_local_time", "use_ecu_id", "use_session_id", "use_timestamp", "use_extended_header",
      97              :   "set_default_log_level", "set_default_trace_status",
      98              :   "get_software_version", "message_buffer_overflow" };
      99              : static char *return_type[] =
     100              : { "ok", "not_supported", "error", "perm_denied", "warning", "", "", "", "no_matching_context_id" };
     101              : 
     102              : /* internal function definitions */
     103              : int dlt_buffer_get(DltBuffer *buf, unsigned char *data, int max_size, int delete);
     104              : int dlt_buffer_reset(DltBuffer *buf);
     105              : int dlt_buffer_increase_size(DltBuffer *buf);
     106              : int dlt_buffer_minimize_size(DltBuffer *buf);
     107              : void dlt_buffer_write_block(DltBuffer *buf, int *write, const unsigned char *data, unsigned int size);
     108              : void dlt_buffer_read_block(DltBuffer *buf, int *read, unsigned char *data, unsigned int size);
     109              : 
     110              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     111              : static int32_t dlt_output_soft_limit_over_warning(
     112              :     DltTraceLoadSettings* tl_settings,
     113              :     DltLogInternal log_internal,
     114              :     void *log_params);
     115              : 
     116              : static int32_t dlt_output_hard_limit_warning(
     117              :     DltTraceLoadSettings* tl_settings,
     118              :     DltLogInternal log_internal,
     119              :     void *log_params);
     120              : 
     121              : static bool dlt_user_cleanup_window(DltTraceLoadStat *tl_stat);
     122              : 
     123              : static int32_t dlt_switch_slot_if_needed(
     124              :     DltTraceLoadSettings* tl_settings,
     125              :     DltLogInternal log_internal,
     126              :     void *log_internal_params,
     127              :     uint32_t timestamp);
     128              : 
     129              : static void dlt_record_trace_load(DltTraceLoadStat *const tl_stat, int32_t size);
     130              : static inline bool dlt_is_over_trace_load_soft_limit(DltTraceLoadSettings* tl_settings);
     131              : static inline bool dlt_is_over_trace_load_hard_limit(DltTraceLoadSettings* tl_settings, int size);
     132              : #endif
     133              : 
     134            0 : void dlt_print_hex(uint8_t *ptr, int size)
     135              : {
     136              :     int num;
     137              : 
     138            0 :     if (ptr == NULL)
     139              :         return;
     140              : 
     141            0 :     for (num = 0; num < size; num++) {
     142            0 :         if (num > 0)
     143            0 :             dlt_user_printf(" ");
     144              : 
     145            0 :         dlt_user_printf("%.2x", ((uint8_t *)ptr)[num]);
     146              :     }
     147              : }
     148              : 
     149         2743 : static DltReturnValue dlt_print_hex_string_delim(char *text, int textlength, uint8_t *ptr, int size, char delim)
     150              : {
     151              :     int num;
     152              : 
     153         2743 :     if ((ptr == NULL) || (text == NULL) || (textlength <= 0) || (size < 0) || (delim == '\0'))
     154              :         return DLT_RETURN_WRONG_PARAMETER;
     155              : 
     156              :     /* Length 3: AB_ , A is first digit of hex number, B is second digit of hex number, _ is space */
     157         2740 :     if (textlength < (size * 3)) {
     158            0 :         dlt_vlog(LOG_WARNING,
     159              :                  "String does not fit hex data (available=%d, required=%d) !\n",
     160              :                  textlength, size * 3);
     161            0 :         return DLT_RETURN_ERROR;
     162              :     }
     163              : 
     164        36599 :     for (num = 0; num < size; num++) {
     165        33859 :         if (num > 0) {
     166        31147 :             snprintf(text, 2, "%c", delim);
     167        31147 :             text++;
     168              :         }
     169              : 
     170        33859 :         snprintf(text, 3, "%.2x", ((uint8_t *)ptr)[num]);
     171        33859 :         text += 2; /* 2 chars */
     172              :     }
     173              : 
     174              :     return DLT_RETURN_OK;
     175              : }
     176              : 
     177         2734 : DltReturnValue dlt_print_hex_string(char *text, int textlength, uint8_t *ptr, int size)
     178              : {
     179         2734 :     return dlt_print_hex_string_delim(text, textlength, ptr, size, ' ');
     180              : }
     181              : 
     182         1066 : DltReturnValue dlt_print_mixed_string(char *text, int textlength, uint8_t *ptr, int size, int html)
     183              : {
     184              :     int required_size = 0;
     185              :     int lines, rest, i;
     186              : 
     187         1066 :     if ((ptr == NULL) || (text == NULL) || (textlength <= 0) || (size < 0))
     188              :         return DLT_RETURN_WRONG_PARAMETER;
     189              : 
     190              :     /* Check maximum required size and do a length check */
     191         1060 :     if (html == 0)
     192          530 :         required_size =
     193              :             (DLT_COMMON_HEX_LINELEN + (2 * DLT_COMMON_HEX_CHARS + (DLT_COMMON_HEX_CHARS - 1)) + DLT_COMMON_CHARLEN +
     194              :              DLT_COMMON_HEX_CHARS + DLT_COMMON_CHARLEN) *
     195          530 :             ((size / DLT_COMMON_HEX_CHARS) + 1);
     196              :     /* Example: (8 chars line number + (2*16 chars + 15 spaces) + space + 16 ascii chars + CR) *
     197              :      * ((size/16) lines + extra line for the rest) */
     198              :     else
     199          530 :         required_size =
     200              :             (DLT_COMMON_HEX_LINELEN + (2 * DLT_COMMON_HEX_CHARS + (DLT_COMMON_HEX_CHARS - 1)) + DLT_COMMON_CHARLEN +
     201              :              DLT_COMMON_HEX_CHARS + 4 * DLT_COMMON_CHARLEN) *
     202          530 :             ((size / DLT_COMMON_HEX_CHARS) + 1);
     203              : 
     204              :     /* Example: (8 chars line number + (2*16 chars + 15 spaces) + space + 16 ascii chars + 4 [HTML CR: <BR>]) *
     205              :      * ((size/16) lines + extra line for the rest) */
     206              : 
     207         1060 :     if (textlength < required_size) {
     208            0 :         dlt_vlog(LOG_WARNING,
     209              :                  "String does not fit mixed data (available=%d, required=%d) !\n",
     210              :                  textlength, required_size);
     211            0 :         return DLT_RETURN_ERROR;
     212              :     }
     213              : 
     214              :     /* print full lines */
     215         1740 :     for (lines = 0; lines < (size / DLT_COMMON_HEX_CHARS); lines++) {
     216              :         int ret = 0;
     217              :         /* Line number */
     218          680 :         ret = snprintf(text, DLT_COMMON_HEX_LINELEN + 1, "%.6x: ", (uint32_t)lines * DLT_COMMON_HEX_CHARS);
     219              : 
     220          680 :         if ((ret < 0) || (ret >= (DLT_COMMON_HEX_LINELEN + 1)))
     221            0 :             dlt_log(LOG_WARNING, "line was truncated\n");
     222              : 
     223          680 :         text += DLT_COMMON_HEX_LINELEN; /* 'XXXXXX: ' */
     224              : 
     225              :         /* Hex-Output */
     226              :         /* It is not required to decrement textlength, as it was already checked, that
     227              :          * there is enough space for the complete output */
     228          680 :         if (dlt_print_hex_string(text, textlength,
     229          680 :                 (uint8_t *)(ptr + (lines * DLT_COMMON_HEX_CHARS)),
     230              :                 DLT_COMMON_HEX_CHARS) < DLT_RETURN_OK)
     231              :             return DLT_RETURN_ERROR;
     232          680 :         text += ((2 * DLT_COMMON_HEX_CHARS) + (DLT_COMMON_HEX_CHARS - 1)); /* 32 characters + 15 spaces */
     233              : 
     234              :         snprintf(text, 2, " ");
     235          680 :         text += DLT_COMMON_CHARLEN;
     236              : 
     237              :         /* Char-Output */
     238              :         /* It is not required to decrement textlength, as it was already checked, that
     239              :          * there is enough space for the complete output */
     240          680 :         if (dlt_print_char_string(&text, textlength,
     241              :                 (uint8_t *)(ptr + (lines * DLT_COMMON_HEX_CHARS)),
     242              :                 DLT_COMMON_HEX_CHARS) < DLT_RETURN_OK)
     243              :             return DLT_RETURN_ERROR;
     244              : 
     245          680 :         if (html == 0) {
     246          340 :             snprintf(text, 2, "\n");
     247          340 :             text += DLT_COMMON_CHARLEN;
     248              :         }
     249              :         else {
     250          340 :             snprintf(text, 5, "<BR>");
     251          340 :             text += (4 * DLT_COMMON_CHARLEN);
     252              :         }
     253              :     }
     254              : 
     255              :     /* print partial line */
     256         1060 :     rest = size % DLT_COMMON_HEX_CHARS;
     257              : 
     258         1060 :     if (rest > 0) {
     259              :         /* Line number */
     260              :         int ret = 0;
     261          986 :         ret = snprintf(text, 9, "%.6x: ", (uint32_t)(size / DLT_COMMON_HEX_CHARS) * DLT_COMMON_HEX_CHARS);
     262              : 
     263          986 :         if ((ret < 0) || (ret >= 9))
     264            0 :             dlt_log(LOG_WARNING, "line number was truncated");
     265              : 
     266          986 :         text += DLT_COMMON_HEX_LINELEN; /* 'XXXXXX: ' */
     267              : 
     268              :         /* Hex-Output */
     269              :         /* It is not required to decrement textlength, as it was already checked, that
     270              :          * there is enough space for the complete output */
     271          986 :         if (dlt_print_hex_string(text,
     272              :                              textlength,
     273          986 :                              (uint8_t *)(ptr + ((size / DLT_COMMON_HEX_CHARS) * DLT_COMMON_HEX_CHARS)),
     274              :                              rest) < DLT_RETURN_OK)
     275              :             return DLT_RETURN_ERROR;
     276          986 :         text += 2 * rest + (rest - 1);
     277              : 
     278         9472 :         for (i = 0; i < (DLT_COMMON_HEX_CHARS - rest); i++) {
     279         8486 :             snprintf(text, 4, " xx");
     280         8486 :             text += (3 * DLT_COMMON_CHARLEN);
     281              :         }
     282              : 
     283          986 :         snprintf(text, 2, " ");
     284          986 :         text += DLT_COMMON_CHARLEN;
     285              : 
     286              :         /* Char-Output */
     287              :         /* It is not required to decrement textlength, as it was already checked, that
     288              :          * there is enough space for the complete output */
     289          986 :         if (dlt_print_char_string(&text, textlength,
     290              :                               (uint8_t *)(ptr + ((size / DLT_COMMON_HEX_CHARS) * DLT_COMMON_HEX_CHARS)),
     291              :                               rest) < DLT_RETURN_OK)
     292              :             return DLT_RETURN_ERROR;
     293              :     }
     294              : 
     295              :     return DLT_RETURN_OK;
     296              : }
     297              : 
     298         1671 : DltReturnValue dlt_print_char_string(char **text, int textlength, uint8_t *ptr, int size)
     299              : {
     300              :     int num;
     301              : 
     302         1671 :     if ((text == NULL) || (ptr == NULL) || (*text == NULL) || (textlength <= 0) || (size < 0))
     303              :         return DLT_RETURN_WRONG_PARAMETER;
     304              : 
     305         1668 :     if (textlength < size) {
     306            0 :         dlt_vlog(LOG_WARNING,
     307              :                  "String does not fit character data (available=%d, required=%d) !\n",
     308              :                  textlength, size);
     309            0 :         return DLT_RETURN_WRONG_PARAMETER;
     310              :     }
     311              : 
     312        19879 :     for (num = 0; num < size; num++) {
     313        18211 :         if ((((char *)ptr)[num] < DLT_COMMON_ASCII_CHAR_SPACE) || (((char *)ptr)[num] > DLT_COMMON_ASCII_CHAR_TILDE)) {
     314        10314 :             snprintf(*text, 2, ".");
     315              :         }
     316              :         else {
     317              :             /* replace < with . */
     318         7897 :             if (((char *)ptr)[num] != DLT_COMMON_ASCII_CHAR_LT)
     319         7895 :                 snprintf(*text, 2, "%c", ((char *)ptr)[num]);
     320              :             else
     321            2 :                 snprintf(*text, 2, ".");
     322              :         }
     323              : 
     324        18211 :         (*text)++;
     325              :     }
     326              : 
     327              :     return DLT_RETURN_OK;
     328              : }
     329              : 
     330         5622 : size_t dlt_strnlen_s(const char* str, size_t maxsize)
     331              : {
     332         5622 :     if (str == NULL)
     333              :         return 0;
     334              : 
     335        24796 :     for (size_t i = 0; i < maxsize; ++i) {
     336        22517 :         if (str[i] == '\0')
     337         3342 :             return i;
     338              :     }
     339              :     return maxsize;
     340              : }
     341              : 
     342         5620 : void dlt_print_id(char *text, const char *id)
     343              : {
     344              :     /* check nullpointer */
     345         5620 :     if ((text == NULL) || (id == NULL))
     346              :         return;
     347              : 
     348              :     /* Initialize text */
     349              :     memset(text, '-', DLT_ID_SIZE);
     350              : 
     351         5617 :     text[DLT_ID_SIZE] = 0;
     352              : 
     353         5617 :     size_t len = dlt_strnlen_s(id, DLT_ID_SIZE);
     354              : 
     355              :     memcpy(text, id, len);
     356              : }
     357              : 
     358        92232 : void dlt_set_id(char *id, const char *text)
     359              : {
     360              :     /* check nullpointer */
     361        92232 :     if ((id == NULL) || (text == NULL))
     362              :         return;
     363              : 
     364        92229 :     id[0] = 0;
     365        92229 :     id[1] = 0;
     366        92229 :     id[2] = 0;
     367        85690 :     id[3] = 0;
     368              : 
     369        92229 :     if (text[0] != 0)
     370        57241 :         id[0] = text[0];
     371              :     else
     372              :         return;
     373              : 
     374        57241 :     if (text[1] != 0)
     375        57235 :         id[1] = text[1];
     376              :     else
     377              :         return;
     378              : 
     379        57235 :     if (text[2] != 0)
     380        57227 :         id[2] = text[2];
     381              :     else
     382              :         return;
     383              : 
     384        57227 :     if (text[3] != 0)
     385        57050 :         id[3] = text[3];
     386              :     else
     387              :         return;
     388              : }
     389              : 
     390         1159 : void dlt_clean_string(char *text, int length)
     391              : {
     392              :     int num;
     393              : 
     394         1159 :     if (text == NULL)
     395              :         return;
     396              : 
     397        10286 :     for (num = 0; num < length; num++)
     398         9127 :         if ((text[num] == '\r') || (text[num] == '\n'))
     399            0 :             text[num] = ' ';
     400              : }
     401              : 
     402            7 : DltReturnValue dlt_filter_init(DltFilter *filter, int verbose)
     403              : {
     404            7 :     PRINT_FUNCTION_VERBOSE(verbose);
     405              : 
     406            7 :     if (filter == NULL)
     407              :         return DLT_RETURN_WRONG_PARAMETER;
     408              : 
     409            7 :     filter->counter = 0;
     410              : 
     411            7 :     return DLT_RETURN_OK;
     412              : }
     413              : 
     414            1 : DltReturnValue dlt_filter_free(DltFilter *filter, int verbose)
     415              : {
     416            1 :     PRINT_FUNCTION_VERBOSE(verbose);
     417              : 
     418            1 :     if (filter == NULL)
     419            0 :         return DLT_RETURN_WRONG_PARAMETER;
     420              : 
     421              :     return DLT_RETURN_OK;
     422              : }
     423              : 
     424            6 : DltReturnValue dlt_filter_load(DltFilter *filter, const char *filename, int verbose)
     425              : {
     426            6 :     if ((filter == NULL) || (filename == NULL))
     427              :         return DLT_RETURN_WRONG_PARAMETER;
     428              : 
     429              :     FILE *handle;
     430              :     char str1[DLT_COMMON_BUFFER_LENGTH + 1];
     431              :     char apid[DLT_ID_SIZE], ctid[DLT_ID_SIZE];
     432              : 
     433            6 :     PRINT_FUNCTION_VERBOSE(verbose);
     434              : 
     435            6 :     handle = fopen(filename, "r");
     436              : 
     437            6 :     if (handle == NULL) {
     438            0 :         dlt_vlog(LOG_WARNING, "Filter file %s cannot be opened!\n", filename);
     439            0 :         return DLT_RETURN_ERROR;
     440              :     }
     441              : 
     442              :     #define FORMAT_STRING_(x) "%" #x "s"
     443              :     #define FORMAT_STRING(x) FORMAT_STRING_(x)
     444              : 
     445              :     /* Reset filters */
     446            6 :     filter->counter = 0;
     447              : 
     448           18 :     while (!feof(handle)) {
     449           18 :         str1[0] = 0;
     450              : 
     451           18 :         if (fscanf(handle, FORMAT_STRING(DLT_COMMON_BUFFER_LENGTH), str1) != 1)
     452              :             break;
     453              : 
     454           12 :         if (str1[0] == 0)
     455              :             break;
     456              : 
     457              :         printf(" %s", str1);
     458              : 
     459           12 :         if (strcmp(str1, "----") == 0 || strcmp(str1, "*") == 0)
     460            0 :             dlt_set_id(apid, "");
     461              :         else
     462           12 :             dlt_set_id(apid, str1);
     463              : 
     464           12 :         str1[0] = 0;
     465              : 
     466           12 :         if (fscanf(handle, FORMAT_STRING(DLT_COMMON_BUFFER_LENGTH), str1) != 1)
     467              :             break;
     468              : 
     469           12 :         if (str1[0] == 0)
     470              :             break;
     471              : 
     472              :         printf(" %s\r\n", str1);
     473              : 
     474           12 :         if (strcmp(str1, "----") == 0)
     475            0 :             dlt_set_id(ctid, "");
     476              :         else
     477           12 :             dlt_set_id(ctid, str1);
     478              : 
     479           12 :         if (filter->counter < DLT_FILTER_MAX)
     480           12 :             dlt_filter_add(filter, apid, ctid, 0, 0, INT32_MAX, verbose);
     481              :         else
     482            0 :             dlt_vlog(LOG_WARNING,
     483              :                      "Maximum number (%d) of allowed filters reached, ignoring rest of filters!\n",
     484              :                      DLT_FILTER_MAX);
     485              :     }
     486              : 
     487            6 :     fclose(handle);
     488              : 
     489            6 :     return DLT_RETURN_OK;
     490              : }
     491              : 
     492            0 : DltReturnValue dlt_filter_save(DltFilter *filter, const char *filename, int verbose)
     493              : {
     494            0 :     if ((filter == NULL) || (filename == NULL))
     495              :         return DLT_RETURN_WRONG_PARAMETER;
     496              : 
     497              :     FILE *handle;
     498              :     int num;
     499              :     char buf[DLT_COMMON_BUFFER_LENGTH];
     500              : 
     501            0 :     PRINT_FUNCTION_VERBOSE(verbose);
     502              : 
     503            0 :     handle = fopen(filename, "w");
     504              : 
     505            0 :     if (handle == NULL) {
     506            0 :         dlt_vlog(LOG_WARNING, "Filter file %s cannot be opened!\n", filename);
     507            0 :         return DLT_RETURN_ERROR;
     508              :     }
     509              : 
     510            0 :     for (num = 0; num < filter->counter; num++) {
     511            0 :         if (filter->apid[num][0] == 0) {
     512              :             fprintf(handle, "---- ");
     513              :         }
     514              :         else {
     515            0 :             dlt_print_id(buf, filter->apid[num]);
     516              :             fprintf(handle, "%s ", buf);
     517              :         }
     518              : 
     519            0 :         if (filter->ctid[num][0] == 0) {
     520              :             fprintf(handle, "---- ");
     521              :         }
     522              :         else {
     523            0 :             dlt_print_id(buf, filter->ctid[num]);
     524              :             fprintf(handle, "%s ", buf);
     525              :         }
     526              :     }
     527              : 
     528            0 :     fclose(handle);
     529              : 
     530            0 :     return DLT_RETURN_OK;
     531              : }
     532              : 
     533           12 : int dlt_filter_find(DltFilter *filter, const char *apid, const char *ctid, const int log_level,
     534              :                     const int32_t payload_min, const int32_t payload_max, int verbose)
     535              : {
     536              :     int num;
     537              : 
     538           12 :     PRINT_FUNCTION_VERBOSE(verbose);
     539              : 
     540           12 :     if ((filter == NULL) || (apid == NULL))
     541              :         return -1;
     542              : 
     543           18 :     for (num = 0; num < filter->counter; num++)
     544            6 :         if (memcmp(filter->apid[num], apid, DLT_ID_SIZE) == 0) {
     545              :             /* apid matches, now check for ctid */
     546            0 :             if (ctid == NULL) {
     547              :                 /* check if empty ctid matches */
     548              :                 /*if (memcmp(filter->ctid[num],"",DLT_ID_SIZE)==0)//coverity complains here about Out-of-bounds access. */
     549            0 :                 char empty_ctid[DLT_ID_SIZE] = "";
     550              : 
     551            0 :                 if (memcmp(filter->ctid[num], empty_ctid, DLT_ID_SIZE) == 0)
     552            0 :                     if ((filter->log_level[num] == log_level) || (filter->log_level[num] == 0))
     553            0 :                         if (filter->payload_min[num] <= payload_min)
     554            0 :                             if (filter->payload_max[num] >= payload_max)
     555            0 :                                 return num;
     556              :             }
     557            0 :             else if (memcmp(filter->ctid[num], ctid, DLT_ID_SIZE) == 0)
     558              :             {
     559            0 :                 if ((filter->log_level[num] == log_level) || (filter->log_level[num] == 0))
     560            0 :                     if (filter->payload_min[num] <= payload_min)
     561            0 :                         if (filter->payload_max[num] >= payload_max)
     562            0 :                             return num;
     563              :             }
     564              :         }
     565              : 
     566              :     return -1; /* Not found */
     567              : }
     568              : 
     569           12 : DltReturnValue dlt_filter_add(DltFilter *filter, const char *apid, const char *ctid, const int log_level,
     570              :                               const int32_t payload_min, const int32_t payload_max, int verbose)
     571              : {
     572           12 :     PRINT_FUNCTION_VERBOSE(verbose);
     573              : 
     574           12 :     if ((filter == NULL) || (apid == NULL))
     575              :         return DLT_RETURN_WRONG_PARAMETER;
     576              : 
     577           12 :     if (filter->counter >= DLT_FILTER_MAX) {
     578            0 :         dlt_vlog(LOG_WARNING,
     579              :                  "Maximum number (%d) of allowed filters reached, ignoring filter!\n",
     580              :                  DLT_FILTER_MAX);
     581            0 :         return DLT_RETURN_ERROR;
     582              :     }
     583              : 
     584              :     /* add each filter (apid, ctid, log_level, payload_min, payload_max) only once to filter array */
     585           12 :     if (dlt_filter_find(filter, apid, ctid, log_level, payload_min, payload_max, verbose) < 0) {
     586              :         /* filter not found, so add it to filter array */
     587           12 :         dlt_set_id(filter->apid[filter->counter], apid);
     588           12 :         dlt_set_id(filter->ctid[filter->counter], (ctid ? ctid : ""));
     589           12 :         filter->log_level[filter->counter] = log_level;
     590           12 :         filter->payload_min[filter->counter] = payload_min;
     591           12 :         filter->payload_max[filter->counter] = payload_max;
     592              : 
     593           12 :         filter->counter++;
     594              : 
     595           12 :         return DLT_RETURN_OK;
     596              :     }
     597              : 
     598              :     return DLT_RETURN_ERROR;
     599              : }
     600              : 
     601            0 : DltReturnValue dlt_filter_delete(DltFilter *filter, const char *apid, const char *ctid, const int log_level,
     602              :                                  const int32_t payload_min, const int32_t payload_max, int verbose)
     603              : {
     604              :     int j, k;
     605              :     int found = 0;
     606              : 
     607            0 :     PRINT_FUNCTION_VERBOSE(verbose);
     608              : 
     609            0 :     if ((filter == NULL) || (apid == NULL) || (ctid == NULL))
     610              :         return DLT_RETURN_WRONG_PARAMETER;
     611              : 
     612            0 :     if (filter->counter > 0) {
     613              :         /* Get first occurence of apid and ctid in filter array */
     614            0 :         for (j = 0; j < filter->counter; j++)
     615            0 :             if ((memcmp(filter->apid[j], apid, DLT_ID_SIZE) == 0) &&
     616            0 :                 (memcmp(filter->ctid[j], ctid, DLT_ID_SIZE) == 0) &&
     617            0 :                 ((filter->log_level[j] == log_level) || (filter->log_level[j] == 0)) &&
     618            0 :                 (filter->payload_min[j] == payload_min) &&
     619            0 :                 (filter->payload_max[j] == payload_max)
     620              :                 ) {
     621              :                 found = 1;
     622              :                 break;
     623              :             }
     624              : 
     625            0 :         if (found) {
     626              :             /* j is index */
     627              :             /* Copy from j+1 til end to j til end-1 */
     628              : 
     629            0 :             dlt_set_id(filter->apid[j], "");
     630            0 :             dlt_set_id(filter->ctid[j], "");
     631            0 :             filter->log_level[j] = 0;
     632            0 :             filter->payload_min[j] = 0;
     633            0 :             filter->payload_max[j] = INT32_MAX;
     634              : 
     635            0 :             for (k = j; k < (filter->counter - 1); k++) {
     636            0 :                 dlt_set_id(filter->apid[k], filter->apid[k + 1]);
     637            0 :                 dlt_set_id(filter->ctid[k], filter->ctid[k + 1]);
     638            0 :                 filter->log_level[k] = filter->log_level[k + 1];
     639            0 :                 filter->payload_min[k] = filter->payload_min[k + 1];
     640            0 :                 filter->payload_max[k] = filter->payload_max[k + 1];
     641              :             }
     642              : 
     643            0 :             filter->counter--;
     644            0 :             return DLT_RETURN_OK;
     645              :         }
     646              :     }
     647              : 
     648              :     return DLT_RETURN_ERROR;
     649              : }
     650              : 
     651         6117 : DltReturnValue dlt_message_init(DltMessage *msg, int verbose)
     652              : {
     653         6117 :     PRINT_FUNCTION_VERBOSE(verbose);
     654              : 
     655         6117 :     if (msg == NULL)
     656              :         return DLT_RETURN_WRONG_PARAMETER;
     657              : 
     658              :     /* initalise structure parameters */
     659         6115 :     msg->headersize = 0;
     660         6115 :     msg->datasize = 0;
     661              : 
     662         6115 :     msg->databuffer = NULL;
     663         6115 :     msg->databuffersize = 0;
     664              : 
     665         6115 :     msg->storageheader = NULL;
     666         6115 :     msg->standardheader = NULL;
     667         6115 :     msg->extendedheader = NULL;
     668              : 
     669         6115 :     msg->found_serialheader = 0;
     670              : 
     671         6115 :     return DLT_RETURN_OK;
     672              : }
     673              : 
     674          115 : DltReturnValue dlt_message_free(DltMessage *msg, int verbose)
     675              : {
     676          115 :     PRINT_FUNCTION_VERBOSE(verbose);
     677              : 
     678          115 :     if (msg == NULL)
     679              :         return DLT_RETURN_WRONG_PARAMETER;
     680              : 
     681              :     /* delete databuffer if exists */
     682          113 :     if (msg->databuffer) {
     683           87 :         free(msg->databuffer);
     684           87 :         msg->databuffer = NULL;
     685           87 :         msg->databuffersize = 0;
     686              :     }
     687              : 
     688              :     return DLT_RETURN_OK;
     689              : }
     690              : 
     691         2420 : DltReturnValue dlt_message_header(DltMessage *msg, char *text, size_t textlength, int verbose)
     692              : {
     693         2420 :     return dlt_message_header_flags(msg, text, textlength, DLT_HEADER_SHOW_ALL, verbose);
     694              : }
     695              : 
     696         5122 : DltReturnValue dlt_message_header_flags(DltMessage *msg, char *text, size_t textlength, int flags, int verbose)
     697              : {
     698              :     struct tm timeinfo;
     699              :     char buffer [DLT_COMMON_BUFFER_LENGTH];
     700              : 
     701         5122 :     PRINT_FUNCTION_VERBOSE(verbose);
     702              : 
     703         5122 :     if ((msg == NULL) || (text == NULL) || (textlength <= 0))
     704              :         return DLT_RETURN_WRONG_PARAMETER;
     705              : 
     706         4926 :     if ((DLT_IS_HTYP_UEH(msg->standardheader->htyp)) && (msg->extendedheader == NULL))
     707              :         return DLT_RETURN_WRONG_PARAMETER;
     708              : 
     709         4926 :     if ((flags < DLT_HEADER_SHOW_NONE) || (flags > DLT_HEADER_SHOW_ALL))
     710              :         return DLT_RETURN_WRONG_PARAMETER;
     711              : 
     712         4926 :     text[0] = 0;
     713              : 
     714         4926 :     if ((flags & DLT_HEADER_SHOW_TIME) == DLT_HEADER_SHOW_TIME) {
     715              :         /* print received time */
     716         2826 :         time_t tt = msg->storageheader->seconds;
     717         2826 :         tzset();
     718         2826 :         localtime_r(&tt, &timeinfo);
     719         2826 :         strftime (buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", &timeinfo);
     720         2826 :         snprintf(text, textlength, "%s.%.6d ", buffer, msg->storageheader->microseconds);
     721              :     }
     722              : 
     723         4926 :     if ((flags & DLT_HEADER_SHOW_TMSTP) == DLT_HEADER_SHOW_TMSTP) {
     724              :         /* print timestamp if available */
     725         2826 :         if (DLT_IS_HTYP_WTMS(msg->standardheader->htyp))
     726          647 :             snprintf(text + strlen(text), textlength - strlen(text), "%10u ", msg->headerextra.tmsp);
     727              :         else
     728         2179 :             snprintf(text + strlen(text), textlength - strlen(text), "---------- ");
     729              :     }
     730              : 
     731         4926 :     if ((flags & DLT_HEADER_SHOW_MSGCNT) == DLT_HEADER_SHOW_MSGCNT)
     732              :         /* print message counter */
     733         2826 :         snprintf(text + strlen(text), textlength - strlen(text), "%.3d ", msg->standardheader->mcnt);
     734              : 
     735         4926 :     if ((flags & DLT_HEADER_SHOW_ECUID) == DLT_HEADER_SHOW_ECUID) {
     736              :         /* print ecu id, use header extra if available, else storage header value */
     737         2826 :         if (DLT_IS_HTYP_WEID(msg->standardheader->htyp))
     738          647 :             dlt_print_id(text + strlen(text), msg->headerextra.ecu);
     739              :         else
     740         2179 :             dlt_print_id(text + strlen(text), msg->storageheader->ecu);
     741              :     }
     742              : 
     743              :     /* print app id and context id if extended header available, else '----' */ #
     744              : 
     745         4926 :     if ((flags & DLT_HEADER_SHOW_APID) == DLT_HEADER_SHOW_APID) {
     746         2826 :         snprintf(text + strlen(text), textlength - strlen(text), " ");
     747              : 
     748         2826 :         if ((DLT_IS_HTYP_UEH(msg->standardheader->htyp)) && (msg->extendedheader->apid[0] != 0))
     749         1395 :             dlt_print_id(text + strlen(text), msg->extendedheader->apid);
     750              :         else
     751         1431 :             snprintf(text + strlen(text), textlength - strlen(text), "----");
     752              : 
     753         2826 :         snprintf(text + strlen(text), textlength - strlen(text), " ");
     754              :     }
     755              : 
     756         4926 :     if ((flags & DLT_HEADER_SHOW_CTID) == DLT_HEADER_SHOW_CTID) {
     757         2826 :         if ((DLT_IS_HTYP_UEH(msg->standardheader->htyp)) && (msg->extendedheader->ctid[0] != 0))
     758         1395 :             dlt_print_id(text + strlen(text), msg->extendedheader->ctid);
     759              :         else
     760         1431 :             snprintf(text + strlen(text), textlength - strlen(text), "----");
     761              : 
     762         2826 :         snprintf(text + strlen(text), textlength - strlen(text), " ");
     763              :     }
     764              : 
     765              :     /* print info about message type and length */
     766         4926 :     if (DLT_IS_HTYP_UEH(msg->standardheader->htyp)) {
     767         2435 :         if ((flags & DLT_HEADER_SHOW_MSGTYPE) == DLT_HEADER_SHOW_MSGTYPE) {
     768         1395 :             snprintf(text + strlen(text), textlength - strlen(text), "%s",
     769         1395 :                      message_type[DLT_GET_MSIN_MSTP(msg->extendedheader->msin)]);
     770         1395 :             snprintf(text + strlen(text), textlength - strlen(text), " ");
     771              :         }
     772              : 
     773         2435 :         if ((flags & DLT_HEADER_SHOW_MSGSUBTYPE) == DLT_HEADER_SHOW_MSGSUBTYPE) {
     774         1395 :             if ((DLT_GET_MSIN_MSTP(msg->extendedheader->msin)) == DLT_TYPE_LOG)
     775         1256 :                 snprintf(text + strlen(text), textlength - strlen(text), "%s",
     776         1256 :                          log_info[DLT_GET_MSIN_MTIN(msg->extendedheader->msin)]);
     777              : 
     778         1395 :             if ((DLT_GET_MSIN_MSTP(msg->extendedheader->msin)) == DLT_TYPE_APP_TRACE)
     779            0 :                 snprintf(text + strlen(text), textlength - strlen(text), "%s",
     780            0 :                          trace_type[DLT_GET_MSIN_MTIN(msg->extendedheader->msin)]);
     781              : 
     782         1395 :             if ((DLT_GET_MSIN_MSTP(msg->extendedheader->msin)) == DLT_TYPE_NW_TRACE)
     783            0 :                 snprintf(text + strlen(text), textlength - strlen(text), "%s",
     784            0 :                          nw_trace_type[DLT_GET_MSIN_MTIN(msg->extendedheader->msin)]);
     785              : 
     786         1395 :             if ((DLT_GET_MSIN_MSTP(msg->extendedheader->msin)) == DLT_TYPE_CONTROL)
     787          139 :                 snprintf(text + strlen(text), textlength - strlen(text), "%s",
     788          139 :                          control_type[DLT_GET_MSIN_MTIN(msg->extendedheader->msin)]);
     789              : 
     790         1395 :             snprintf(text + strlen(text), textlength - strlen(text), " ");
     791              :         }
     792              : 
     793         2435 :         if ((flags & DLT_HEADER_SHOW_VNVSTATUS) == DLT_HEADER_SHOW_VNVSTATUS) {
     794              :             /* print verbose status pf message */
     795         1395 :             if (DLT_IS_MSIN_VERB(msg->extendedheader->msin))
     796         1256 :                 snprintf(text + strlen(text), textlength - strlen(text), "V");
     797              :             else
     798          139 :                 snprintf(text + strlen(text), textlength - strlen(text), "N");
     799              : 
     800         1395 :             snprintf(text + strlen(text), textlength - strlen(text), " ");
     801              :         }
     802              : 
     803         2435 :         if ((flags & DLT_HEADER_SHOW_NOARG) == DLT_HEADER_SHOW_NOARG)
     804              :             /* print number of arguments */
     805         1395 :             snprintf(text + strlen(text), textlength - strlen(text), "%d", msg->extendedheader->noar);
     806              :     }
     807              :     else {
     808         2491 :         if ((flags & DLT_HEADER_SHOW_MSGTYPE) == DLT_HEADER_SHOW_MSGTYPE)
     809         1431 :             snprintf(text + strlen(text), textlength - strlen(text), "--- ");
     810              : 
     811         2491 :         if ((flags & DLT_HEADER_SHOW_MSGSUBTYPE) == DLT_HEADER_SHOW_MSGSUBTYPE)
     812         1431 :             snprintf(text + strlen(text), textlength - strlen(text), "--- ");
     813              : 
     814         2491 :         if ((flags & DLT_HEADER_SHOW_VNVSTATUS) == DLT_HEADER_SHOW_VNVSTATUS)
     815         1431 :             snprintf(text + strlen(text), textlength - strlen(text), "N ");
     816              : 
     817         2491 :         if ((flags & DLT_HEADER_SHOW_NOARG) == DLT_HEADER_SHOW_NOARG)
     818         1431 :             snprintf(text + strlen(text), textlength - strlen(text), "-");
     819              :     }
     820              : 
     821              :     return DLT_RETURN_OK;
     822              : }
     823              : 
     824         3131 : DltReturnValue dlt_message_payload(DltMessage *msg, char *text, size_t textlength, int type, int verbose)
     825              : {
     826              :     uint32_t id = 0, id_tmp = 0;
     827              :     uint8_t retval = 0;
     828              : 
     829              :     uint8_t *ptr;
     830              :     int32_t datalength;
     831              : 
     832              :     /* Pointer to ptr and datalength */
     833              :     uint8_t **pptr;
     834              :     int32_t *pdatalength;
     835              : 
     836              :     int ret = 0;
     837              : 
     838              :     int num;
     839              :     uint32_t type_info = 0, type_info_tmp = 0;
     840              :     int text_offset = 0;
     841              : 
     842         3131 :     PRINT_FUNCTION_VERBOSE(verbose);
     843              : 
     844         3131 :     if ((msg == NULL) || (msg->databuffer == NULL) || (text == NULL) ||
     845         3072 :         (type < DLT_OUTPUT_HEX) || (type > DLT_OUTPUT_ASCII_LIMITED))
     846              :         return DLT_RETURN_WRONG_PARAMETER;
     847              : 
     848         2941 :     if (textlength <= 0) {
     849           10 :         dlt_log(LOG_WARNING, "String does not fit binary data!\n");
     850           10 :         return DLT_RETURN_WRONG_PARAMETER;
     851              :     }
     852              : 
     853              :     /* start with empty string */
     854         2931 :     text[0] = 0;
     855              : 
     856              :     /* print payload only as hex */
     857         2931 :     if (type == DLT_OUTPUT_HEX)
     858          526 :         return dlt_print_hex_string(text, (int)textlength, msg->databuffer, (int)msg->datasize);
     859              : 
     860              :     /* print payload as mixed */
     861         2405 :     if (type == DLT_OUTPUT_MIXED_FOR_PLAIN)
     862          526 :         return dlt_print_mixed_string(text, (int)textlength, msg->databuffer, (int)msg->datasize, 0);
     863              : 
     864         1879 :     if (type == DLT_OUTPUT_MIXED_FOR_HTML)
     865          526 :         return dlt_print_mixed_string(text, (int)textlength, msg->databuffer, (int)msg->datasize, 1);
     866              : 
     867         1353 :     ptr = msg->databuffer;
     868         1353 :     datalength = (int32_t)msg->datasize;
     869              : 
     870              :     /* Pointer to ptr and datalength */
     871              :     pptr = &ptr;
     872              :     pdatalength = &datalength;
     873              : 
     874              :     /* non-verbose mode */
     875              : 
     876              :     /* print payload as hex */
     877         1353 :     if (DLT_MSG_IS_NONVERBOSE(msg)) {
     878              : 
     879          537 :         DLT_MSG_READ_VALUE(id_tmp, ptr, datalength, uint32_t);
     880          537 :         id = DLT_ENDIAN_GET_32(msg->standardheader->htyp, id_tmp);
     881              : 
     882          537 :         if ((datalength < 0) || (textlength < (((unsigned int)datalength * 3) + 20))) {
     883            0 :             dlt_vlog(LOG_WARNING,
     884              :                      "String does not fit binary data (available=%zu, required=%zu) !\n",
     885            0 :                      (size_t)textlength, ((size_t)datalength * 3U) + 20U);
     886            0 :             return DLT_RETURN_ERROR;
     887              :         }
     888              : 
     889              :         /* process message id / service id */
     890          537 :         if (DLT_MSG_IS_CONTROL(msg)) {
     891           60 :             if ((id > 0) && (id < DLT_SERVICE_ID_LAST_ENTRY))
     892           57 :                 snprintf(text + strlen(text), textlength - strlen(text), "%s",
     893              :                          service_id_name[id]); /* service id */
     894            3 :             else if (!(DLT_MSG_IS_CONTROL_TIME(msg)))
     895            3 :                 snprintf(text + strlen(text), textlength - strlen(text), "service(%u)", id); /* service id */
     896              : 
     897           60 :             if (datalength > 0)
     898           60 :                 snprintf(text + strlen(text), textlength - strlen(text), ", ");
     899              :         }
     900              :         else {
     901          477 :             snprintf(text + strlen(text), textlength - strlen(text), "%u, ", id); /* message id */
     902              :         }
     903              : 
     904              :         /* process return value */
     905          537 :         if (DLT_MSG_IS_CONTROL_RESPONSE(msg)) {
     906            4 :             if (datalength > 0) {
     907            4 :                 DLT_MSG_READ_VALUE(retval, ptr, datalength, uint8_t); /* No endian conversion necessary */
     908              : 
     909            4 :                 if ((retval < DLT_SERVICE_RESPONSE_LAST) || (retval == 8))
     910            3 :                     snprintf(text + strlen(text), textlength - strlen(text), "%s", return_type[retval]);
     911              :                 else
     912            1 :                     snprintf(text + strlen(text), textlength - strlen(text), "%.2x", retval);
     913              : 
     914            4 :                 if (datalength >= 1)
     915            2 :                     snprintf(text + strlen(text), textlength - strlen(text), ", ");
     916              :             }
     917              :         }
     918              : 
     919          537 :         if (type == DLT_OUTPUT_ASCII_LIMITED) {
     920          122 :             ret = dlt_print_hex_string(text + strlen(text),
     921          122 :                                        (int)((size_t)textlength - strlen(text)),
     922              :                                        ptr,
     923          122 :                                        (datalength > DLT_COMMON_ASCII_LIMIT_MAX_CHARS ? DLT_COMMON_ASCII_LIMIT_MAX_CHARS : datalength));
     924              : 
     925          122 :             if ((datalength > DLT_COMMON_ASCII_LIMIT_MAX_CHARS) &&
     926            6 :                 ((textlength - strlen(text)) > 4))
     927            6 :                 snprintf(text + strlen(text), textlength - strlen(text), " ...");
     928              :         }
     929              :         else {
     930          415 :             ret = dlt_print_hex_string(text + strlen(text), (int)((size_t)textlength - strlen(text)), ptr, datalength);
     931              :         }
     932              : 
     933          537 :         return ret;
     934              :     }
     935              : 
     936              :     /* At this point, it is ensured that a extended header is available */
     937              : 
     938              :     /* verbose mode */
     939              :     type_info = 0;
     940              :     type_info_tmp = 0;
     941              : 
     942         3361 :     for (num = 0; num < (int)(msg->extendedheader->noar); num++) {
     943         2545 :         if (num != 0) {
     944         1743 :             text_offset = (int)strlen(text);
     945         1743 :             snprintf(text + text_offset, textlength - (size_t)text_offset, " ");
     946              :         }
     947              : 
     948              :         /* first read the type info of the argument */
     949         2545 :         DLT_MSG_READ_VALUE(type_info_tmp, ptr, datalength, uint32_t);
     950         2545 :         type_info = DLT_ENDIAN_GET_32(msg->standardheader->htyp, type_info_tmp);
     951              : 
     952              :         /* print out argument */
     953         2545 :         text_offset = (int)strlen(text);
     954              : 
     955         2545 :         if (dlt_message_argument_print(msg, type_info, pptr, pdatalength,
     956         2545 :                                        (text + text_offset), (textlength - (size_t)text_offset), -1,
     957              :                                        0) == DLT_RETURN_ERROR)
     958              :             return DLT_RETURN_ERROR;
     959              :     }
     960              : 
     961              :     return DLT_RETURN_OK;
     962              : }
     963              : 
     964          742 : DltReturnValue dlt_message_filter_check(DltMessage *msg, DltFilter *filter, int verbose)
     965              : {
     966              :     /* check the filters if message is used */
     967              :     int num;
     968              :     DltReturnValue found = DLT_RETURN_OK;
     969              : 
     970          742 :     PRINT_FUNCTION_VERBOSE(verbose);
     971              : 
     972          742 :     if ((msg == NULL) || (filter == NULL))
     973              :         return DLT_RETURN_WRONG_PARAMETER;
     974              : 
     975          736 :     if ((filter->counter == 0) || (!(DLT_IS_HTYP_UEH(msg->standardheader->htyp))))
     976              :         /* no filter is set, or no extended header is available, so do as filter is matching */
     977              :         return DLT_RETURN_TRUE;
     978              : 
     979          936 :     for (num = 0; num < filter->counter; num++)
     980              :         /* check each filter if it matches */
     981          624 :         if ((DLT_IS_HTYP_UEH(msg->standardheader->htyp)) &&
     982          624 :             ((filter->apid[num][0] == 0) || (memcmp(filter->apid[num], msg->extendedheader->apid, DLT_ID_SIZE) == 0)) &&
     983            0 :             ((filter->ctid[num][0] == 0) || (memcmp(filter->ctid[num], msg->extendedheader->ctid, DLT_ID_SIZE) == 0)) &&
     984            0 :             ((filter->log_level[num] == 0) ||
     985            0 :              (filter->log_level[num] == DLT_GET_MSIN_MTIN(msg->extendedheader->msin))) &&
     986            0 :             ((filter->payload_min[num] == 0) || (filter->payload_min[num] <= msg->datasize)) &&
     987            0 :             ((filter->payload_max[num] == 0) || (filter->payload_max[num] >= msg->datasize))) {
     988              :             found = DLT_RETURN_TRUE;
     989              :             break;
     990              :         }
     991              : 
     992              :     return found;
     993              : }
     994              : 
     995         6686 : int dlt_message_read(DltMessage *msg, uint8_t *buffer, unsigned int length, int resync, int verbose)
     996              : {
     997              :     uint32_t extra_size = 0;
     998              : 
     999         6686 :     PRINT_FUNCTION_VERBOSE(verbose);
    1000              : 
    1001         6686 :     if ((msg == NULL) || (buffer == NULL) || (length <= 0))
    1002              :         return DLT_MESSAGE_ERROR_UNKNOWN;
    1003              : 
    1004              :     /* initialize resync_offset */
    1005         6250 :     msg->resync_offset = 0;
    1006              : 
    1007              :     /* check if message contains serial header, smaller than standard header */
    1008         6250 :     if (length < sizeof(dltSerialHeader))
    1009              :         /* dlt_log(LOG_ERR, "Length smaller than serial header!\n"); */
    1010              :         return DLT_MESSAGE_ERROR_SIZE;
    1011              : 
    1012         6250 :     if (memcmp(buffer, dltSerialHeader, sizeof(dltSerialHeader)) == 0) {
    1013              :         /* serial header found */
    1014            0 :         msg->found_serialheader = 1;
    1015            0 :         buffer += sizeof(dltSerialHeader);
    1016            0 :         length -= (unsigned int)sizeof(dltSerialHeader);
    1017              :     }
    1018              :     else {
    1019              :         /* serial header not found */
    1020         6250 :         msg->found_serialheader = 0;
    1021              : 
    1022         6250 :         if (resync) {
    1023              :             /* resync if necessary */
    1024              :             msg->resync_offset = 0;
    1025              : 
    1026              :             do {
    1027            0 :                 if (memcmp(buffer + msg->resync_offset, dltSerialHeader, sizeof(dltSerialHeader)) == 0) {
    1028              :                     /* serial header found */
    1029            0 :                     msg->found_serialheader = 1;
    1030            0 :                     buffer += sizeof(dltSerialHeader);
    1031            0 :                     length -= (unsigned int)sizeof(dltSerialHeader);
    1032            0 :                     break;
    1033              :                 }
    1034              : 
    1035            0 :                 msg->resync_offset++;
    1036            0 :             } while ((sizeof(dltSerialHeader) + (size_t)msg->resync_offset) <= length);
    1037              : 
    1038              :             /* Set new start offset */
    1039            0 :             if (msg->resync_offset > 0) {
    1040              :                 /* Resyncing connection */
    1041            0 :                 buffer += msg->resync_offset;
    1042            0 :                 length -= (unsigned int)msg->resync_offset;
    1043              :             }
    1044              :         }
    1045              :     }
    1046              : 
    1047              :     /* check that standard header fits buffer */
    1048         6250 :     if (length < sizeof(DltStandardHeader))
    1049              :         /* dlt_log(LOG_ERR, "Length smaller than standard header!\n"); */
    1050              :         return DLT_MESSAGE_ERROR_SIZE;
    1051              : 
    1052         6250 :     memcpy(msg->headerbuffer + sizeof(DltStorageHeader), buffer, sizeof(DltStandardHeader));
    1053              : 
    1054              :     /* set ptrs to structures */
    1055         6250 :     msg->storageheader = (DltStorageHeader *)msg->headerbuffer;
    1056         6250 :     msg->standardheader = (DltStandardHeader *)(msg->headerbuffer + sizeof(DltStorageHeader));
    1057              : 
    1058              :     /* calculate complete size of headers */
    1059         6250 :     extra_size = (uint32_t) (DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp) +
    1060              :         (DLT_IS_HTYP_UEH(msg->standardheader->htyp) ? sizeof(DltExtendedHeader) : 0));
    1061         6250 :     msg->headersize = (int32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + extra_size);
    1062         6250 :     msg->datasize = (int32_t) ((uint32_t)DLT_BETOH_16(msg->standardheader->len) - (uint32_t)msg->headersize + (uint32_t) sizeof(DltStorageHeader));
    1063              : 
    1064              :     /* calculate complete size of payload */
    1065              :     int32_t temp_datasize;
    1066         6250 :     temp_datasize = DLT_BETOH_16(msg->standardheader->len) - (int32_t) msg->headersize + (int32_t) sizeof(DltStorageHeader);
    1067              : 
    1068              :     /* check data size */
    1069         6250 :     if (temp_datasize < 0) {
    1070            0 :         dlt_vlog(LOG_WARNING,
    1071              :                  "Plausibility check failed. Complete message size too short (%d)!\n",
    1072              :                  temp_datasize);
    1073            0 :         return DLT_MESSAGE_ERROR_CONTENT;
    1074              :     }
    1075              :     else {
    1076         6250 :         msg->datasize = (int32_t) temp_datasize;
    1077              :     }
    1078              : 
    1079              :     /* check if verbose mode is on*/
    1080         6250 :     if (verbose) {
    1081            0 :         dlt_vlog(LOG_DEBUG, "BufferLength=%u, HeaderSize=%u, DataSize=%u\n",
    1082              :                  length, msg->headersize, msg->datasize);
    1083              :     }
    1084              : 
    1085              :     /* load standard header extra parameters and Extended header if used */
    1086         6250 :     if (extra_size > 0) {
    1087         6250 :         if (length < (size_t)((int32_t)msg->headersize - (int32_t)sizeof(DltStorageHeader)))
    1088              :             return DLT_MESSAGE_ERROR_SIZE;
    1089              : 
    1090         6250 :         memcpy(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader),
    1091         6250 :                buffer + sizeof(DltStandardHeader), (size_t)extra_size);
    1092              : 
    1093              :         /* set extended header ptr and get standard header extra parameters */
    1094         6250 :         if (DLT_IS_HTYP_UEH(msg->standardheader->htyp))
    1095         6250 :             msg->extendedheader =
    1096         6250 :                 (DltExtendedHeader *)(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) +
    1097         6250 :                                       DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp));
    1098              :         else
    1099            0 :             msg->extendedheader = NULL;
    1100              : 
    1101         6250 :         dlt_message_get_extraparameters(msg, verbose);
    1102              :     }
    1103              : 
    1104              :     /* check if payload fits length */
    1105         6250 :     if (length < (size_t)((int32_t)msg->headersize - (int32_t)sizeof(DltStorageHeader) + msg->datasize))
    1106              :         /* dlt_log(LOG_ERR,"length does not fit!\n"); */
    1107              :         return DLT_MESSAGE_ERROR_SIZE;
    1108              : 
    1109              :     /* free last used memory for buffer */
    1110         6040 :     if (msg->databuffer) {
    1111         6023 :         if (msg->datasize > msg->databuffersize) {
    1112            9 :             free(msg->databuffer);
    1113            9 :             msg->databuffer = (uint8_t *)malloc((size_t)msg->datasize);
    1114            9 :             msg->databuffersize = msg->datasize;
    1115              :         }
    1116              :     }
    1117              :     else {
    1118              :         /* get new memory for buffer */
    1119           17 :         msg->databuffer = (uint8_t *)malloc((size_t)msg->datasize);
    1120           17 :         msg->databuffersize = msg->datasize;
    1121              :     }
    1122              : 
    1123         6040 :     if (msg->databuffer == NULL) {
    1124            0 :         dlt_vlog(LOG_WARNING,
    1125              :                  "Cannot allocate memory for payload buffer of size %u!\n",
    1126              :                  msg->datasize);
    1127            0 :         return DLT_MESSAGE_ERROR_UNKNOWN;
    1128              :     }
    1129              : 
    1130              :     /* load payload data from buffer */
    1131         6040 :     memcpy(msg->databuffer, buffer + (size_t)((int32_t)msg->headersize - (int32_t)sizeof(DltStorageHeader)), (size_t)msg->datasize);
    1132              : 
    1133         6040 :     return DLT_MESSAGE_ERROR_OK;
    1134              : }
    1135              : 
    1136         7227 : DltReturnValue dlt_message_get_extraparameters(DltMessage *msg, int verbose)
    1137              : {
    1138         7227 :     PRINT_FUNCTION_VERBOSE(verbose);
    1139              : 
    1140         7227 :     if (msg == NULL)
    1141              :         return DLT_RETURN_WRONG_PARAMETER;
    1142              : 
    1143         7225 :     if (DLT_IS_HTYP_WEID(msg->standardheader->htyp))
    1144         7031 :         memcpy(msg->headerextra.ecu,
    1145              :                msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader),
    1146              :                DLT_ID_SIZE);
    1147              : 
    1148         7225 :     if (DLT_IS_HTYP_WSID(msg->standardheader->htyp)) {
    1149         6733 :         memcpy(&(msg->headerextra.seid), msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader)
    1150         6733 :                + (DLT_IS_HTYP_WEID(msg->standardheader->htyp) ? DLT_SIZE_WEID : 0), DLT_SIZE_WSID);
    1151         6733 :         msg->headerextra.seid = DLT_BETOH_32(msg->headerextra.seid);
    1152              :     }
    1153              : 
    1154         7225 :     if (DLT_IS_HTYP_WTMS(msg->standardheader->htyp)) {
    1155        14062 :         memcpy(&(msg->headerextra.tmsp), msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader)
    1156         7031 :                + (DLT_IS_HTYP_WEID(msg->standardheader->htyp) ? DLT_SIZE_WEID : 0)
    1157         7031 :                + (DLT_IS_HTYP_WSID(msg->standardheader->htyp) ? DLT_SIZE_WSID : 0), DLT_SIZE_WTMS);
    1158         7031 :         msg->headerextra.tmsp = DLT_BETOH_32(msg->headerextra.tmsp);
    1159              :     }
    1160              : 
    1161              :     return DLT_RETURN_OK;
    1162              : }
    1163              : 
    1164         6247 : DltReturnValue dlt_message_set_extraparameters(DltMessage *msg, int verbose)
    1165              : {
    1166         6247 :     PRINT_FUNCTION_VERBOSE(verbose);
    1167              : 
    1168         6247 :     if (msg == NULL)
    1169              :         return DLT_RETURN_WRONG_PARAMETER;
    1170              : 
    1171         6245 :     if (DLT_IS_HTYP_WEID(msg->standardheader->htyp))
    1172         6049 :         memcpy(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader),
    1173         6049 :                msg->headerextra.ecu,
    1174              :                DLT_ID_SIZE);
    1175              : 
    1176         6245 :     if (DLT_IS_HTYP_WSID(msg->standardheader->htyp)) {
    1177         5999 :         msg->headerextra.seid = DLT_HTOBE_32(msg->headerextra.seid);
    1178         5999 :         memcpy(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader)
    1179         5999 :                + (DLT_IS_HTYP_WEID(msg->standardheader->htyp) ? DLT_SIZE_WEID : 0),
    1180         5999 :                &(msg->headerextra.seid),
    1181              :                DLT_SIZE_WSID);
    1182              :     }
    1183              : 
    1184         6245 :     if (DLT_IS_HTYP_WTMS(msg->standardheader->htyp)) {
    1185         6049 :         msg->headerextra.tmsp = DLT_HTOBE_32(msg->headerextra.tmsp);
    1186        12098 :         memcpy(msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader)
    1187         6049 :                + (DLT_IS_HTYP_WEID(msg->standardheader->htyp) ? DLT_SIZE_WEID : 0)
    1188         6049 :                + (DLT_IS_HTYP_WSID(msg->standardheader->htyp) ? DLT_SIZE_WSID : 0),
    1189         6049 :                &(msg->headerextra.tmsp),
    1190              :                DLT_SIZE_WTMS);
    1191              :     }
    1192              : 
    1193              :     return DLT_RETURN_OK;
    1194              : }
    1195              : 
    1196           54 : DltReturnValue dlt_file_init(DltFile *file, int verbose)
    1197              : {
    1198           54 :     PRINT_FUNCTION_VERBOSE(verbose);
    1199              : 
    1200           54 :     if (file == NULL)
    1201              :         return DLT_RETURN_WRONG_PARAMETER;
    1202              : 
    1203              :     /* initalise structure parameters */
    1204           54 :     file->handle = NULL;
    1205           54 :     file->counter = 0;
    1206           54 :     file->counter_total = 0;
    1207           54 :     file->index = NULL;
    1208              : 
    1209           54 :     file->filter = NULL;
    1210           54 :     file->filter_counter = 0;
    1211           54 :     file->file_position = 0;
    1212              : 
    1213           54 :     file->position = 0;
    1214              : 
    1215           54 :     file->error_messages = 0;
    1216              : 
    1217           54 :     return dlt_message_init(&(file->msg), verbose);
    1218              : }
    1219              : 
    1220            6 : DltReturnValue dlt_file_set_filter(DltFile *file, DltFilter *filter, int verbose)
    1221              : {
    1222            6 :     PRINT_FUNCTION_VERBOSE(verbose);
    1223              : 
    1224            6 :     if (file == NULL)
    1225              :         return DLT_RETURN_WRONG_PARAMETER;
    1226              : 
    1227              :     /* set filter */
    1228            6 :     file->filter = filter;
    1229              : 
    1230            6 :     return DLT_RETURN_OK;
    1231              : }
    1232              : 
    1233         6627 : DltReturnValue dlt_file_read_header(DltFile *file, int verbose)
    1234              : {
    1235         6627 :     PRINT_FUNCTION_VERBOSE(verbose);
    1236              : 
    1237         6627 :     if (file == NULL)
    1238              :         return DLT_RETURN_WRONG_PARAMETER;
    1239              : 
    1240              :     /* Loop until storage header is found */
    1241              :     while (1) {
    1242              :         /* load header from file */
    1243        13254 :         if (fread(file->msg.headerbuffer,
    1244              :                   sizeof(DltStorageHeader) + sizeof(DltStandardHeader), 1,
    1245              :                   file->handle) != 1) {
    1246           38 :             if (!feof(file->handle))
    1247            0 :                 dlt_log(LOG_WARNING, "Cannot read header from file!\n");
    1248              :             else
    1249           38 :                 dlt_log(LOG_DEBUG, "Reached end of file\n");
    1250              : 
    1251           38 :             return DLT_RETURN_ERROR;
    1252              :         }
    1253              : 
    1254              :         /* set ptrs to structures */
    1255         6589 :         file->msg.storageheader = (DltStorageHeader *)file->msg.headerbuffer;
    1256         6589 :         file->msg.standardheader = (DltStandardHeader *)(file->msg.headerbuffer +
    1257              :                                                          sizeof(DltStorageHeader));
    1258              : 
    1259              :         /* check id of storage header */
    1260         6589 :         if (dlt_check_storageheader(file->msg.storageheader) != DLT_RETURN_TRUE) {
    1261              :             /* Shift the position back to the place where it stared to read + 1 */
    1262            0 :             if (fseek(file->handle,
    1263              :                       (long) (1 - (sizeof(DltStorageHeader) + sizeof(DltStandardHeader))),
    1264              :                       SEEK_CUR) < 0) {
    1265            0 :                 dlt_log(LOG_WARNING, "DLT storage header pattern not found!\n");
    1266            0 :                 return DLT_RETURN_ERROR;
    1267              :             }
    1268              :         }
    1269              :         else {
    1270              :             /* storage header is found */
    1271              :             break;
    1272              :         }
    1273              :     }
    1274              : 
    1275              :     /* calculate complete size of headers */
    1276         6589 :     file->msg.headersize = (int32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) +
    1277         6589 :     DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp) +
    1278              :     (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp) ? (uint32_t)sizeof(DltExtendedHeader) : 0U));
    1279              : 
    1280              :     /* calculate complete size of payload */
    1281              :     int32_t temp_datasize;
    1282         6589 :     temp_datasize = DLT_BETOH_16(file->msg.standardheader->len) + (int32_t) sizeof(DltStorageHeader) - (int32_t) file->msg.headersize;
    1283              : 
    1284              :     /* check data size */
    1285         6589 :     if (temp_datasize < 0) {
    1286            0 :         dlt_vlog(LOG_WARNING,
    1287              :                  "Plausibility check failed. Complete message size too short! (%d)\n",
    1288              :                  temp_datasize);
    1289            0 :         return DLT_RETURN_ERROR;
    1290              :     } else {
    1291         6589 :         file->msg.datasize = temp_datasize;
    1292              :     }
    1293              : 
    1294              :     /* check if verbose mode is on */
    1295         6589 :     if (verbose) {
    1296            0 :         dlt_vlog(LOG_DEBUG, "HeaderSize=%u, DataSize=%u\n",
    1297              :                  file->msg.headersize, file->msg.datasize);
    1298              :     }
    1299              : 
    1300              :     return DLT_RETURN_OK;
    1301              : }
    1302              : 
    1303            0 : DltReturnValue dlt_file_read_header_raw(DltFile *file, int resync, int verbose)
    1304              : {
    1305              :     char dltSerialHeaderBuffer[DLT_ID_SIZE];
    1306              : 
    1307            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1308              : 
    1309            0 :     if (file == NULL)
    1310              :         return DLT_RETURN_WRONG_PARAMETER;
    1311              : 
    1312              :     /* check if serial header exists, ignore if found */
    1313            0 :     if (fread(dltSerialHeaderBuffer, sizeof(dltSerialHeaderBuffer), 1, file->handle) != 1) {
    1314              :         /* cannot read serial header, not enough data available in file */
    1315            0 :         if (!feof(file->handle))
    1316            0 :             dlt_log(LOG_WARNING, "Cannot read header from file!\n");
    1317              : 
    1318            0 :         return DLT_RETURN_ERROR;
    1319              :     }
    1320              : 
    1321            0 :     if (memcmp(dltSerialHeaderBuffer, dltSerialHeader, sizeof(dltSerialHeader)) == 0) {
    1322              :         /* serial header found */
    1323              :         /* nothing to do continue reading */
    1324              : 
    1325              :     }
    1326              :     else {
    1327              :         /* serial header not found */
    1328            0 :         if (resync) {
    1329              :             /* increase error counter */
    1330            0 :             file->error_messages++;
    1331              : 
    1332              :             /* resync to serial header */
    1333              :             do {
    1334              :                 memmove(dltSerialHeaderBuffer, dltSerialHeaderBuffer + 1, sizeof(dltSerialHeader) - 1);
    1335              : 
    1336            0 :                 if (fread(dltSerialHeaderBuffer + 3, 1, 1, file->handle) != 1)
    1337              :                     /* cannot read any data, perhaps end of file reached */
    1338              :                     return DLT_RETURN_ERROR;
    1339              : 
    1340            0 :                 if (memcmp(dltSerialHeaderBuffer, dltSerialHeader, sizeof(dltSerialHeader)) == 0)
    1341              :                     /* serial header synchronised */
    1342              :                     break;
    1343              :             } while (1);
    1344              :         }
    1345              :         else
    1346              :         /* go back to last file position */
    1347            0 :         if (0 != fseek(file->handle, (long)file->file_position, SEEK_SET))
    1348              :         {
    1349              :             return DLT_RETURN_ERROR;
    1350              :         }
    1351              :     }
    1352              : 
    1353              :     /* load header from file */
    1354            0 :     if (fread(file->msg.headerbuffer + sizeof(DltStorageHeader), sizeof(DltStandardHeader), 1, file->handle) != 1) {
    1355            0 :         if (!feof(file->handle))
    1356            0 :             dlt_log(LOG_WARNING, "Cannot read header from file!\n");
    1357              : 
    1358            0 :         return DLT_RETURN_ERROR;
    1359              :     }
    1360              : 
    1361              :     /* set ptrs to structures */
    1362            0 :     file->msg.storageheader = (DltStorageHeader *)file->msg.headerbuffer; /* this points now to a empty storage header (filled with '0') */
    1363            0 :     file->msg.standardheader = (DltStandardHeader *)(file->msg.headerbuffer + sizeof(DltStorageHeader));
    1364              : 
    1365              :     /* Skip storage header field, fill this field with '0' */
    1366              :     memset(file->msg.storageheader, 0, sizeof(DltStorageHeader));
    1367              : 
    1368              :     /* Set storage header */
    1369            0 :     dlt_set_storageheader(file->msg.storageheader, DLT_COMMON_DUMMY_ECUID);
    1370              : 
    1371              :     /* no check for storage header id*/
    1372              : 
    1373              :     /* calculate complete size of headers */
    1374            0 :     file->msg.headersize = (int32_t) (sizeof(DltStorageHeader) + sizeof(DltStandardHeader) +
    1375            0 :         DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp) +
    1376              :         (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp) ? (uint32_t)sizeof(DltExtendedHeader) : 0U));
    1377              : 
    1378              :     /* calculate complete size of payload */
    1379              :     int32_t temp_datasize;
    1380            0 :     temp_datasize = DLT_BETOH_16(file->msg.standardheader->len) + (int32_t) sizeof(DltStorageHeader) - (int32_t) file->msg.headersize;
    1381              : 
    1382              :     /* check data size */
    1383            0 :     if (temp_datasize < 0) {
    1384            0 :         dlt_vlog(LOG_WARNING,
    1385              :                  "Plausibility check failed. Complete message size too short! (%d)\n",
    1386              :                  temp_datasize);
    1387            0 :         return DLT_RETURN_ERROR;
    1388              :     }
    1389              :     else {
    1390            0 :         file->msg.datasize = temp_datasize;
    1391              :     }
    1392              : 
    1393              :     /* check if verbose mode is on */
    1394            0 :     if (verbose) {
    1395            0 :         dlt_vlog(LOG_DEBUG, "HeaderSize=%u, DataSize=%u\n",
    1396              :                  file->msg.headersize, file->msg.datasize);
    1397              :     }
    1398              : 
    1399              :     return DLT_RETURN_OK;
    1400              : }
    1401              : 
    1402         4505 : DltReturnValue dlt_file_read_header_extended(DltFile *file, int verbose)
    1403              : {
    1404         4505 :     PRINT_FUNCTION_VERBOSE(verbose);
    1405              : 
    1406         4505 :     if (file == NULL)
    1407              :         return DLT_RETURN_WRONG_PARAMETER;
    1408              : 
    1409              :     /* load standard header extra parameters if used */
    1410         4505 :     if (DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp)) {
    1411         1530 :         if (fread(file->msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader),
    1412              :                   DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp),
    1413              :                   1, file->handle) != 1) {
    1414            0 :             dlt_log(LOG_WARNING, "Cannot read standard header extra parameters from file!\n");
    1415            0 :             return DLT_RETURN_ERROR;
    1416              :         }
    1417              : 
    1418          765 :         dlt_message_get_extraparameters(&(file->msg), verbose);
    1419              :     }
    1420              : 
    1421              :     /* load Extended header if used */
    1422         4505 :     if (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp) == 0)
    1423              :         /* there is nothing to be loaded */
    1424              :         return DLT_RETURN_OK;
    1425              : 
    1426         2173 :     if (fread(file->msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) +
    1427         2173 :               DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp),
    1428              :               (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp) ? sizeof(DltExtendedHeader) : 0),
    1429              :               1, file->handle) != 1) {
    1430            0 :         dlt_log(LOG_WARNING, "Cannot read extended header from file!\n");
    1431            0 :         return DLT_RETURN_ERROR;
    1432              :     }
    1433              : 
    1434              :     /* set extended header ptr */
    1435         2173 :     if (DLT_IS_HTYP_UEH(file->msg.standardheader->htyp))
    1436         2173 :         file->msg.extendedheader =
    1437         2173 :             (DltExtendedHeader *)(file->msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) +
    1438         2173 :                                   DLT_STANDARD_HEADER_EXTRA_SIZE(file->msg.standardheader->htyp));
    1439              :     else
    1440            0 :         file->msg.extendedheader = NULL;
    1441              : 
    1442              :     return DLT_RETURN_OK;
    1443              : }
    1444              : 
    1445         3875 : DltReturnValue dlt_file_read_data(DltFile *file, int verbose)
    1446              : {
    1447         3875 :     PRINT_FUNCTION_VERBOSE(verbose);
    1448              : 
    1449         3875 :     if (file == NULL)
    1450              :         return DLT_RETURN_WRONG_PARAMETER;
    1451              : 
    1452              :     /* free last used memory for buffer */
    1453         3875 :     if (file->msg.databuffer && (file->msg.databuffersize < file->msg.datasize)) {
    1454          129 :         free(file->msg.databuffer);
    1455          129 :         file->msg.databuffer = NULL;
    1456              :     }
    1457              : 
    1458         3875 :     if (file->msg.databuffer == NULL) {
    1459              :         /* get new memory for buffer */
    1460          168 :         file->msg.databuffer = (uint8_t *)malloc((size_t)file->msg.datasize);
    1461          168 :         file->msg.databuffersize = file->msg.datasize;
    1462              :     }
    1463              : 
    1464         3875 :     if (file->msg.databuffer == NULL) {
    1465            0 :         dlt_vlog(LOG_WARNING,
    1466              :                  "Cannot allocate memory for payload buffer of size %u!\n",
    1467              :                  file->msg.datasize);
    1468            0 :         return DLT_RETURN_ERROR;
    1469              :     }
    1470              : 
    1471              :     /* load payload data from file */
    1472         7750 :     if (fread(file->msg.databuffer, (size_t)file->msg.datasize, 1, file->handle) != 1) {
    1473           52 :         if (file->msg.datasize != 0) {
    1474            0 :             dlt_vlog(LOG_WARNING,
    1475              :                      "Cannot read payload data from file of size %u!\n",
    1476              :                      file->msg.datasize);
    1477            0 :             return DLT_RETURN_ERROR;
    1478              :         }
    1479              :     }
    1480              : 
    1481              :     return DLT_RETURN_OK;
    1482              : }
    1483              : 
    1484           50 : DltReturnValue dlt_file_open(DltFile *file, const char *filename, int verbose)
    1485              : {
    1486           50 :     PRINT_FUNCTION_VERBOSE(verbose);
    1487              : 
    1488           50 :     if ((file == NULL) || (filename == NULL))
    1489              :         return DLT_RETURN_WRONG_PARAMETER;
    1490              : 
    1491              :     /* reset counters */
    1492           44 :     file->counter = 0;
    1493           44 :     file->counter_total = 0;
    1494           44 :     file->position = 0;
    1495           44 :     file->file_position = 0;
    1496           44 :     file->file_length = 0;
    1497           44 :     file->error_messages = 0;
    1498              : 
    1499           44 :     if (file->handle)
    1500            0 :         fclose(file->handle);
    1501              : 
    1502              :     /* open dlt file */
    1503           44 :     file->handle = fopen(filename, "rb");
    1504              : 
    1505           44 :     if (file->handle == NULL) {
    1506            1 :         dlt_vlog(LOG_WARNING, "File %s cannot be opened!\n", filename);
    1507            1 :         return DLT_RETURN_ERROR;
    1508              :     }
    1509              : 
    1510           43 :     if (0 != fseek(file->handle, 0, SEEK_END)) {
    1511            0 :         dlt_vlog(LOG_WARNING, "dlt_file_open: Seek failed to 0,SEEK_END");
    1512            0 :         return DLT_RETURN_ERROR;
    1513              :     }
    1514              : 
    1515           43 :     file->file_length = (uint64_t)ftell(file->handle);
    1516              : 
    1517           43 :     if (0 != fseek(file->handle, 0, SEEK_SET)) {
    1518            0 :         dlt_vlog(LOG_WARNING, "dlt_file_open: Seek failed to 0,SEEK_SET");
    1519            0 :         return DLT_RETURN_ERROR;
    1520              :     }
    1521              : 
    1522           43 :     if (verbose)
    1523              :         /* print file length */
    1524            1 :         dlt_vlog(LOG_DEBUG, "File is %" PRIu64 "bytes long\n", file->file_length);
    1525              : 
    1526              :     return DLT_RETURN_OK;
    1527              : }
    1528              : 
    1529         2752 : DltReturnValue dlt_file_read(DltFile *file, int verbose)
    1530              : {
    1531              :     long *ptr;
    1532              :     int found = DLT_RETURN_OK;
    1533              : 
    1534         2752 :     if (file == NULL)
    1535              :         return DLT_RETURN_WRONG_PARAMETER;
    1536              : 
    1537         2752 :     if (verbose)
    1538            0 :         dlt_vlog(LOG_DEBUG, "%s: Message %d:\n", __func__, file->counter_total);
    1539              : 
    1540              :     /* allocate new memory for index if number of messages exceeds a multiple of DLT_COMMON_INDEX_ALLOC (e.g.: 1000) */
    1541         2752 :     if (file->counter % DLT_COMMON_INDEX_ALLOC == 0) {
    1542          350 :         ptr = (long *)malloc((size_t)((file->counter / DLT_COMMON_INDEX_ALLOC) + 1) * (size_t)DLT_COMMON_INDEX_ALLOC * sizeof(long));
    1543              : 
    1544          350 :         if (ptr == NULL)
    1545              :             return DLT_RETURN_ERROR;
    1546              : 
    1547          350 :         if (file->index) {
    1548          312 :             memcpy(ptr, file->index, (size_t)(file->counter) * sizeof(long));
    1549          312 :             free(file->index);
    1550              :         }
    1551              : 
    1552          350 :         file->index = ptr;
    1553              :     }
    1554              : 
    1555              :     /* set to end of last succesful read message, because of conflicting calls to dlt_file_read and dlt_file_message */
    1556         2752 :     if (0 != fseek(file->handle, (long)file->file_position, SEEK_SET)) {
    1557            0 :         dlt_vlog(LOG_WARNING, "Seek failed to file_position %" PRIu64 "\n",
    1558              :                  file->file_position);
    1559            0 :         return DLT_RETURN_ERROR;
    1560              :     }
    1561              : 
    1562              :     /* get file position at start of DLT message */
    1563         2752 :     if (verbose)
    1564            0 :         dlt_vlog(LOG_INFO, "Position in file: %" PRIu64 "\n", file->file_position);
    1565              : 
    1566              :     /* read header */
    1567         2752 :     if (dlt_file_read_header(file, verbose) < DLT_RETURN_OK) {
    1568              :         /* go back to last position in file */
    1569           38 :         if (0 != fseek(file->handle, (long)file->file_position, SEEK_SET)) {
    1570            0 :             dlt_vlog(LOG_WARNING, "Seek failed to file_position %" PRIu64 " \n",
    1571              :                     file->file_position);
    1572              :         }
    1573           38 :         return DLT_RETURN_ERROR;
    1574              :     }
    1575              : 
    1576         2714 :     if (file->filter) {
    1577              :         /* read the extended header if filter is enabled and extended header exists */
    1578          630 :         if (dlt_file_read_header_extended(file, verbose) < DLT_RETURN_OK) {
    1579              :             /* go back to last position in file */
    1580            0 :             if (0 != fseek(file->handle, (long)file->file_position, SEEK_SET))
    1581            0 :                 dlt_vlog(LOG_WARNING, "Seek to last file pos failed!\n");
    1582              : 
    1583            0 :             return DLT_RETURN_ERROR;
    1584              :         }
    1585              : 
    1586              :         /* check the filters if message is used */
    1587          630 :         if (dlt_message_filter_check(&(file->msg), file->filter, verbose) == DLT_RETURN_TRUE) {
    1588              :             /* filter matched, consequently store current message */
    1589              :             /* store index pointer to message position in DLT file */
    1590          318 :             file->index[file->counter] = (long)file->file_position;
    1591          318 :             file->counter++;
    1592          318 :             file->position = file->counter - 1;
    1593              : 
    1594              :             found = DLT_RETURN_TRUE;
    1595              :         }
    1596              : 
    1597              :         /* skip payload data */
    1598          630 :         if (fseek(file->handle, (long)file->msg.datasize, SEEK_CUR) != 0) {
    1599              :             /* go back to last position in file */
    1600            0 :             dlt_vlog(LOG_WARNING,
    1601              :                      "Seek failed to skip payload data of size %u!\n",
    1602              :                      file->msg.datasize);
    1603              : 
    1604            0 :             if (0 != fseek(file->handle, (long)file->file_position, SEEK_SET))
    1605            0 :                 dlt_log(LOG_WARNING, "Seek back also failed!\n");
    1606              : 
    1607            0 :             return DLT_RETURN_ERROR;
    1608              :         }
    1609              :     }
    1610              :     else {
    1611              :         /* filter is disabled */
    1612              :         /* skip additional header parameters and payload data */
    1613         2084 :         if (fseek(file->handle,
    1614         2084 :                   (long)((int32_t)file->msg.headersize - (int32_t)sizeof(DltStorageHeader) - (int32_t)sizeof(DltStandardHeader) + (long)file->msg.datasize),
    1615              :                   SEEK_CUR)) {
    1616              : 
    1617            0 :             dlt_vlog(LOG_WARNING,
    1618              :                      "Seek failed to skip extra header and payload data from file of size %u!\n",
    1619            0 :                      file->msg.headersize - (int32_t)sizeof(DltStorageHeader) -
    1620            0 :                      (int32_t)sizeof(DltStandardHeader) + file->msg.datasize);
    1621              : 
    1622              :             /* go back to last position in file */
    1623            0 :             if (fseek(file->handle, (long)file->file_position, SEEK_SET))
    1624            0 :                 dlt_log(LOG_WARNING, "Seek back also failed!\n");
    1625              : 
    1626            0 :             return DLT_RETURN_ERROR;
    1627              :         }
    1628              : 
    1629              :         /* store index pointer to message position in DLT file */
    1630         2084 :         file->index[file->counter] = (long)file->file_position;
    1631         2084 :         file->counter++;
    1632         2084 :         file->position = file->counter - 1;
    1633              : 
    1634              :         found = DLT_RETURN_TRUE;
    1635              :     }
    1636              : 
    1637              :     /* increase total message counter */
    1638         2714 :     file->counter_total++;
    1639              : 
    1640              :     /* store position to next message */
    1641         2714 :     file->file_position = (uint64_t)ftell(file->handle);
    1642              : 
    1643         2714 :     return found;
    1644              : }
    1645              : 
    1646            0 : DltReturnValue dlt_file_read_raw(DltFile *file, int resync, int verbose)
    1647              : {
    1648              :     int found = DLT_RETURN_OK;
    1649              :     long *ptr;
    1650              : 
    1651            0 :     if (verbose)
    1652            0 :         dlt_vlog(LOG_DEBUG, "%s: Message %d:\n", __func__, file->counter_total);
    1653              : 
    1654            0 :     if (file == NULL)
    1655              :         return DLT_RETURN_WRONG_PARAMETER;
    1656              : 
    1657              :     /* allocate new memory for index if number of messages exceeds a multiple of DLT_COMMON_INDEX_ALLOC (e.g.: 1000) */
    1658            0 :     if (file->counter % DLT_COMMON_INDEX_ALLOC == 0) {
    1659            0 :         ptr = (long *)malloc((size_t)((file->counter / DLT_COMMON_INDEX_ALLOC) + 1) * (size_t)DLT_COMMON_INDEX_ALLOC * sizeof(long));
    1660              : 
    1661            0 :         if (ptr == NULL)
    1662              :             return DLT_RETURN_ERROR;
    1663              : 
    1664            0 :         if (file->index) {
    1665            0 :             memcpy(ptr, file->index, (size_t)(file->counter) * sizeof(long));
    1666            0 :             free(file->index);
    1667              :         }
    1668              : 
    1669            0 :         file->index = ptr;
    1670              :     }
    1671              : 
    1672              :     /* set to end of last successful read message, because of conflicting calls to dlt_file_read and dlt_file_message */
    1673            0 :     if (0 != fseek(file->handle, (long)file->file_position, SEEK_SET))
    1674              :         return DLT_RETURN_ERROR;
    1675              : 
    1676              :     /* get file position at start of DLT message */
    1677            0 :     if (verbose)
    1678            0 :         dlt_vlog(LOG_DEBUG, "Position in file: %" PRIu64 "\n", file->file_position);
    1679              : 
    1680              :     /* read header */
    1681            0 :     if (dlt_file_read_header_raw(file, resync, verbose) < DLT_RETURN_OK) {
    1682              :         /* go back to last position in file */
    1683            0 :         if (0 != fseek(file->handle, (long)file->file_position, SEEK_SET))
    1684            0 :             dlt_log(LOG_WARNING, "dlt_file_read_raw, fseek failed 1\n");
    1685              : 
    1686            0 :         return DLT_RETURN_ERROR;
    1687              :     }
    1688              : 
    1689              :     /* read the extended header if filter is enabled and extended header exists */
    1690            0 :     if (dlt_file_read_header_extended(file, verbose) < DLT_RETURN_OK) {
    1691              :         /* go back to last position in file */
    1692            0 :         if (0 != fseek(file->handle, (long)file->file_position, SEEK_SET))
    1693            0 :             dlt_log(LOG_WARNING, "dlt_file_read_raw, fseek failed 2\n");
    1694              : 
    1695            0 :         return DLT_RETURN_ERROR;
    1696              :     }
    1697              : 
    1698            0 :     if (dlt_file_read_data(file, verbose) < DLT_RETURN_OK) {
    1699              :         /* go back to last position in file */
    1700            0 :         if (0 != fseek(file->handle, (long)file->file_position, SEEK_SET))
    1701            0 :             dlt_log(LOG_WARNING, "dlt_file_read_raw, fseek failed 3\n");
    1702              : 
    1703            0 :         return DLT_RETURN_ERROR;
    1704              :     }
    1705              : 
    1706              :     /* store index pointer to message position in DLT file */
    1707            0 :     file->index[file->counter] = (long)file->file_position;
    1708            0 :     file->counter++;
    1709            0 :     file->position = file->counter - 1;
    1710              : 
    1711              :     found = DLT_RETURN_TRUE;
    1712              : 
    1713              :     /* increase total message counter */
    1714            0 :     file->counter_total++;
    1715              : 
    1716              :     /* store position to next message */
    1717            0 :     file->file_position = (uint64_t)ftell(file->handle);
    1718              : 
    1719            0 :     return found;
    1720              : }
    1721              : 
    1722            0 : DltReturnValue dlt_file_close(DltFile *file, int verbose)
    1723              : {
    1724            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1725              : 
    1726            0 :     if (file == NULL)
    1727              :         return DLT_RETURN_WRONG_PARAMETER;
    1728              : 
    1729            0 :     if (file->handle)
    1730            0 :         fclose(file->handle);
    1731              : 
    1732            0 :     file->handle = NULL;
    1733              : 
    1734            0 :     return DLT_RETURN_OK;
    1735              : }
    1736              : 
    1737         3770 : DltReturnValue dlt_file_message(DltFile *file, int index, int verbose)
    1738              : {
    1739         3770 :     PRINT_FUNCTION_VERBOSE(verbose);
    1740              : 
    1741         3770 :     if (file == NULL)
    1742              :         return DLT_RETURN_WRONG_PARAMETER;
    1743              : 
    1744              :     /* check if message is in range */
    1745         3770 :     if (index < 0 || index >= file->counter) {
    1746            0 :         dlt_vlog(LOG_WARNING, "Message %d out of range!\r\n", index);
    1747            0 :         return DLT_RETURN_WRONG_PARAMETER;
    1748              :     }
    1749              : 
    1750              :     /* seek to position in file */
    1751         3770 :     if (fseek(file->handle, file->index[index], SEEK_SET) != 0) {
    1752            0 :         dlt_vlog(LOG_WARNING, "Seek to message %d to position %ld failed!\r\n",
    1753            0 :                  index, file->index[index]);
    1754            0 :         return DLT_RETURN_ERROR;
    1755              :     }
    1756              : 
    1757              :     /* read all header and payload */
    1758         3770 :     if (dlt_file_read_header(file, verbose) < DLT_RETURN_OK)
    1759              :         return DLT_RETURN_ERROR;
    1760              : 
    1761         3770 :     if (dlt_file_read_header_extended(file, verbose) < DLT_RETURN_OK)
    1762              :         return DLT_RETURN_ERROR;
    1763              : 
    1764         3770 :     if (dlt_file_read_data(file, verbose) < DLT_RETURN_OK)
    1765              :         return DLT_RETURN_ERROR;
    1766              : 
    1767              :     /* set current position in file */
    1768         3770 :     file->position = index;
    1769              : 
    1770         3770 :     return DLT_RETURN_OK;
    1771              : }
    1772              : 
    1773           51 : DltReturnValue dlt_file_free(DltFile *file, int verbose)
    1774              : {
    1775           51 :     PRINT_FUNCTION_VERBOSE(verbose);
    1776              : 
    1777           51 :     if (file == NULL)
    1778              :         return DLT_RETURN_WRONG_PARAMETER;
    1779              : 
    1780              :     /* delete index lost if exists */
    1781           51 :     if (file->index)
    1782           36 :         free(file->index);
    1783              : 
    1784           51 :     file->index = NULL;
    1785              : 
    1786              :     /* close file */
    1787           51 :     if (file->handle)
    1788           41 :         fclose(file->handle);
    1789              : 
    1790           51 :     file->handle = NULL;
    1791              : 
    1792           51 :     return dlt_message_free(&(file->msg), verbose);
    1793              : }
    1794              : 
    1795              : #if defined DLT_DAEMON_USE_FIFO_IPC || defined DLT_LIB_USE_FIFO_IPC
    1796        24523 : void dlt_log_set_fifo_basedir(const char *pipe_dir)
    1797              : {
    1798              :     strncpy(dltFifoBaseDir, pipe_dir, DLT_PATH_MAX);
    1799        24523 :     dltFifoBaseDir[DLT_PATH_MAX - 1] = 0;
    1800        24514 : }
    1801              : #endif
    1802              : 
    1803              : #ifdef DLT_SHM_ENABLE
    1804              : void dlt_log_set_shm_name(const char *env_shm_name)
    1805              : {
    1806              :     strncpy(dltShmName, env_shm_name, NAME_MAX);
    1807              :     dltShmName[NAME_MAX] = 0;
    1808              : }
    1809              : #endif
    1810              : 
    1811            0 : void dlt_print_with_attributes(bool state)
    1812              : {
    1813            0 :     print_with_attributes = state;
    1814            0 : }
    1815              : 
    1816        24556 : DltReturnValue dlt_receiver_init(DltReceiver *receiver, int fd, DltReceiverType type, int buffersize)
    1817              : {
    1818        24556 :     if (NULL == receiver)
    1819              :         return DLT_RETURN_WRONG_PARAMETER;
    1820              : 
    1821        24556 :     receiver->fd = fd;
    1822        24556 :     receiver->type = type;
    1823              : 
    1824              :     /** Reuse the receiver buffer if it exists and the buffer size
    1825              :       * is not changed. If not, free the old one and allocate a new buffer.
    1826              :       */
    1827        24556 :     if ((NULL != receiver->buffer) && ( buffersize != receiver->buffersize)) {
    1828            0 :        free(receiver->buffer);
    1829            0 :        receiver->buffer = NULL;
    1830              :     }
    1831              : 
    1832        24556 :     if (NULL == receiver->buffer) {
    1833        24556 :         receiver->lastBytesRcvd = 0;
    1834        24556 :         receiver->bytesRcvd = 0;
    1835        24556 :         receiver->totalBytesRcvd = 0;
    1836        24556 :         receiver->buf = NULL;
    1837        24556 :         receiver->backup_buf = NULL;
    1838        24556 :         receiver->buffer = (char *)calloc(1, (size_t)buffersize);
    1839        24556 :         receiver->buffersize = (int32_t)buffersize;
    1840              :     }
    1841              : 
    1842        24556 :     if (NULL == receiver->buffer) {
    1843            0 :         dlt_log(LOG_ERR, "allocate memory for receiver buffer failed.\n");
    1844            0 :         return DLT_RETURN_ERROR;
    1845              :     }
    1846              :     else {
    1847        24556 :         receiver->buf = receiver->buffer;
    1848              :     }
    1849              : 
    1850        24556 :     return DLT_RETURN_OK;
    1851              : }
    1852              : 
    1853            9 : DltReturnValue dlt_receiver_init_global_buffer(DltReceiver *receiver, int fd, DltReceiverType type, char **buffer)
    1854              : {
    1855            9 :     if (receiver == NULL)
    1856              :         return DLT_RETURN_WRONG_PARAMETER;
    1857              : 
    1858            9 :     if (*buffer == NULL) {
    1859              :         /* allocating the buffer once and using it for all application receivers
    1860              :          * by keeping allocated buffer in app_recv_buffer global handle
    1861              :          */
    1862            9 :         *buffer = (char *)malloc(DLT_RECEIVE_BUFSIZE);
    1863              : 
    1864            9 :         if (*buffer == NULL)
    1865              :             return DLT_RETURN_ERROR;
    1866              :     }
    1867              : 
    1868            9 :     receiver->lastBytesRcvd = 0;
    1869            9 :     receiver->bytesRcvd = 0;
    1870            9 :     receiver->totalBytesRcvd = 0;
    1871            9 :     receiver->buffersize = DLT_RECEIVE_BUFSIZE;
    1872            9 :     receiver->fd = fd;
    1873            9 :     receiver->type = type;
    1874            9 :     receiver->buffer = *buffer;
    1875            9 :     receiver->backup_buf = NULL;
    1876            9 :     receiver->buf = receiver->buffer;
    1877              : 
    1878            9 :     return DLT_RETURN_OK;
    1879              : }
    1880              : 
    1881        24555 : DltReturnValue dlt_receiver_free(DltReceiver *receiver)
    1882              : {
    1883              : 
    1884        24555 :     if (receiver == NULL)
    1885              :         return DLT_RETURN_WRONG_PARAMETER;
    1886              : 
    1887        24555 :     if (receiver->buffer)
    1888        24553 :         free(receiver->buffer);
    1889              : 
    1890        24555 :     if (receiver->backup_buf)
    1891            0 :         free(receiver->backup_buf);
    1892              : 
    1893        24555 :     receiver->buffer = NULL;
    1894        24555 :     receiver->buf = NULL;
    1895        24555 :     receiver->backup_buf = NULL;
    1896              : 
    1897        24555 :     return DLT_RETURN_OK;
    1898              : }
    1899              : 
    1900            9 : DltReturnValue dlt_receiver_free_global_buffer(DltReceiver *receiver)
    1901              : {
    1902              : 
    1903            9 :     if (receiver == NULL)
    1904              :         return DLT_RETURN_WRONG_PARAMETER;
    1905              : 
    1906            9 :     if (receiver->backup_buf)
    1907            0 :         free(receiver->backup_buf);
    1908              : 
    1909            9 :     receiver->buffer = NULL;
    1910            9 :     receiver->buf = NULL;
    1911            9 :     receiver->backup_buf = NULL;
    1912              : 
    1913            9 :     return DLT_RETURN_OK;
    1914              : }
    1915              : 
    1916         1692 : int dlt_receiver_receive(DltReceiver *receiver)
    1917              : {
    1918              :     socklen_t addrlen;
    1919              : 
    1920         1692 :     if (receiver == NULL)
    1921              :         return -1;
    1922              : 
    1923         1692 :     if (receiver->buffer == NULL)
    1924              :         return -1;
    1925              : 
    1926         1691 :     receiver->buf = (char *)receiver->buffer;
    1927         1691 :     receiver->lastBytesRcvd = receiver->bytesRcvd;
    1928              : 
    1929         1691 :     if ((receiver->lastBytesRcvd) && (receiver->backup_buf != NULL)) {
    1930            1 :         memcpy(receiver->buf, receiver->backup_buf, (size_t)receiver->lastBytesRcvd);
    1931            1 :         free(receiver->backup_buf);
    1932            1 :         receiver->backup_buf = NULL;
    1933              :     }
    1934              : 
    1935         1691 :     if (receiver->type == DLT_RECEIVE_SOCKET) {
    1936              :         /* wait for data from socket */
    1937          437 :         ssize_t bytes = recv(receiver->fd,
    1938          437 :                             receiver->buf + receiver->lastBytesRcvd,
    1939          437 :                             (size_t)(receiver->buffersize - receiver->lastBytesRcvd),
    1940              :                             0);
    1941          873 :         receiver->bytesRcvd = (bytes >= 0 && bytes <= INT32_MAX) ? (int32_t)bytes : 0;
    1942              :     }
    1943         1254 :     else if (receiver->type == DLT_RECEIVE_FD) {
    1944              :         /* wait for data from fd */
    1945         1254 :         ssize_t bytes = read(receiver->fd,
    1946         1254 :                             receiver->buf + receiver->lastBytesRcvd,
    1947         1254 :                             (size_t)(receiver->buffersize - receiver->lastBytesRcvd));
    1948         2508 :         receiver->bytesRcvd = (bytes >= 0 && bytes <= INT32_MAX) ? (int32_t)bytes : 0;
    1949              :     }
    1950              :     else { /* receiver->type == DLT_RECEIVE_UDP_SOCKET */
    1951              :         /* wait for data from UDP socket */
    1952            0 :         addrlen = sizeof(receiver->addr);
    1953            0 :         ssize_t bytes = recvfrom(receiver->fd,
    1954            0 :                                 receiver->buf + receiver->lastBytesRcvd,
    1955            0 :                                 (size_t)(receiver->buffersize - receiver->lastBytesRcvd),
    1956              :                                 0,
    1957            0 :                                 (struct sockaddr *)&(receiver->addr),
    1958              :                                 &addrlen);
    1959            0 :         receiver->bytesRcvd = (bytes >= 0 && bytes <= INT32_MAX) ? (int32_t)bytes : 0;
    1960              :     }
    1961              : 
    1962         1691 :     if (receiver->bytesRcvd <= 0) {
    1963            6 :         receiver->bytesRcvd = 0;
    1964            6 :         return receiver->bytesRcvd;
    1965              :     } /* if */
    1966              : 
    1967         1685 :     receiver->totalBytesRcvd += receiver->bytesRcvd;
    1968         1685 :     receiver->bytesRcvd += receiver->lastBytesRcvd;
    1969              : 
    1970         1685 :     return receiver->bytesRcvd;
    1971              : }
    1972              : 
    1973         6096 : DltReturnValue dlt_receiver_remove(DltReceiver *receiver, int size)
    1974              : {
    1975         6096 :     if (receiver == NULL)
    1976              :         return DLT_RETURN_WRONG_PARAMETER;
    1977              : 
    1978         6139 :     if (receiver->buf == NULL)
    1979              :         return DLT_RETURN_ERROR;
    1980              : 
    1981         6139 :     if ((size > receiver->bytesRcvd) || (size <= 0)) {
    1982            0 :         receiver->buf = receiver->buf + receiver->bytesRcvd;
    1983            0 :         receiver->bytesRcvd = 0;
    1984            0 :         return DLT_RETURN_WRONG_PARAMETER;
    1985              :     }
    1986              : 
    1987         6139 :     receiver->bytesRcvd = receiver->bytesRcvd - size;
    1988          262 :     receiver->buf = receiver->buf + size;
    1989              : 
    1990         6096 :     return DLT_RETURN_OK;
    1991              : }
    1992              : 
    1993         1686 : DltReturnValue dlt_receiver_move_to_begin(DltReceiver *receiver)
    1994              : {
    1995         1686 :     if (receiver == NULL)
    1996              :         return DLT_RETURN_WRONG_PARAMETER;
    1997              : 
    1998         1686 :     if ((receiver->buffer == NULL) || (receiver->buf == NULL))
    1999              :         return DLT_RETURN_ERROR;
    2000              : 
    2001         1686 :     if ((receiver->buffer != receiver->buf) && (receiver->bytesRcvd != 0)) {
    2002            1 :         receiver->backup_buf = calloc((size_t)(receiver->bytesRcvd + 1), sizeof(char));
    2003              : 
    2004            1 :         if (receiver->backup_buf == NULL)
    2005            0 :             dlt_vlog(LOG_WARNING,
    2006              :                      "Can't allocate memory for backup buf, there will be atleast"
    2007              :                      "one corrupted message for fd[%d] \n", receiver->fd);
    2008              :         else
    2009            1 :             memcpy(receiver->backup_buf, receiver->buf, (size_t)receiver->bytesRcvd);
    2010              :     }
    2011              : 
    2012              :     return DLT_RETURN_OK;
    2013              : }
    2014              : 
    2015          133 : int dlt_receiver_check_and_get(DltReceiver *receiver,
    2016              :                                void *dest,
    2017              :                                unsigned int to_get,
    2018              :                                unsigned int flags)
    2019              : {
    2020          133 :     size_t min_size = (size_t)to_get;
    2021              :     uint8_t *src = NULL;
    2022              : 
    2023          133 :     if (flags & DLT_RCV_SKIP_HEADER)
    2024           88 :         min_size += sizeof(DltUserHeader);
    2025              : 
    2026          133 :     if (!receiver ||
    2027          133 :         (receiver->bytesRcvd < (int32_t) min_size) ||
    2028          133 :         !receiver->buf ||
    2029              :         !dest)
    2030              :         return DLT_RETURN_WRONG_PARAMETER;
    2031              : 
    2032              :     src = (uint8_t *)receiver->buf;
    2033              : 
    2034          133 :     if (flags & DLT_RCV_SKIP_HEADER)
    2035           88 :         src += sizeof(DltUserHeader);
    2036              : 
    2037              :     memcpy(dest, src, to_get);
    2038              : 
    2039          133 :     if (flags & DLT_RCV_REMOVE) {
    2040            0 :         if (dlt_receiver_remove(receiver, (int)min_size) != DLT_RETURN_OK) {
    2041            0 :             dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
    2042            0 :             return DLT_RETURN_ERROR;
    2043              :         }
    2044              :     }
    2045              : 
    2046          133 :     return (int)to_get;
    2047              : }
    2048              : 
    2049        12103 : DltReturnValue dlt_set_storageheader(DltStorageHeader *storageheader, const char *ecu)
    2050              : {
    2051              : 
    2052              : #if !defined(_MSC_VER)
    2053              :     struct timeval tv;
    2054              : #endif
    2055              : 
    2056        12103 :     if ((storageheader == NULL) || (ecu == NULL))
    2057              :         return DLT_RETURN_WRONG_PARAMETER;
    2058              : 
    2059              :     /* get time of day */
    2060              : #if defined(_MSC_VER)
    2061              :     time(&(storageheader->seconds));
    2062              : #else
    2063        12103 :     gettimeofday(&tv, NULL);
    2064              : #endif
    2065              : 
    2066              :     /* prepare storage header */
    2067        12103 :     storageheader->pattern[0] = 'D';
    2068        12103 :     storageheader->pattern[1] = 'L';
    2069        12103 :     storageheader->pattern[2] = 'T';
    2070        12103 :     storageheader->pattern[3] = 0x01;
    2071              : 
    2072        12103 :     dlt_set_id(storageheader->ecu, ecu);
    2073              : 
    2074              :     /* Set current time */
    2075              : #if defined(_MSC_VER)
    2076              :     storageheader->microseconds = 0;
    2077              : #else
    2078        12103 :     storageheader->seconds = (uint32_t) tv.tv_sec; /* value is long */
    2079        12103 :     storageheader->microseconds = (int32_t) tv.tv_usec; /* value is long */
    2080              : #endif
    2081              : 
    2082        12103 :     return DLT_RETURN_OK;
    2083              : }
    2084              : 
    2085            9 : DltReturnValue dlt_check_rcv_data_size(int received, int required)
    2086              : {
    2087              :     int _ret = DLT_RETURN_OK;
    2088            9 :     if (received < required) {
    2089            1 :         dlt_vlog(LOG_WARNING, "%s: Received data not complete\n", __func__);
    2090              :         _ret = DLT_RETURN_ERROR;
    2091              :     }
    2092              : 
    2093            9 :     return _ret;
    2094              : }
    2095              : 
    2096         6589 : DltReturnValue dlt_check_storageheader(DltStorageHeader *storageheader)
    2097              : {
    2098         6589 :     if (storageheader == NULL)
    2099              :         return DLT_RETURN_WRONG_PARAMETER;
    2100              : 
    2101        13178 :     return ((storageheader->pattern[0] == 'D') &&
    2102         6589 :             (storageheader->pattern[1] == 'L') &&
    2103         6589 :             (storageheader->pattern[2] == 'T') &&
    2104         6589 :             (storageheader->pattern[3] == 1))
    2105        13178 :            ? DLT_RETURN_TRUE : DLT_RETURN_OK;
    2106              : }
    2107              : 
    2108            0 : DltReturnValue dlt_buffer_init_static_server(DltBuffer *buf, const unsigned char *ptr, uint32_t size)
    2109              : {
    2110            0 :     if ((buf == NULL) || (ptr == NULL))
    2111              :         return DLT_RETURN_WRONG_PARAMETER;
    2112              : 
    2113              :     DltBufferHead *head;
    2114              : 
    2115              :     /* Init parameters */
    2116              :     union {
    2117              :         const unsigned char *cp;
    2118              :         unsigned char *p;
    2119              :     } shm_cast;
    2120              :     shm_cast.cp = ptr;
    2121            0 :     buf->shm = shm_cast.p;
    2122            0 :     buf->min_size = size;
    2123            0 :     buf->max_size = size;
    2124            0 :     buf->step_size = 0;
    2125              : 
    2126              :     /* Init pointers */
    2127              :     head = (DltBufferHead *)buf->shm;
    2128            0 :     head->read = 0;
    2129            0 :     head->write = 0;
    2130            0 :     head->count = 0;
    2131            0 :     buf->mem = (unsigned char *)(buf->shm + sizeof(DltBufferHead));
    2132            0 :     buf->size = (unsigned int) buf->min_size - (unsigned int) sizeof(DltBufferHead);
    2133              : 
    2134              :     /* clear memory */
    2135            0 :     memset(buf->mem, 0, buf->size);
    2136              : 
    2137            0 :     dlt_vlog(LOG_DEBUG,
    2138              :              "%s: Buffer: Size %u, Start address %lX\n",
    2139            0 :              __func__, buf->size, (unsigned long)buf->mem);
    2140              : 
    2141            0 :     return DLT_RETURN_OK; /* OK */
    2142              : }
    2143              : 
    2144            0 : DltReturnValue dlt_buffer_init_static_client(DltBuffer *buf, const unsigned char *ptr, uint32_t size)
    2145              : {
    2146            0 :     if ((buf == NULL) || (ptr == NULL))
    2147              :         return DLT_RETURN_WRONG_PARAMETER;
    2148              : 
    2149              :     /* Init parameters */
    2150              :     union {
    2151              :         const unsigned char *cp;
    2152              :         unsigned char *p;
    2153              :     } shm_cast;
    2154              :     shm_cast.cp = ptr;
    2155            0 :     buf->shm = shm_cast.p;
    2156            0 :     buf->min_size = size;
    2157            0 :     buf->max_size = size;
    2158            0 :     buf->step_size = 0;
    2159              : 
    2160              :     /* Init pointers */
    2161            0 :     buf->mem = (unsigned char *)(buf->shm + sizeof(DltBufferHead));
    2162            0 :     buf->size = (uint32_t)(buf->min_size - sizeof(DltBufferHead));
    2163              : 
    2164            0 :     dlt_vlog(LOG_DEBUG,
    2165              :              "%s: Buffer: Size %u, Start address %lX\n",
    2166              :              __func__, buf->size, (unsigned long)buf->mem);
    2167              : 
    2168            0 :     return DLT_RETURN_OK; /* OK */
    2169              : }
    2170              : 
    2171        24651 : DltReturnValue dlt_buffer_init_dynamic(DltBuffer *buf, uint32_t min_size, uint32_t max_size, uint32_t step_size)
    2172              : {
    2173              :     /*Do not dlt_mutex_lock inside here! */
    2174              :     DltBufferHead *head;
    2175              : 
    2176              :     /* catch null pointer */
    2177        24651 :     if (buf == NULL)
    2178              :         return DLT_RETURN_WRONG_PARAMETER;
    2179              : 
    2180              :     /* catch 0 logical errors */
    2181        24643 :     if ((min_size == 0) || (max_size == 0) || (step_size == 0))
    2182              :         return DLT_RETURN_WRONG_PARAMETER;
    2183              : 
    2184        24634 :     if (min_size > max_size)
    2185              :         return DLT_RETURN_WRONG_PARAMETER;
    2186              : 
    2187        24632 :     if (step_size > max_size)
    2188              :         return DLT_RETURN_WRONG_PARAMETER;
    2189              : 
    2190              :     /* Init parameters */
    2191        24632 :     buf->min_size = min_size;
    2192        24632 :     buf->max_size = max_size;
    2193        24632 :     buf->step_size = step_size;
    2194              : 
    2195              :     /* allocat memory */
    2196        24632 :     buf->shm = malloc(buf->min_size);
    2197              : 
    2198        24632 :     if (buf->shm == NULL) {
    2199            0 :         dlt_vlog(LOG_EMERG,
    2200              :                  "%s: Buffer: Cannot allocate %u bytes\n",
    2201              :                  __func__, buf->min_size);
    2202            0 :         return DLT_RETURN_ERROR;
    2203              :     }
    2204              : 
    2205              :     /* Init pointers */
    2206              :     head = (DltBufferHead *)buf->shm;
    2207        24632 :     head->read = 0;
    2208        24632 :     head->write = 0;
    2209        24632 :     head->count = 0;
    2210        24632 :     buf->mem = (unsigned char *)(buf->shm + sizeof(DltBufferHead));
    2211              : 
    2212        24632 :     if (buf->min_size < (uint32_t)sizeof(DltBufferHead)) {
    2213            0 :         dlt_vlog(LOG_ERR,
    2214              :                  "%s: min_size is too small [%u]\n",
    2215              :                  __func__, buf->min_size);
    2216            0 :         return DLT_RETURN_WRONG_PARAMETER;
    2217              :     }
    2218              : 
    2219        24632 :     buf->size = (uint32_t) (buf->min_size - sizeof(DltBufferHead));
    2220              : 
    2221        24632 :     dlt_vlog(LOG_DEBUG,
    2222              :              "%s: Buffer: Size %u, Start address %lX\n",
    2223              :              __func__, buf->size, (unsigned long)buf->mem);
    2224              : 
    2225              :     /* clear memory */
    2226        24632 :     memset(buf->mem, 0, (size_t)buf->size);
    2227              : 
    2228        24632 :     return DLT_RETURN_OK; /* OK */
    2229              : }
    2230              : 
    2231            0 : DltReturnValue dlt_buffer_free_static(DltBuffer *buf)
    2232              : {
    2233              :     /* catch null pointer */
    2234            0 :     if (buf == NULL)
    2235              :         return DLT_RETURN_WRONG_PARAMETER;
    2236              : 
    2237            0 :     if (buf->mem == NULL) {
    2238              :         /* buffer not initialized */
    2239            0 :         dlt_vlog(LOG_WARNING, "%s: Buffer: Buffer not initialized\n", __func__);
    2240            0 :         return DLT_RETURN_ERROR; /* ERROR */
    2241              :     }
    2242              : 
    2243              :     return DLT_RETURN_OK;
    2244              : }
    2245              : 
    2246        24622 : DltReturnValue dlt_buffer_free_dynamic(DltBuffer *buf)
    2247              : {
    2248              :     /* catch null pointer */
    2249        24622 :     if (buf == NULL)
    2250              :         return DLT_RETURN_WRONG_PARAMETER;
    2251              : 
    2252        24621 :     if (buf->shm == NULL) {
    2253              :         /* buffer not initialized */
    2254            0 :         dlt_vlog(LOG_WARNING, "%s: Buffer: Buffer not initialized\n", __func__);
    2255            0 :         return DLT_RETURN_ERROR; /* ERROR */
    2256              :     }
    2257              : 
    2258        24621 :     free(buf->shm);
    2259        24621 :     buf->shm = NULL;
    2260        24621 :     buf->mem = NULL;
    2261              : 
    2262        24621 :     return DLT_RETURN_OK;
    2263              : }
    2264              : 
    2265        53549 : void dlt_buffer_write_block(DltBuffer *buf, int *write, const unsigned char *data, unsigned int size)
    2266              : {
    2267              :     /* catch null pointer */
    2268        53549 :     if ((buf != NULL) && (write != NULL) && (data != NULL)) {
    2269        52530 :         if (size <= buf->size){
    2270        52530 :             if (( (unsigned int) (*write ) + size) <= buf->size) {
    2271              :                 /* write one block */
    2272        52529 :                 memcpy(buf->mem + *write, data, size);
    2273        52529 :                 *write += (int) size;
    2274              :             }
    2275              :             else {
    2276              :                 /* when (*write) = buf->size, write only the second block
    2277              :                 * and update write position correspondingly.
    2278              :                 */
    2279            1 :                 if((unsigned int) (*write) <= buf->size) {
    2280              :                     /* write two blocks */
    2281            1 :                     memcpy(buf->mem + *write, data, buf->size - (unsigned int) (*write));
    2282            1 :                     memcpy(buf->mem, data + buf->size - *write, size - buf->size + (unsigned int) (*write));
    2283            1 :                     *write += (int) (size - buf->size);
    2284              :                 }
    2285              :             }
    2286              :         }
    2287              :         else {
    2288            0 :             dlt_vlog(LOG_WARNING, "%s: Write error: ring buffer to small\n", __func__);
    2289              :         }
    2290              :     }
    2291              :     else {
    2292         1019 :         dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__);
    2293              :     }
    2294        53549 : }
    2295              : 
    2296           53 : void dlt_buffer_read_block(DltBuffer *buf, int *read, unsigned char *data, unsigned int size)
    2297              : {
    2298              :     /* catch nullpointer */
    2299           53 :     if ((buf != NULL) && (read != NULL) && (data != NULL)) {
    2300           37 :         if (((unsigned int)(*read) + size) <= buf->size) {
    2301              :             /* read one block */
    2302           35 :             memcpy(data, buf->mem + *read, size);
    2303           35 :             *read += (int)size;
    2304              :         }
    2305              :         else {
    2306              :             /* when (*read) = buf->size, read only the second block
    2307              :             * and update read position correspondingly.
    2308              :             */
    2309            2 :             if ((unsigned int)(*read) <= buf->size) {
    2310              :                 /* read two blocks */
    2311            1 :                 memcpy(data, buf->mem + *read, buf->size - (unsigned int)(*read));
    2312            1 :                 memcpy(data + buf->size - *read, buf->mem, size - buf->size + (unsigned int)(*read));
    2313            1 :                 *read += (int) (size - buf->size);
    2314              :             }
    2315              :         }
    2316              :     }
    2317              :     else {
    2318           16 :         dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__);
    2319              :     }
    2320           53 : }
    2321              : 
    2322          859 : DltReturnValue dlt_buffer_check_size(DltBuffer *buf, int needed)
    2323              : {
    2324          859 :     if (buf == NULL)
    2325              :         return DLT_RETURN_WRONG_PARAMETER;
    2326              : 
    2327          859 :     if ((buf->size + sizeof(DltBufferHead) + (size_t) needed) > buf->max_size)
    2328            0 :         return DLT_RETURN_ERROR;
    2329              : 
    2330              :     return DLT_RETURN_OK;
    2331              : }
    2332              : 
    2333           11 : int dlt_buffer_increase_size(DltBuffer *buf)
    2334              : {
    2335              :     DltBufferHead *head, *new_head;
    2336              :     unsigned char *new_ptr;
    2337              : 
    2338              :     /* catch null pointer */
    2339           11 :     if (buf == NULL) {
    2340            1 :         dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__);
    2341            1 :         return DLT_RETURN_WRONG_PARAMETER;
    2342              :     }
    2343              : 
    2344              :     /* check size */
    2345           10 :     if (buf->step_size == 0)
    2346              :         /* cannot increase size */
    2347              :         return DLT_RETURN_ERROR;
    2348              : 
    2349              :     /* check size */
    2350            9 :     if ((buf->size + sizeof(DltBufferHead) + buf->step_size) > buf->max_size)
    2351              :         /* max size reached, do not increase */
    2352              :         return DLT_RETURN_ERROR;
    2353              : 
    2354              :     /* allocate new buffer */
    2355            8 :     new_ptr = malloc(buf->size + sizeof(DltBufferHead) + buf->step_size);
    2356              : 
    2357            8 :     if (new_ptr == NULL) {
    2358            0 :         dlt_vlog(LOG_WARNING,
    2359              :                  "%s: Buffer: Cannot increase size because allocate %u bytes failed\n",
    2360              :                  __func__, buf->min_size);
    2361            0 :         return DLT_RETURN_ERROR;
    2362              :     }
    2363              : 
    2364              :     /* copy data */
    2365            8 :     head = (DltBufferHead *)buf->shm;
    2366              :     new_head = (DltBufferHead *)new_ptr;
    2367              : 
    2368            8 :     if (head->read < head->write) {
    2369            6 :         memcpy(new_ptr + sizeof(DltBufferHead), buf->mem + head->read, (size_t)(head->write - head->read));
    2370            6 :         new_head->read = 0;
    2371            6 :         new_head->write = head->write - head->read;
    2372            6 :         new_head->count = head->count;
    2373              :     }
    2374              :     else {
    2375            2 :         memcpy(new_ptr + sizeof(DltBufferHead), buf->mem + head->read, buf->size - (uint32_t)(head->read));
    2376            2 :         memcpy(new_ptr + sizeof(DltBufferHead) + buf->size - head->read, buf->mem, (size_t)head->write);
    2377            2 :         new_head->read = 0;
    2378            2 :         new_head->write = (int)(buf->size) + head->write - head->read;
    2379            2 :         new_head->count = head->count;
    2380              :     }
    2381              : 
    2382              :     /* free old data */
    2383            8 :     free(buf->shm);
    2384              : 
    2385              :     /* update data */
    2386            8 :     buf->shm = new_ptr;
    2387            8 :     buf->mem = new_ptr + sizeof(DltBufferHead);
    2388            8 :     buf->size += buf->step_size;
    2389              : 
    2390            8 :     dlt_vlog(LOG_DEBUG,
    2391              :              "%s: Buffer: Size increased to %u bytes with start address %lX\n",
    2392              :              __func__,
    2393              :              buf->size + (int32_t)sizeof(DltBufferHead),
    2394              :              (unsigned long)buf->mem);
    2395              : 
    2396            8 :     return DLT_RETURN_OK; /* OK */
    2397              : }
    2398              : 
    2399            9 : int dlt_buffer_minimize_size(DltBuffer *buf)
    2400              : {
    2401              :     unsigned char *new_ptr;
    2402              : 
    2403              :     /* catch null pointer */
    2404            9 :     if (buf == NULL) {
    2405            1 :         dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__);
    2406            1 :         return DLT_RETURN_WRONG_PARAMETER;
    2407              :     }
    2408              : 
    2409            8 :     if ((buf->size + sizeof(DltBufferHead)) == buf->min_size)
    2410              :         /* already minimized */
    2411              :         return DLT_RETURN_OK;
    2412              : 
    2413              :     /* allocate new buffer */
    2414            0 :     new_ptr = malloc(buf->min_size);
    2415              : 
    2416            0 :     if (new_ptr == NULL) {
    2417            0 :         dlt_vlog(LOG_WARNING,
    2418              :                  "%s: Buffer: Cannot set to min size of %u bytes\n",
    2419              :                  __func__, buf->min_size);
    2420            0 :         return DLT_RETURN_ERROR;
    2421              :     }
    2422              : 
    2423              :     /* free old data */
    2424            0 :     free(buf->shm);
    2425              : 
    2426              :     /* update data */
    2427            0 :     buf->shm = new_ptr;
    2428            0 :     buf->mem = new_ptr + sizeof(DltBufferHead);
    2429            0 :     buf->size = (uint32_t)(buf->min_size - sizeof(DltBufferHead));
    2430              : 
    2431              :     /* reset pointers and counters */
    2432            0 :     ((int *)(buf->shm))[0] = 0;  /* pointer to write memory */
    2433            0 :     ((int *)(buf->shm))[1] = 0;  /* pointer to read memory */
    2434            0 :     ((int *)(buf->shm))[2] = 0;  /* number of packets */
    2435              : 
    2436            0 :     dlt_vlog(LOG_DEBUG,
    2437              :              "%s: Buffer: Buffer minimized to Size %u bytes with start address %lX\n",
    2438              :              __func__, buf->size, (unsigned long)buf->mem);
    2439              : 
    2440              :     /* clear memory */
    2441            0 :     memset(buf->mem, 0, buf->size);
    2442              : 
    2443            0 :     return DLT_RETURN_OK; /* OK */
    2444              : }
    2445              : 
    2446            9 : int dlt_buffer_reset(DltBuffer *buf)
    2447              : {
    2448              :     /* catch null pointer */
    2449            9 :     if (buf == NULL) {
    2450            1 :         dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__);
    2451            1 :         return DLT_RETURN_WRONG_PARAMETER;
    2452              :     }
    2453              : 
    2454            8 :     dlt_vlog(LOG_WARNING,
    2455              :              "%s: Buffer: Buffer reset triggered. Size: %u, Start address: %lX\n",
    2456            8 :              __func__, buf->size, (unsigned long)buf->mem);
    2457              : 
    2458              :     /* reset pointers and counters */
    2459            8 :     ((int *)(buf->shm))[0] = 0;  /* pointer to write memory */
    2460            8 :     ((int *)(buf->shm))[1] = 0;  /* pointer to read memory */
    2461            8 :     ((int *)(buf->shm))[2] = 0;  /* number of packets */
    2462              : 
    2463              :     /* clear memory */
    2464            8 :     memset(buf->mem, 0, buf->size);
    2465              : 
    2466            8 :     return DLT_RETURN_OK; /* OK */
    2467              : }
    2468              : 
    2469        13775 : DltReturnValue dlt_buffer_push(DltBuffer *buf, const unsigned char *data, unsigned int size)
    2470              : {
    2471        13775 :     return dlt_buffer_push3(buf, data, size, 0, 0, 0, 0);
    2472              : }
    2473              : 
    2474        21543 : DltReturnValue dlt_buffer_push3(DltBuffer *buf,
    2475              :                      const unsigned char *data1,
    2476              :                      unsigned int size1,
    2477              :                      const unsigned char *data2,
    2478              :                      unsigned int size2,
    2479              :                      const unsigned char *data3,
    2480              :                      unsigned int size3)
    2481              : {
    2482              :     int free_size;
    2483              :     int write, read, count;
    2484              :     DltBufferBlockHead head;
    2485              : 
    2486              :     /* catch null pointer */
    2487        21543 :     if (buf == NULL)
    2488              :         return DLT_RETURN_WRONG_PARAMETER;
    2489              : 
    2490        21475 :     if (buf->shm == NULL) {
    2491              :         /* buffer not initialised */
    2492            0 :         dlt_vlog(LOG_ERR, "%s: Buffer: Buffer not initialized\n", __func__);
    2493            0 :         return DLT_RETURN_ERROR; /* ERROR */
    2494              :     }
    2495              : 
    2496              :     /* get current write pointer */
    2497        21475 :     write = ((int *)(buf->shm))[0];
    2498        21475 :     read = ((int *)(buf->shm))[1];
    2499        21475 :     count = ((int *)(buf->shm))[2];
    2500              : 
    2501              :     /* check pointers */
    2502        21475 :     if (((unsigned int)read > buf->size) || ((unsigned int)write > buf->size)) {
    2503            0 :         dlt_vlog(LOG_ERR,
    2504              :                  "%s: Buffer: Pointer out of range. Read: %d, Write: %d, Size: %u\n",
    2505              :                  __func__, read, write, buf->size);
    2506            0 :         dlt_buffer_reset(buf);
    2507            0 :         return DLT_RETURN_ERROR; /* ERROR */
    2508              :     }
    2509              : 
    2510              :     /* calculate free size */
    2511        21475 :     if (read > write)
    2512            0 :         free_size = read - write;
    2513        21475 :     else if (count && (write == read))
    2514              :         free_size = 0;
    2515              :     else
    2516        21475 :         free_size = (int)buf->size - write + read;
    2517              : 
    2518              :     /* check size */
    2519        21481 :     while (free_size < (int) (sizeof(DltBufferBlockHead) + size1 + size2 + size3)) {
    2520              :         /* try to increase size if possible */
    2521            6 :         if (dlt_buffer_increase_size(buf))
    2522              :             /* increase size is not possible */
    2523              :             /*dlt_log(LOG_ERR, "Buffer: Buffer is full\n"); */
    2524              :             return DLT_RETURN_ERROR; /* ERROR */
    2525              : 
    2526              :         /* update pointers */
    2527            6 :         write = ((int *)(buf->shm))[0];
    2528            6 :         read = ((int *)(buf->shm))[1];
    2529              : 
    2530              :             /* update free size */
    2531            6 :         if (read > write)
    2532            0 :             free_size = read - write;
    2533            6 :         else if (count && (write == read))
    2534              :             free_size = 0;
    2535              :         else
    2536            6 :             free_size = (int)((unsigned int)buf->size - (unsigned int)write + (unsigned int)read);
    2537              :     }
    2538              : 
    2539              :     /* set header */
    2540              :     strncpy(head.head, DLT_BUFFER_HEAD, 4);
    2541              :     head.head[3] = 0;
    2542        21475 :     head.status = 2;
    2543        21475 :     head.size = (int)(size1 + size2 + size3);
    2544              : 
    2545              :     /* write data */
    2546        21475 :     dlt_buffer_write_block(buf, &write, (unsigned char *)&head, sizeof(DltBufferBlockHead));
    2547              : 
    2548        21475 :     if (size1)
    2549        21475 :         dlt_buffer_write_block(buf, &write, data1, size1);
    2550              : 
    2551        21475 :     if (size2)
    2552         7702 :         dlt_buffer_write_block(buf, &write, data2, size2);
    2553              : 
    2554        21475 :     if (size3)
    2555         1877 :         dlt_buffer_write_block(buf, &write, data3, size3);
    2556              : 
    2557              :     /* update global shm pointers */
    2558        21475 :     ((int *)(buf->shm))[0] = write; /* set new write pointer */
    2559        21475 :     ((int *)(buf->shm))[2] += 1; /* increase counter */
    2560              : 
    2561        21475 :     return DLT_RETURN_OK; /* OK */
    2562              : 
    2563              : }
    2564              : 
    2565           64 : int dlt_buffer_get(DltBuffer *buf, unsigned char *data, int max_size, int delete)
    2566              : {
    2567              :     int used_size;
    2568              :     int write, read, count;
    2569           64 :     char head_compare[] = DLT_BUFFER_HEAD;
    2570              :     DltBufferBlockHead head;
    2571              : 
    2572              :     /* catch null pointer */
    2573           64 :     if (buf == NULL)
    2574              :         return DLT_RETURN_WRONG_PARAMETER;
    2575              : 
    2576           47 :     if (buf->shm == NULL) {
    2577              :         /* shm not initialised */
    2578            0 :         dlt_vlog(LOG_ERR, "%s: Buffer: SHM not initialized\n", __func__);
    2579            0 :         return DLT_RETURN_ERROR; /* ERROR */
    2580              :     }
    2581              : 
    2582              :     /* get current write pointer */
    2583           47 :     write = ((int *)(buf->shm))[0];
    2584           47 :     read = ((int *)(buf->shm))[1];
    2585           47 :     count = ((int *)(buf->shm))[2];
    2586              : 
    2587              :     /* check pointers */
    2588           47 :     if (((unsigned int)read > buf->size) || ((unsigned int)write > buf->size) || (count < 0)) {
    2589            3 :         dlt_vlog(LOG_ERR,
    2590              :                  "%s: Buffer: Pointer out of range. Read: %d, Write: %d, Count: %d, Size: %u\n",
    2591              :                  __func__, read, write, count, buf->size);
    2592            3 :         dlt_buffer_reset(buf);
    2593            3 :         return DLT_RETURN_ERROR; /* ERROR */
    2594              :     }
    2595              : 
    2596              :     /* check if data is in there */
    2597           44 :     if (count == 0) {
    2598           22 :         if (write != read) {
    2599            1 :             dlt_vlog(LOG_ERR,
    2600              :                      "%s: Buffer: SHM should be empty, but is not. Read: %d, Write: %d\n",
    2601              :                      __func__, read, write);
    2602            1 :             dlt_buffer_reset(buf);
    2603              :         }
    2604              : 
    2605           22 :         return DLT_RETURN_ERROR; /* ERROR */
    2606              :     }
    2607              : 
    2608              :     /* calculate used size */
    2609           22 :     if (write > read)
    2610           21 :         used_size = write - read;
    2611              :     else
    2612            1 :         used_size = (int)buf->size - read + write;
    2613              : 
    2614              :     /* first check size */
    2615           22 :     if (used_size < (int)(sizeof(DltBufferBlockHead))) {
    2616            1 :         dlt_vlog(LOG_ERR,
    2617              :                  "%s: Buffer: Used size is smaller than buffer block header size. Used size: %d\n",
    2618              :                  __func__, used_size);
    2619            1 :         dlt_buffer_reset(buf);
    2620            1 :         return DLT_RETURN_ERROR; /* ERROR */
    2621              :     }
    2622              : 
    2623              :     /* read header */
    2624           21 :     dlt_buffer_read_block(buf, &read, (unsigned char *)&head, sizeof(DltBufferBlockHead));
    2625              : 
    2626              :     /* check header */
    2627           21 :     if (memcmp((unsigned char *)(head.head), head_compare, sizeof(head_compare)) != 0) {
    2628            1 :         dlt_vlog(LOG_ERR, "%s: Buffer: Header head check failed\n", __func__);
    2629            1 :         dlt_buffer_reset(buf);
    2630            1 :         return DLT_RETURN_ERROR; /* ERROR */
    2631              :     }
    2632              : 
    2633           20 :     if (head.status != 2) {
    2634            0 :         dlt_vlog(LOG_ERR, "%s: Buffer: Header status check failed\n", __func__);
    2635            0 :         dlt_buffer_reset(buf);
    2636            0 :         return DLT_RETURN_ERROR; /* ERROR */
    2637              :     }
    2638              : 
    2639              :     /* second check size */
    2640           20 :     if (used_size < ((int)sizeof(DltBufferBlockHead) + head.size)) {
    2641            1 :         dlt_vlog(LOG_ERR,
    2642              :                  "%s: Buffer: Used size is smaller than buffer block header size And read header size. Used size: %d\n",
    2643              :                  __func__, used_size);
    2644            1 :         dlt_buffer_reset(buf);
    2645            1 :         return DLT_RETURN_ERROR; /* ERROR */
    2646              :     }
    2647              : 
    2648              :     /* third check size */
    2649           19 :     if (max_size && (head.size > max_size))
    2650            1 :         dlt_vlog(LOG_WARNING,
    2651              :                  "%s: Buffer: Max size is smaller than read header size. Max size: %d\n",
    2652              :                  __func__, max_size);
    2653              : 
    2654              :     /* nothing to do but data does not fit provided buffer */
    2655              : 
    2656           19 :     if ((data != NULL) && max_size) {
    2657              :         /* read data */
    2658           14 :         dlt_buffer_read_block(buf, &read, data, (unsigned int)head.size);
    2659              : 
    2660           14 :         if (delete)
    2661              :             /* update buffer pointers */
    2662            3 :             ((int *)(buf->shm))[1] = read; /* set new read pointer */
    2663              : 
    2664              :     }
    2665            5 :     else if (delete)
    2666              :     {
    2667            5 :         if ((unsigned int)(read + head.size) <= buf->size)
    2668            5 :             ((int *)(buf->shm))[1] = read + head.size;  /* set new read pointer */
    2669              :         else
    2670            0 :             ((int *)(buf->shm))[1] = read + head.size - (int)buf->size;  /* set new read pointer */
    2671              : 
    2672              :     }
    2673              : 
    2674            8 :     if (delete) {
    2675            8 :         ((int *)(buf->shm))[2] -= 1; /* decrease counter */
    2676              : 
    2677            8 :         if (((int *)(buf->shm))[2] == 0)
    2678              :             /* try to minimize size */
    2679            5 :             dlt_buffer_minimize_size(buf);
    2680              :     }
    2681              : 
    2682           19 :     return head.size; /* OK */
    2683              : }
    2684              : 
    2685            8 : int dlt_buffer_pull(DltBuffer *buf, unsigned char *data, int max_size)
    2686              : {
    2687            8 :     return dlt_buffer_get(buf, data, max_size, 1);
    2688              : }
    2689              : 
    2690           13 : int dlt_buffer_copy(DltBuffer *buf, unsigned char *data, int max_size)
    2691              : {
    2692           13 :     return dlt_buffer_get(buf, data, max_size, 0);
    2693              : }
    2694              : 
    2695            7 : int dlt_buffer_remove(DltBuffer *buf)
    2696              : {
    2697            7 :     return dlt_buffer_get(buf, 0, 0, 1);
    2698              : }
    2699              : 
    2700            2 : void dlt_buffer_info(DltBuffer *buf)
    2701              : {
    2702              :     /* check nullpointer */
    2703            2 :     if (buf == NULL) {
    2704            1 :         dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__);
    2705            1 :         return;
    2706              :     }
    2707              : 
    2708            1 :     dlt_vlog(LOG_DEBUG,
    2709              :              "Buffer: Available size: %u, Buffer: Buffer full start address: %lX, Buffer: Buffer start address: %lX\n",
    2710            1 :              buf->size, (unsigned long)buf->shm, (unsigned long)buf->mem);
    2711              : }
    2712              : 
    2713            2 : void dlt_buffer_status(DltBuffer *buf)
    2714              : {
    2715              :     int write, read, count;
    2716              : 
    2717              :     /* check nullpointer */
    2718            2 :     if (buf == NULL) {
    2719            1 :         dlt_vlog(LOG_WARNING, "%s: Wrong parameter: Null pointer\n", __func__);
    2720            1 :         return;
    2721              :     }
    2722              : 
    2723              :     /* check if buffer available */
    2724            1 :     if (buf->shm == NULL)
    2725              :         return;
    2726              : 
    2727            1 :     write = ((int *)(buf->shm))[0];
    2728            1 :     read = ((int *)(buf->shm))[1];
    2729            1 :     count = ((int *)(buf->shm))[2];
    2730              : 
    2731            1 :     dlt_vlog(LOG_DEBUG,
    2732              :              "Buffer: Write: %d, Read: %d, Count: %d\n",
    2733              :              write, read, count);
    2734              : }
    2735              : 
    2736            3 : uint32_t dlt_buffer_get_total_size(DltBuffer *buf)
    2737              : {
    2738              :     /* catch null pointer */
    2739            3 :     if (buf == NULL)
    2740              :         return (uint32_t)DLT_RETURN_WRONG_PARAMETER;
    2741              : 
    2742            2 :     return buf->max_size;
    2743              : }
    2744              : 
    2745         2503 : int dlt_buffer_get_used_size(DltBuffer *buf)
    2746              : {
    2747              :     int write, read, count;
    2748              : 
    2749              :     /* catch null pointer */
    2750         2503 :     if (buf == NULL)
    2751              :         return DLT_RETURN_WRONG_PARAMETER;
    2752              : 
    2753              :     /* check if buffer available */
    2754         2502 :     if (buf->shm == NULL)
    2755              :         return DLT_RETURN_OK;
    2756              : 
    2757         2502 :     write = ((int *)(buf->shm))[0];
    2758         2502 :     read = ((int *)(buf->shm))[1];
    2759         2502 :     count = ((int *)(buf->shm))[2];
    2760              : 
    2761         2502 :     if (count == 0)
    2762              :         return DLT_RETURN_OK;
    2763              : 
    2764         2501 :     if (write > read)
    2765         2501 :         return write - read;
    2766              : 
    2767            0 :     return (int)buf->size - read + write;
    2768              : }
    2769              : 
    2770         8522 : int dlt_buffer_get_message_count(DltBuffer *buf)
    2771              : {
    2772              :     /* catch null pointer */
    2773         8522 :     if (buf == NULL)
    2774              :         return DLT_RETURN_WRONG_PARAMETER;
    2775              : 
    2776              :     /* check if buffer available */
    2777         8522 :     if (buf->shm == NULL)
    2778              :         return DLT_RETURN_OK;
    2779              : 
    2780         8522 :     return ((int *)(buf->shm))[2];
    2781              : }
    2782              : 
    2783              : #if !defined (__WIN32__)
    2784              : 
    2785            0 : DltReturnValue dlt_setup_serial(int fd, speed_t speed)
    2786              : {
    2787              : #   if !defined (__WIN32__) && !defined(_MSC_VER)
    2788              :     struct termios config;
    2789              : 
    2790            0 :     if (isatty(fd) == 0)
    2791              :         return DLT_RETURN_ERROR;
    2792              : 
    2793            0 :     if (tcgetattr(fd, &config) < 0)
    2794              :         return DLT_RETURN_ERROR;
    2795              : 
    2796              :     /* Input flags - Turn off input processing
    2797              :      * convert break to null byte, no CR to NL translation,
    2798              :      * no NL to CR translation, don't mark parity errors or breaks
    2799              :      * no input parity check, don't strip high bit off,
    2800              :      * no XON/XOFF software flow control
    2801              :      */
    2802            0 :     config.c_iflag &= (tcflag_t)~(IGNBRK | BRKINT | ICRNL |
    2803              :                         INLCR | PARMRK | INPCK | ISTRIP | IXON);
    2804              : 
    2805              :     /* Output flags - Turn off output processing
    2806              :      * no CR to NL translation, no NL to CR-NL translation,
    2807              :      * no NL to CR translation, no column 0 CR suppression,
    2808              :      * no Ctrl-D suppression, no fill characters, no case mapping,
    2809              :      * no local output processing
    2810              :      *
    2811              :      * config.c_oflag &= ~(OCRNL | ONLCR | ONLRET |
    2812              :      *                     ONOCR | ONOEOT| OFILL | OLCUC | OPOST);
    2813              :      */
    2814            0 :     config.c_oflag = 0;
    2815              : 
    2816              :     /* No line processing:
    2817              :      * echo off, echo newline off, canonical mode off,
    2818              :      * extended input processing off, signal chars off
    2819              :      */
    2820            0 :     config.c_lflag &= (tcflag_t)~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
    2821              : 
    2822              :     /* Turn off character processing
    2823              :      * clear current char size mask, no parity checking,
    2824              :      * no output processing, force 8 bit input
    2825              :      */
    2826            0 :     config.c_cflag &= (tcflag_t)~(CSIZE | PARENB);
    2827            0 :     config.c_cflag |= CS8;
    2828              : 
    2829              :     /* One input byte is enough to return from read()
    2830              :      * Inter-character timer off
    2831              :      */
    2832            0 :     config.c_cc[VMIN] = 1;
    2833            0 :     config.c_cc[VTIME] = 0;
    2834              : 
    2835              :     /* Communication speed (simple version, using the predefined
    2836              :      * constants)
    2837              :      */
    2838            0 :     if ((cfsetispeed(&config, speed) < 0) || (cfsetospeed(&config, speed) < 0))
    2839            0 :         return DLT_RETURN_ERROR;
    2840              : 
    2841              :     /* Finally, apply the configuration
    2842              :      */
    2843            0 :     if (tcsetattr(fd, TCSAFLUSH, &config) < 0)
    2844              :         return DLT_RETURN_ERROR;
    2845              : 
    2846              :     return DLT_RETURN_OK;
    2847              : #   else
    2848              :     return DLT_RETURN_ERROR;
    2849              : #   endif
    2850              : }
    2851              : 
    2852            0 : speed_t dlt_convert_serial_speed(int baudrate)
    2853              : {
    2854              : #   if !defined (__WIN32__) && !defined(_MSC_VER) && !defined(__CYGWIN__)
    2855              :     speed_t ret;
    2856              : 
    2857            0 :     switch (baudrate) {
    2858              :     case  50:
    2859              :     {
    2860              :         ret = B50;
    2861              :         break;
    2862              :     }
    2863            0 :     case  75:
    2864              :     {
    2865              :         ret = B75;
    2866            0 :         break;
    2867              :     }
    2868            0 :     case  110:
    2869              :     {
    2870              :         ret = B110;
    2871            0 :         break;
    2872              :     }
    2873            0 :     case  134:
    2874              :     {
    2875              :         ret = B134;
    2876            0 :         break;
    2877              :     }
    2878            0 :     case  150:
    2879              :     {
    2880              :         ret = B150;
    2881            0 :         break;
    2882              :     }
    2883            0 :     case  200:
    2884              :     {
    2885              :         ret = B200;
    2886            0 :         break;
    2887              :     }
    2888            0 :     case  300:
    2889              :     {
    2890              :         ret = B300;
    2891            0 :         break;
    2892              :     }
    2893            0 :     case  600:
    2894              :     {
    2895              :         ret = B600;
    2896            0 :         break;
    2897              :     }
    2898            0 :     case  1200:
    2899              :     {
    2900              :         ret = B1200;
    2901            0 :         break;
    2902              :     }
    2903            0 :     case  1800:
    2904              :     {
    2905              :         ret = B1800;
    2906            0 :         break;
    2907              :     }
    2908            0 :     case  2400:
    2909              :     {
    2910              :         ret = B2400;
    2911            0 :         break;
    2912              :     }
    2913            0 :     case  4800:
    2914              :     {
    2915              :         ret = B4800;
    2916            0 :         break;
    2917              :     }
    2918            0 :     case  9600:
    2919              :     {
    2920              :         ret = B9600;
    2921            0 :         break;
    2922              :     }
    2923            0 :     case  19200:
    2924              :     {
    2925              :         ret = B19200;
    2926            0 :         break;
    2927              :     }
    2928            0 :     case  38400:
    2929              :     {
    2930              :         ret = B38400;
    2931            0 :         break;
    2932              :     }
    2933            0 :     case  57600:
    2934              :     {
    2935              :         ret = B57600;
    2936            0 :         break;
    2937              :     }
    2938              :     case  115200:
    2939              :     {
    2940              :         ret = B115200;
    2941              :         break;
    2942              :     }
    2943              : #      ifdef __linux__
    2944            0 :     case 230400:
    2945              :     {
    2946              :         ret = B230400;
    2947            0 :         break;
    2948              :     }
    2949            0 :     case 460800:
    2950              :     {
    2951              :         ret = B460800;
    2952            0 :         break;
    2953              :     }
    2954            0 :     case  500000:
    2955              :     {
    2956              :         ret = B500000;
    2957            0 :         break;
    2958              :     }
    2959            0 :     case  576000:
    2960              :     {
    2961              :         ret = B576000;
    2962            0 :         break;
    2963              :     }
    2964            0 :     case  921600:
    2965              :     {
    2966              :         ret = B921600;
    2967            0 :         break;
    2968              :     }
    2969            0 :     case  1000000:
    2970              :     {
    2971              :         ret = B1000000;
    2972            0 :         break;
    2973              :     }
    2974            0 :     case  1152000:
    2975              :     {
    2976              :         ret = B1152000;
    2977            0 :         break;
    2978              :     }
    2979            0 :     case  1500000:
    2980              :     {
    2981              :         ret = B1500000;
    2982            0 :         break;
    2983              :     }
    2984            0 :     case  2000000:
    2985              :     {
    2986              :         ret = B2000000;
    2987            0 :         break;
    2988              :     }
    2989              : #ifdef B2500000
    2990            0 :     case  2500000:
    2991              :     {
    2992              :         ret = B2500000;
    2993            0 :         break;
    2994              :     }
    2995              : #endif
    2996              : #ifdef B3000000
    2997            0 :     case  3000000:
    2998              :     {
    2999              :         ret = B3000000;
    3000            0 :         break;
    3001              :     }
    3002              : #endif
    3003              : #ifdef B3500000
    3004            0 :     case  3500000:
    3005              :     {
    3006              :         ret = B3500000;
    3007            0 :         break;
    3008              :     }
    3009              : #endif
    3010              : #ifdef B4000000
    3011            0 :     case  4000000:
    3012              :     {
    3013              :         ret = B4000000;
    3014            0 :         break;
    3015              :     }
    3016              : #endif
    3017              : #      endif /* __linux__ */
    3018              :     default:
    3019              :     {
    3020              :         ret = B115200;
    3021              :         break;
    3022              :     }
    3023              :     }
    3024              : 
    3025            0 :     return ret;
    3026              : #   else
    3027              :     return 0;
    3028              : #   endif
    3029              : }
    3030              : 
    3031              : #endif
    3032              : 
    3033           20 : void dlt_get_version(char *buf, size_t size)
    3034              : {
    3035           20 :     if ((buf == NULL) && (size > 0)) {
    3036            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
    3037            0 :         return;
    3038              :     }
    3039              : 
    3040              : /* Clang does not like these macros, because they are not reproducable */
    3041              : #pragma GCC diagnostic push
    3042              : #pragma GCC diagnostic ignored "-Wdate-time"
    3043              :     snprintf(buf,
    3044              :              size,
    3045              :              "DLT Package Version: %s %s, Package Revision: %s, build on %s %s\n%s %s %s %s\n",
    3046              :              _DLT_PACKAGE_VERSION,
    3047              :              _DLT_PACKAGE_VERSION_STATE,
    3048              :              _DLT_PACKAGE_REVISION,
    3049              :              __DATE__,
    3050              :              __TIME__,
    3051              :              _DLT_SYSTEMD_ENABLE,
    3052              :              _DLT_SYSTEMD_WATCHDOG_ENABLE,
    3053              :              _DLT_TEST_ENABLE,
    3054              :              _DLT_SHM_ENABLE);
    3055              : #pragma GCC diagnostic pop
    3056              : }
    3057              : 
    3058            8 : void dlt_get_major_version(char *buf, size_t size)
    3059              : {
    3060            8 :     if ((buf == NULL) && (size > 0)) {
    3061            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
    3062            0 :         return;
    3063              :     }
    3064              : 
    3065              :     snprintf(buf, size, "%s", _DLT_PACKAGE_MAJOR_VERSION);
    3066              : }
    3067              : 
    3068            8 : void dlt_get_minor_version(char *buf, size_t size)
    3069              : {
    3070            8 :     if ((buf == NULL) && (size > 0)) {
    3071            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
    3072            0 :         return;
    3073              :     }
    3074              : 
    3075              :     snprintf(buf, size, "%s", _DLT_PACKAGE_MINOR_VERSION);
    3076              : }
    3077              : 
    3078              : 
    3079         6300 : uint32_t dlt_uptime(void)
    3080              : {
    3081              : 
    3082              : #if defined (__WIN32__) || defined(_MSC_VER)
    3083              : 
    3084              :     return (uint32_t)(GetTickCount() * 10); /* GetTickCount() return DWORD */
    3085              : 
    3086              : #else
    3087              :     struct timespec ts;
    3088              : 
    3089         6300 :     if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
    3090         6300 :         return (uint32_t)ts.tv_sec * 10000 + (uint32_t)ts.tv_nsec / 100000; /* in 0.1 ms = 100 us */
    3091              :     else
    3092              :         return 0;
    3093              : 
    3094              : #endif
    3095              : 
    3096              : }
    3097              : 
    3098          328 : DltReturnValue dlt_message_print_header(DltMessage *message, char *text, uint32_t size, int verbose)
    3099              : {
    3100          328 :     if ((message == NULL) || (text == NULL))
    3101              :         return DLT_RETURN_WRONG_PARAMETER;
    3102              : 
    3103          316 :     if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK)
    3104              :         return DLT_RETURN_ERROR;
    3105          316 :     dlt_user_printf("%s\n", text);
    3106              : 
    3107          316 :     return DLT_RETURN_OK;
    3108              : }
    3109              : 
    3110          328 : DltReturnValue dlt_message_print_hex(DltMessage *message, char *text, uint32_t size, int verbose)
    3111              : {
    3112          328 :     if ((message == NULL) || (text == NULL))
    3113              :         return DLT_RETURN_WRONG_PARAMETER;
    3114              : 
    3115          316 :     if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK)
    3116              :         return DLT_RETURN_ERROR;
    3117          316 :     dlt_user_printf("%s ", text);
    3118              : 
    3119          316 :     if (dlt_message_payload(message, text, size, DLT_OUTPUT_HEX, verbose) < DLT_RETURN_OK)
    3120              :         return DLT_RETURN_ERROR;
    3121          316 :     dlt_user_printf("[%s]\n", text);
    3122              : 
    3123          316 :     return DLT_RETURN_OK;
    3124              : }
    3125              : 
    3126          328 : DltReturnValue dlt_message_print_ascii(DltMessage *message, char *text, uint32_t size, int verbose)
    3127              : {
    3128          328 :     if ((message == NULL) || (text == NULL))
    3129              :         return DLT_RETURN_WRONG_PARAMETER;
    3130              : 
    3131          316 :     if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK)
    3132              :         return DLT_RETURN_ERROR;
    3133          316 :     dlt_user_printf("%s ", text);
    3134              : 
    3135          316 :     if (dlt_message_payload(message, text, size, DLT_OUTPUT_ASCII, verbose) < DLT_RETURN_OK)
    3136              :         return DLT_RETURN_ERROR;
    3137          316 :     dlt_user_printf("[%s]\n", text);
    3138              : 
    3139          316 :     return DLT_RETURN_OK;
    3140              : }
    3141              : 
    3142          328 : DltReturnValue dlt_message_print_mixed_plain(DltMessage *message, char *text, uint32_t size, int verbose)
    3143              : {
    3144          328 :     if ((message == NULL) || (text == NULL))
    3145              :         return DLT_RETURN_WRONG_PARAMETER;
    3146              : 
    3147          316 :     if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK)
    3148              :         return DLT_RETURN_ERROR;
    3149          316 :     dlt_user_printf("%s \n", text);
    3150              : 
    3151          316 :     if (dlt_message_payload(message, text, size, DLT_OUTPUT_MIXED_FOR_PLAIN, verbose) < DLT_RETURN_OK)
    3152              :         return DLT_RETURN_ERROR;
    3153          316 :     dlt_user_printf("[%s]\n", text);
    3154              : 
    3155          316 :     return DLT_RETURN_OK;
    3156              : }
    3157              : 
    3158          328 : DltReturnValue dlt_message_print_mixed_html(DltMessage *message, char *text, uint32_t size, int verbose)
    3159              : {
    3160          328 :     if ((message == NULL) || (text == NULL))
    3161              :         return DLT_RETURN_WRONG_PARAMETER;
    3162              : 
    3163          316 :     if (dlt_message_header(message, text, size, verbose) < DLT_RETURN_OK)
    3164              :         return DLT_RETURN_ERROR;
    3165          316 :     dlt_user_printf("%s \n", text);
    3166              : 
    3167          316 :     if (dlt_message_payload(message, text, size, DLT_OUTPUT_MIXED_FOR_HTML, verbose) < DLT_RETURN_OK)
    3168              :         return DLT_RETURN_ERROR;
    3169              : 
    3170          316 :     dlt_user_printf("[%s]\n", text);
    3171              : 
    3172          316 :     return DLT_RETURN_OK;
    3173              : }
    3174              : 
    3175         2771 : DltReturnValue dlt_message_argument_print(DltMessage *msg,
    3176              :                                           uint32_t type_info,
    3177              :                                           uint8_t **ptr,
    3178              :                                           int32_t *datalength,
    3179              :                                           char *text,
    3180              :                                           size_t textlength,
    3181              :                                           int byteLength,
    3182              :                                           int __attribute__((unused)) verbose)
    3183              : {
    3184              :     /* check null pointers */
    3185         2771 :     if ((msg == NULL) || (ptr == NULL) || (datalength == NULL) || (text == NULL))
    3186              :         return DLT_RETURN_WRONG_PARAMETER;
    3187              : 
    3188              :     uint16_t length = 0, length2 = 0, length3 = 0;
    3189              : 
    3190              :     uint8_t value8u = 0;
    3191              :     uint16_t value16u = 0, value16u_tmp = 0;
    3192              :     uint32_t value32u = 0, value32u_tmp = 0;
    3193              :     uint64_t value64u = 0, value64u_tmp = 0;
    3194              : 
    3195              :     int8_t value8i = 0;
    3196              :     int16_t value16i = 0, value16i_tmp = 0;
    3197              :     int32_t value32i = 0, value32i_tmp = 0;
    3198              :     int64_t value64i = 0, value64i_tmp = 0;
    3199              : 
    3200         2756 :     float32_t value32f = 0, value32f_tmp = 0;
    3201         2756 :     int32_t value32f_tmp_int32i = 0, value32f_tmp_int32i_swaped = 0;
    3202         2756 :     float64_t value64f = 0, value64f_tmp = 0;
    3203         2756 :     int64_t value64f_tmp_int64i = 0, value64f_tmp_int64i_swaped = 0;
    3204              : 
    3205              :     uint32_t quantisation_tmp = 0;
    3206              : 
    3207              :     // pointer to the value string
    3208              :     char* value_text = text;
    3209              :     // pointer to the "unit" attribute string, if there is one (only for *INT and FLOAT*)
    3210              :     const uint8_t* unit_text_src = NULL;
    3211              :     // length of the "unit" attribute string, if there is one (only for *INT and FLOAT*)
    3212              :     size_t unit_text_len = 0;
    3213              : 
    3214              :     /* apparently this makes no sense but needs to be done to prevent compiler warning.
    3215              :      * This variable is only written by DLT_MSG_READ_VALUE macro in if (type_info & DLT_TYPE_INFO_FIXP)
    3216              :      * case but never read anywhere */
    3217              :     quantisation_tmp += quantisation_tmp;
    3218              : 
    3219         2756 :     if ((type_info & DLT_TYPE_INFO_STRG) &&
    3220         1159 :         (((type_info & DLT_TYPE_INFO_SCOD) == DLT_SCOD_ASCII) || ((type_info & DLT_TYPE_INFO_SCOD) == DLT_SCOD_UTF8))) {
    3221              :         /* string type or utf8-encoded string type */
    3222         1159 :         if (byteLength < 0) {
    3223         1159 :             DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3224              : 
    3225         1159 :             if ((*datalength) < 0)
    3226              :                 return DLT_RETURN_ERROR;
    3227              : 
    3228         1159 :             length = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3229              :         }
    3230              :         else {
    3231            0 :             length = (uint16_t)byteLength;
    3232              :         }
    3233              : 
    3234         1159 :         if (type_info & DLT_TYPE_INFO_VARI) {
    3235            0 :             DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3236              : 
    3237            0 :             if ((*datalength) < 0)
    3238              :                 return DLT_RETURN_ERROR;
    3239              : 
    3240            0 :             length2 = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3241              : 
    3242            0 :             if ((*datalength) < length2)
    3243              :                 return DLT_RETURN_ERROR;
    3244              : 
    3245            0 :             if (print_with_attributes) {
    3246              :                 // Print "name" attribute, if we have one with non-zero size.
    3247            0 :                 if (length2 > 1) {
    3248            0 :                     snprintf(text, (size_t)textlength, "%s:", *ptr);
    3249            0 :                     value_text += length2+1-1;  // +1 for ":" and -1 for NUL
    3250            0 :                     textlength -= (size_t)(length2+1-1);
    3251              :                 }
    3252              :             }
    3253              : 
    3254            0 :             *ptr += length2;
    3255            0 :             *datalength -= length2;
    3256              :         }
    3257              : 
    3258         1159 :         DLT_MSG_READ_STRING(value_text, *ptr, *datalength, textlength, length);
    3259              : 
    3260         1159 :         if ((*datalength) < 0)
    3261              :             return DLT_RETURN_ERROR;
    3262              :     }
    3263         1597 :     else if (type_info & DLT_TYPE_INFO_BOOL)
    3264              :     {
    3265              :         /* Boolean type */
    3266          112 :         if (type_info & DLT_TYPE_INFO_VARI) {
    3267            0 :             DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3268              : 
    3269            0 :             if ((*datalength) < 0)
    3270              :                 return DLT_RETURN_ERROR;
    3271              : 
    3272            0 :             length2 = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3273              : 
    3274            0 :             if ((*datalength) < length2)
    3275              :                 return DLT_RETURN_ERROR;
    3276              : 
    3277            0 :             if (print_with_attributes) {
    3278              :                 // Print "name" attribute, if we have one with non-zero size.
    3279            0 :                 if (length2 > 1) {
    3280            0 :                     snprintf(text, (size_t)textlength, "%s:", *ptr);
    3281            0 :                     value_text += length2+1-1;  // +1 for ":" and -1 for NUL
    3282            0 :                     textlength -= (size_t)(length2+1-2);
    3283              :                 }
    3284              :             }
    3285              : 
    3286            0 :             *ptr += length2;
    3287            0 :             *datalength -= length2;
    3288              :         }
    3289              : 
    3290              :         value8u = 0;
    3291          112 :         DLT_MSG_READ_VALUE(value8u, *ptr, *datalength, uint8_t); /* No endian conversion necessary */
    3292              : 
    3293          112 :         if ((*datalength) < 0)
    3294              :             return DLT_RETURN_ERROR;
    3295              : 
    3296          110 :         snprintf(value_text, textlength, "%d", value8u);
    3297              :     }
    3298         1485 :     else if ((type_info & DLT_TYPE_INFO_UINT) && (DLT_SCOD_BIN == (type_info & DLT_TYPE_INFO_SCOD)))
    3299              :     {
    3300            0 :         if (DLT_TYLE_8BIT == (type_info & DLT_TYPE_INFO_TYLE)) {
    3301            0 :             DLT_MSG_READ_VALUE(value8u, *ptr, *datalength, uint8_t); /* No endian conversion necessary */
    3302              : 
    3303            0 :             if ((*datalength) < 0)
    3304            0 :                 return DLT_RETURN_ERROR;
    3305              : 
    3306            0 :             char binary[10] = { '\0' }; /* e.g.: "0b1100 0010" */
    3307              :             int i;
    3308              : 
    3309            0 :             for (i = (1 << 7); i > 0; i >>= 1) {
    3310            0 :                 if ((1 << 3) == i)
    3311              :                     strcat(binary, " ");
    3312              : 
    3313            0 :                 strcat(binary, (i == (value8u & i)) ? "1" : "0");
    3314              :             }
    3315              : 
    3316              :             snprintf(value_text, textlength, "0b%s", binary);
    3317              :         }
    3318              : 
    3319            0 :         if (DLT_TYLE_16BIT == (type_info & DLT_TYPE_INFO_TYLE)) {
    3320            0 :             DLT_MSG_READ_VALUE(value16u, *ptr, *datalength, uint16_t);
    3321              : 
    3322            0 :             if ((*datalength) < 0)
    3323            0 :                 return DLT_RETURN_ERROR;
    3324              : 
    3325            0 :             char binary[20] = { '\0' }; /* e.g.: "0b1100 0010 0011 0110" */
    3326              :             int i;
    3327              : 
    3328            0 :             for (i = (1 << 15); i > 0; i >>= 1) {
    3329            0 :                 if (((1 << 3) == i) || ((1 << 7) == i) || ((1 << 11) == i))
    3330              :                     strcat(binary, " ");
    3331              : 
    3332            0 :                 strcat(binary, (i == (value16u & i)) ? "1" : "0");
    3333              :             }
    3334              : 
    3335              :             snprintf(value_text, textlength, "0b%s", binary);
    3336              :         }
    3337              :     }
    3338         1485 :     else if ((type_info & DLT_TYPE_INFO_UINT) && (DLT_SCOD_HEX == (type_info & DLT_TYPE_INFO_SCOD)))
    3339              :     {
    3340            0 :         if (DLT_TYLE_8BIT == (type_info & DLT_TYPE_INFO_TYLE)) {
    3341            0 :             DLT_MSG_READ_VALUE(value8u, *ptr, *datalength, uint8_t); /* No endian conversion necessary */
    3342              : 
    3343            0 :             if ((*datalength) < 0)
    3344              :                 return DLT_RETURN_ERROR;
    3345              : 
    3346            0 :             snprintf(value_text, textlength, "0x%02x", value8u);
    3347              :         }
    3348              : 
    3349            0 :         if (DLT_TYLE_16BIT == (type_info & DLT_TYPE_INFO_TYLE)) {
    3350            0 :             DLT_MSG_READ_VALUE(value16u, *ptr, *datalength, uint16_t);
    3351              : 
    3352            0 :             if ((*datalength) < 0)
    3353              :                 return DLT_RETURN_ERROR;
    3354              : 
    3355            0 :             snprintf(value_text, textlength, "0x%04x", value16u);
    3356              :         }
    3357              : 
    3358            0 :         if (DLT_TYLE_32BIT == (type_info & DLT_TYPE_INFO_TYLE)) {
    3359            0 :             DLT_MSG_READ_VALUE(value32u, *ptr, *datalength, uint32_t);
    3360              : 
    3361            0 :             if ((*datalength) < 0)
    3362              :                 return DLT_RETURN_ERROR;
    3363              : 
    3364              :             snprintf(value_text, textlength, "0x%08x", value32u);
    3365              :         }
    3366              : 
    3367            0 :         if (DLT_TYLE_64BIT == (type_info & DLT_TYPE_INFO_TYLE)) {
    3368            0 :             *ptr += 4;
    3369            0 :             DLT_MSG_READ_VALUE(value32u, *ptr, *datalength, uint32_t);
    3370              : 
    3371            0 :             if ((*datalength) < 0)
    3372              :                 return DLT_RETURN_ERROR;
    3373              : 
    3374              :             snprintf(value_text, textlength, "0x%08x", value32u);
    3375            0 :             *ptr -= 8;
    3376            0 :             DLT_MSG_READ_VALUE(value32u, *ptr, *datalength, uint32_t);
    3377              : 
    3378            0 :             if ((*datalength) < 0)
    3379              :                 return DLT_RETURN_ERROR;
    3380              : 
    3381            0 :             snprintf(value_text + strlen(value_text), textlength - strlen(value_text), "%08x", value32u);
    3382            0 :             *ptr += 4;
    3383              :         }
    3384              :     }
    3385         1485 :     else if ((type_info & DLT_TYPE_INFO_SINT) || (type_info & DLT_TYPE_INFO_UINT))
    3386              :     {
    3387              :         /* signed or unsigned argument received */
    3388         1358 :         if (type_info & DLT_TYPE_INFO_VARI) {
    3389            0 :             DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3390              : 
    3391            0 :             if ((*datalength) < 0)
    3392              :                 return DLT_RETURN_ERROR;
    3393              : 
    3394            0 :             length2 = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3395            0 :             DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3396              : 
    3397            0 :             if ((*datalength) < 0)
    3398              :                 return DLT_RETURN_ERROR;
    3399              : 
    3400            0 :             length3 = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3401              : 
    3402            0 :             if ((*datalength) < length2)
    3403              :                 return DLT_RETURN_ERROR;
    3404              : 
    3405            0 :             if (print_with_attributes) {
    3406              :                 // Print "name" attribute, if we have one with non-zero size.
    3407            0 :                 if (length2 > 1) {
    3408            0 :                     snprintf(text, (size_t)textlength, "%s:", *ptr);
    3409            0 :                     value_text += length2+1-1;  // +1 for ":", and -1 for nul
    3410            0 :                     textlength -= (size_t)(length2+1-1);
    3411              :                 }
    3412              :             }
    3413              : 
    3414            0 :             *ptr += length2;
    3415            0 :             *datalength -= length2;
    3416              : 
    3417            0 :             if ((*datalength) < length3)
    3418              :                 return DLT_RETURN_ERROR;
    3419              : 
    3420              :             // We want to add the "unit" attribute only after the value, so remember its pointer and length here.
    3421              :             unit_text_src = *ptr;
    3422            0 :             unit_text_len = length3;
    3423              : 
    3424            0 :             *ptr += length3;
    3425            0 :             *datalength -= length3;
    3426              :         }
    3427              : 
    3428         1358 :         if (type_info & DLT_TYPE_INFO_FIXP) {
    3429            0 :             DLT_MSG_READ_VALUE(quantisation_tmp, *ptr, *datalength, uint32_t);
    3430              : 
    3431            0 :             if ((*datalength) < 0)
    3432              :                 return DLT_RETURN_ERROR;
    3433              : 
    3434            0 :             switch (type_info & DLT_TYPE_INFO_TYLE) {
    3435            0 :             case DLT_TYLE_8BIT:
    3436              :             case DLT_TYLE_16BIT:
    3437              :             case DLT_TYLE_32BIT:
    3438              :             {
    3439            0 :                 if ((*datalength) < 4)
    3440              :                     return DLT_RETURN_ERROR;
    3441              : 
    3442            0 :                 *ptr += 4;
    3443            0 :                 *datalength -= 4;
    3444            0 :                 break;
    3445              :             }
    3446            0 :             case DLT_TYLE_64BIT:
    3447              :             {
    3448            0 :                 if ((*datalength) < 8)
    3449              :                     return DLT_RETURN_ERROR;
    3450              : 
    3451            0 :                 *ptr += 8;
    3452            0 :                 *datalength -= 8;
    3453            0 :                 break;
    3454              :             }
    3455            0 :             case DLT_TYLE_128BIT:
    3456              :             {
    3457            0 :                 if ((*datalength) < 16)
    3458              :                     return DLT_RETURN_ERROR;
    3459              : 
    3460            0 :                 *ptr += 16;
    3461            0 :                 *datalength -= 16;
    3462            0 :                 break;
    3463              :             }
    3464              :             default:
    3465              :             {
    3466              :                 return DLT_RETURN_ERROR;
    3467              :             }
    3468              :             }
    3469              :         }
    3470              : 
    3471         1358 :         switch (type_info & DLT_TYPE_INFO_TYLE) {
    3472           14 :         case DLT_TYLE_8BIT:
    3473              :         {
    3474           14 :             if (type_info & DLT_TYPE_INFO_SINT) {
    3475              :                 value8i = 0;
    3476            7 :                 DLT_MSG_READ_VALUE(value8i, *ptr, *datalength, int8_t);  /* No endian conversion necessary */
    3477              : 
    3478            7 :                 if ((*datalength) < 0)
    3479              :                     return DLT_RETURN_ERROR;
    3480              : 
    3481            7 :                 snprintf(value_text, (size_t)textlength, "%d", value8i);
    3482              :             }
    3483              :             else {
    3484              :                 value8u = 0;
    3485            7 :                 DLT_MSG_READ_VALUE(value8u, *ptr, *datalength, uint8_t);  /* No endian conversion necessary */
    3486              : 
    3487            7 :                 if ((*datalength) < 0)
    3488              :                     return DLT_RETURN_ERROR;
    3489              : 
    3490            7 :                 snprintf(value_text, (size_t)textlength, "%d", value8u);
    3491              :             }
    3492              : 
    3493              :             break;
    3494              :         }
    3495           21 :         case DLT_TYLE_16BIT:
    3496              :         {
    3497           21 :             if (type_info & DLT_TYPE_INFO_SINT) {
    3498              :                 value16i = 0;
    3499              :                 value16i_tmp = 0;
    3500            7 :                 DLT_MSG_READ_VALUE(value16i_tmp, *ptr, *datalength, int16_t);
    3501              : 
    3502            7 :                 if ((*datalength) < 0)
    3503              :                     return DLT_RETURN_ERROR;
    3504              : 
    3505            7 :                 value16i = (int16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16i_tmp);
    3506            7 :                 snprintf(value_text, (size_t)textlength, "%hd", value16i);
    3507              :             }
    3508              :             else {
    3509              :                 value16u = 0;
    3510              :                 value16u_tmp = 0;
    3511           14 :                 DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3512              : 
    3513           14 :                 if ((*datalength) < 0)
    3514              :                     return DLT_RETURN_ERROR;
    3515              : 
    3516           14 :                 value16u = (uint16_t) DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3517           14 :                 snprintf(value_text, (size_t)textlength, "%hu", value16u);
    3518              :             }
    3519              : 
    3520              :             break;
    3521              :         }
    3522         1309 :         case DLT_TYLE_32BIT:
    3523              :         {
    3524         1309 :             if (type_info & DLT_TYPE_INFO_SINT) {
    3525              :                 value32i = 0;
    3526              :                 value32i_tmp = 0;
    3527          287 :                 DLT_MSG_READ_VALUE(value32i_tmp, *ptr, *datalength, int32_t);
    3528              : 
    3529          287 :                 if ((*datalength) < 0)
    3530              :                     return DLT_RETURN_ERROR;
    3531              : 
    3532          287 :                 value32i = (int32_t) DLT_ENDIAN_GET_32(msg->standardheader->htyp, (uint32_t)value32i_tmp);
    3533              :                 snprintf(value_text, (size_t)textlength, "%d", value32i);
    3534              :             }
    3535              :             else {
    3536              :                 value32u = 0;
    3537              :                 value32u_tmp = 0;
    3538         1022 :                 DLT_MSG_READ_VALUE(value32u_tmp, *ptr, *datalength, uint32_t);
    3539              : 
    3540         1022 :                 if ((*datalength) < 0)
    3541              :                     return DLT_RETURN_ERROR;
    3542              : 
    3543         1022 :                 value32u = DLT_ENDIAN_GET_32(msg->standardheader->htyp, value32u_tmp);
    3544              :                 snprintf(value_text, (size_t)textlength, "%u", value32u);
    3545              :             }
    3546              : 
    3547              :             break;
    3548              :         }
    3549           14 :         case DLT_TYLE_64BIT:
    3550              :         {
    3551           14 :             if (type_info & DLT_TYPE_INFO_SINT) {
    3552              :                 value64i = 0;
    3553              :                 value64i_tmp = 0;
    3554            7 :                 DLT_MSG_READ_VALUE(value64i_tmp, *ptr, *datalength, int64_t);
    3555              : 
    3556            7 :                 if ((*datalength) < 0)
    3557              :                     return DLT_RETURN_ERROR;
    3558              : 
    3559            7 :                 value64i = (int64_t) DLT_ENDIAN_GET_64(msg->standardheader->htyp, (uint64_t)value64i_tmp);
    3560              :     #if defined (__WIN32__) && !defined(_MSC_VER)
    3561              :                 snprintf(value_text, (size_t)textlength, "%I64d", value64i);
    3562              :     #else
    3563              :                 snprintf(value_text, (size_t)textlength, "%" PRId64, value64i);
    3564              :     #endif
    3565              :             }
    3566              :             else {
    3567              :                 value64u = 0;
    3568              :                 value64u_tmp = 0;
    3569            7 :                 DLT_MSG_READ_VALUE(value64u_tmp, *ptr, *datalength, uint64_t);
    3570              : 
    3571            7 :                 if ((*datalength) < 0)
    3572              :                     return DLT_RETURN_ERROR;
    3573              : 
    3574            7 :                 value64u = DLT_ENDIAN_GET_64(msg->standardheader->htyp, value64u_tmp);
    3575              :     #if defined (__WIN32__) && !defined(_MSC_VER)
    3576              :                 snprintf(value_text, textlength, "%I64u", value64u);
    3577              :     #else
    3578              :                 snprintf(value_text, textlength, "%" PRIu64, value64u);
    3579              :     #endif
    3580              :             }
    3581              : 
    3582              :             break;
    3583              :         }
    3584            0 :         case DLT_TYLE_128BIT:
    3585              :         {
    3586            0 :             if (*datalength >= 16)
    3587            0 :                 dlt_print_hex_string(value_text, (int) textlength, *ptr, 16);
    3588              : 
    3589            0 :             if ((*datalength) < 16)
    3590              :                 return DLT_RETURN_ERROR;
    3591              : 
    3592            0 :             *ptr += 16;
    3593            0 :             *datalength -= 16;
    3594            0 :             break;
    3595              :         }
    3596              :         default:
    3597              :         {
    3598              :             return DLT_RETURN_ERROR;
    3599              :         }
    3600              :         }
    3601              :     }
    3602          127 :     else if (type_info & DLT_TYPE_INFO_FLOA)
    3603              :     {
    3604              :         /* float data argument */
    3605           14 :         if (type_info & DLT_TYPE_INFO_VARI) {
    3606            0 :             DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3607              : 
    3608            0 :             if ((*datalength) < 0)
    3609              :                 return DLT_RETURN_ERROR;
    3610              : 
    3611            0 :             length2 = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3612            0 :             DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3613              : 
    3614            0 :             if ((*datalength) < 0)
    3615              :                 return DLT_RETURN_ERROR;
    3616              : 
    3617            0 :             length3 = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3618              : 
    3619            0 :             if ((*datalength) < length2)
    3620              :                 return DLT_RETURN_ERROR;
    3621              : 
    3622            0 :             if (print_with_attributes) {
    3623              :                 // Print "name" attribute, if we have one with non-zero size.
    3624            0 :                 if (length2 > 1) {
    3625            0 :                     snprintf(text, textlength, "%s:", *ptr);
    3626            0 :                     value_text += length2+1-1;  // +1 for ":" and -1 for NUL
    3627            0 :                     textlength -= (size_t)length2+1-1;
    3628              :                 }
    3629              :             }
    3630              : 
    3631            0 :             *ptr += length2;
    3632            0 :             *datalength -= length2;
    3633              : 
    3634            0 :             if ((*datalength) < length3)
    3635              :                 return DLT_RETURN_ERROR;
    3636              : 
    3637              :             // We want to add the "unit" attribute only after the value, so remember its pointer and length here.
    3638              :             unit_text_src = *ptr;
    3639            0 :             unit_text_len = length3;
    3640              : 
    3641            0 :             *ptr += length3;
    3642            0 :             *datalength -= length3;
    3643              :         }
    3644              : 
    3645           14 :         switch (type_info & DLT_TYPE_INFO_TYLE) {
    3646            0 :         case DLT_TYLE_8BIT:
    3647              :         {
    3648            0 :             if (*datalength >= 1)
    3649            0 :                 dlt_print_hex_string(value_text, (int) textlength, *ptr, 1);
    3650              : 
    3651            0 :             if ((*datalength) < 1)
    3652              :                 return DLT_RETURN_ERROR;
    3653              : 
    3654            0 :             *ptr += 1;
    3655            0 :             *datalength -= 1;
    3656            0 :             break;
    3657              :         }
    3658            0 :         case DLT_TYLE_16BIT:
    3659              :         {
    3660            0 :             if (*datalength >= 2)
    3661            0 :                 dlt_print_hex_string(value_text, (int) textlength, *ptr, 2);
    3662              : 
    3663            0 :             if ((*datalength) < 2)
    3664              :                 return DLT_RETURN_ERROR;
    3665              : 
    3666            0 :             *ptr += 2;
    3667            0 :             *datalength -= 2;
    3668            0 :             break;
    3669              :         }
    3670              :         case DLT_TYLE_32BIT:
    3671              :         {
    3672              :             if (sizeof(float32_t) == 4) {
    3673              :                 value32f = 0;
    3674              :                 value32f_tmp = 0;
    3675              :                 value32f_tmp_int32i = 0;
    3676              :                 value32f_tmp_int32i_swaped = 0;
    3677            7 :                 DLT_MSG_READ_VALUE(value32f_tmp, *ptr, *datalength, float32_t);
    3678              : 
    3679            7 :                 if ((*datalength) < 0)
    3680              :                     return DLT_RETURN_ERROR;
    3681              : 
    3682              :                 memcpy(&value32f_tmp_int32i, &value32f_tmp, sizeof(float32_t));
    3683              :                 value32f_tmp_int32i_swaped =
    3684            7 :                     (int32_t) DLT_ENDIAN_GET_32(msg->standardheader->htyp, (uint32_t)value32f_tmp_int32i);
    3685              :                 memcpy(&value32f, &value32f_tmp_int32i_swaped, sizeof(float32_t));
    3686            7 :                 snprintf(value_text, textlength, "%g", value32f);
    3687              :             }
    3688              :             else {
    3689              :                 dlt_log(LOG_ERR, "Invalid size of float32_t\n");
    3690              :                 return DLT_RETURN_ERROR;
    3691              :             }
    3692              : 
    3693              :             break;
    3694              :         }
    3695              :         case DLT_TYLE_64BIT:
    3696              :         {
    3697              :             if (sizeof(float64_t) == 8) {
    3698              :                 value64f = 0;
    3699              :                 value64f_tmp = 0;
    3700              :                 value64f_tmp_int64i = 0;
    3701              :                 value64f_tmp_int64i_swaped = 0;
    3702            7 :                 DLT_MSG_READ_VALUE(value64f_tmp, *ptr, *datalength, float64_t);
    3703              : 
    3704            7 :                 if ((*datalength) < 0)
    3705              :                     return DLT_RETURN_ERROR;
    3706              : 
    3707              :                 memcpy(&value64f_tmp_int64i, &value64f_tmp, sizeof(float64_t));
    3708              :                 value64f_tmp_int64i_swaped =
    3709            7 :                     (int64_t) DLT_ENDIAN_GET_64(msg->standardheader->htyp, (uint64_t)value64f_tmp_int64i);
    3710              :                 memcpy(&value64f, &value64f_tmp_int64i_swaped, sizeof(float64_t));
    3711              : #ifdef __arm__
    3712              :                 snprintf(value_text, textlength, "ILLEGAL");
    3713              : #else
    3714              :                 snprintf(value_text, textlength, "%g", value64f);
    3715              : #endif
    3716              :             }
    3717              :             else {
    3718              :                 dlt_log(LOG_ERR, "Invalid size of float64_t\n");
    3719              :                 return DLT_RETURN_ERROR;
    3720              :             }
    3721              : 
    3722              :             break;
    3723              :         }
    3724            0 :         case DLT_TYLE_128BIT:
    3725              :         {
    3726            0 :             if (*datalength >= 16)
    3727            0 :                 dlt_print_hex_string(value_text, (int)textlength, *ptr, 16);
    3728              : 
    3729            0 :             if ((*datalength) < 16)
    3730              :                 return DLT_RETURN_ERROR;
    3731              : 
    3732            0 :             *ptr += 16;
    3733            0 :             *datalength -= 16;
    3734            0 :             break;
    3735              :         }
    3736              :         default:
    3737              :         {
    3738              :             return DLT_RETURN_ERROR;
    3739              :         }
    3740              :         }
    3741              :     }
    3742          113 :     else if (type_info & DLT_TYPE_INFO_RAWD)
    3743              :     {
    3744              :         /* raw data argument */
    3745          112 :         DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3746              : 
    3747          112 :         if ((*datalength) < 0)
    3748              :             return DLT_RETURN_ERROR;
    3749              : 
    3750          110 :         length = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3751              : 
    3752          110 :         if (type_info & DLT_TYPE_INFO_VARI) {
    3753            0 :             DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3754              : 
    3755            0 :             if ((*datalength) < 0)
    3756              :                 return DLT_RETURN_ERROR;
    3757              : 
    3758            0 :             length2 = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3759              : 
    3760            0 :             if ((*datalength) < length2)
    3761              :                 return DLT_RETURN_ERROR;
    3762              : 
    3763            0 :             if (print_with_attributes) {
    3764              :                 // Print "name" attribute, if we have one with non-zero size.
    3765            0 :                 if (length2 > 1) {
    3766            0 :                     snprintf(text, textlength, "%s:", *ptr);
    3767            0 :                     value_text += length2+1-1;  // +1 for ":" and -1 for NUL
    3768            0 :                     textlength -= (size_t)(length2+1-1);
    3769              :                 }
    3770              :             }
    3771              : 
    3772            0 :             *ptr += length2;
    3773            0 :             *datalength -= length2;
    3774              :         }
    3775              : 
    3776          110 :         if ((*datalength) < length)
    3777              :             return DLT_RETURN_ERROR;
    3778              : 
    3779            9 :         if (dlt_print_hex_string_delim(value_text, (int) textlength, *ptr, length, '\'') < DLT_RETURN_OK)
    3780              :             return DLT_RETURN_ERROR;
    3781            9 :         *ptr += length;
    3782            9 :         *datalength -= length;
    3783              :     }
    3784            1 :     else if (type_info & DLT_TYPE_INFO_TRAI)
    3785              :     {
    3786              :         /* trace info argument */
    3787            0 :         DLT_MSG_READ_VALUE(value16u_tmp, *ptr, *datalength, uint16_t);
    3788              : 
    3789            0 :         if ((*datalength) < 0)
    3790              :             return DLT_RETURN_ERROR;
    3791              : 
    3792            0 :         length = DLT_ENDIAN_GET_16(msg->standardheader->htyp, value16u_tmp);
    3793              : 
    3794            0 :         DLT_MSG_READ_STRING(value_text, *ptr, *datalength, textlength, length);
    3795              : 
    3796            0 :         if ((*datalength) < 0)
    3797              :             return DLT_RETURN_ERROR;
    3798              :     }
    3799              :     else {
    3800              :         return DLT_RETURN_ERROR;
    3801              :     }
    3802              : 
    3803         2650 :     if (*datalength < 0) {
    3804            0 :         dlt_log(LOG_ERR, "Payload of DLT message corrupted\n");
    3805            0 :         return DLT_RETURN_ERROR;
    3806              :     }
    3807              : 
    3808              :     // Now write "unit" attribute, but only if it has more than only a nul-termination char.
    3809         2650 :     if (print_with_attributes) {
    3810            0 :         if (unit_text_len > 1) {
    3811              :             // 'value_text' still points to the +start+ of the value text
    3812            0 :             size_t currLen = strlen(value_text);
    3813              : 
    3814            0 :             char* unitText = value_text + currLen;
    3815            0 :             textlength -= currLen;
    3816              :             snprintf(unitText, textlength, ":%s", unit_text_src);
    3817              :         }
    3818              :     }
    3819              : 
    3820              :     return DLT_RETURN_OK;
    3821              : }
    3822              : 
    3823        24514 : void dlt_check_envvar()
    3824              : {
    3825        24514 :     char *env_log_filename = getenv("DLT_LOG_FILENAME");
    3826              : 
    3827        24514 :     if (env_log_filename != NULL)
    3828            0 :         dlt_log_set_filename(env_log_filename);
    3829              : 
    3830        24514 :     char *env_log_level_str = getenv("DLT_LOG_LEVEL");
    3831              : 
    3832        24514 :     if (env_log_level_str != NULL) {
    3833            0 :         int level = 0;
    3834              : 
    3835            0 :         if (sscanf(env_log_level_str, "%d", &level) == 1)
    3836            0 :             dlt_log_set_level(level);
    3837              :     }
    3838              : 
    3839        24514 :     char *env_log_mode = getenv("DLT_LOG_MODE");
    3840              : 
    3841        24514 :     if (env_log_mode != NULL) {
    3842            0 :         int mode = 0;
    3843              : 
    3844            0 :         if (sscanf(env_log_mode, "%d", &mode) == 1)
    3845            0 :             dlt_log_init(mode);
    3846              :     }
    3847              : 
    3848              : #if defined DLT_DAEMON_USE_FIFO_IPC || defined DLT_LIB_USE_FIFO_IPC
    3849        24514 :     char *env_pipe_dir = getenv("DLT_PIPE_DIR");
    3850              : 
    3851        24514 :     if (env_pipe_dir != NULL)
    3852            0 :         dlt_log_set_fifo_basedir(env_pipe_dir);
    3853              :     else
    3854        24514 :         dlt_log_set_fifo_basedir(DLT_USER_IPC_PATH);
    3855              : 
    3856              : #endif
    3857              : 
    3858              : #ifdef DLT_SHM_ENABLE
    3859              :     char *env_shm_name = getenv("DLT_SHM_NAME");
    3860              : 
    3861              :     if (env_shm_name != NULL)
    3862              :         dlt_log_set_shm_name(env_shm_name);
    3863              : 
    3864              : #endif
    3865        24514 : }
    3866              : 
    3867            2 : int dlt_set_loginfo_parse_service_id(char *resp_text,
    3868              :                                      uint32_t *service_id,
    3869              :                                      uint8_t *service_opt)
    3870              : {
    3871              :     int ret = -1;
    3872              :     char get_log_info_tag[GET_LOG_INFO_LENGTH];
    3873              :     char service_opt_str[SERVICE_OPT_LENGTH];
    3874              : 
    3875            2 :     if ((resp_text == NULL) || (service_id == NULL) || (service_opt == NULL))
    3876              :         return DLT_RETURN_ERROR;
    3877              : 
    3878              :     /* ascii type, syntax is 'get_log_info, ..' */
    3879              :     /* check target id */
    3880              :     strncpy(get_log_info_tag, "get_log_info", strlen("get_log_info") + 1);
    3881            2 :     ret = memcmp((void *)resp_text, (void *)get_log_info_tag, sizeof(get_log_info_tag) - 1);
    3882              : 
    3883            2 :     if (ret == 0) {
    3884            2 :         *service_id = DLT_SERVICE_ID_GET_LOG_INFO;
    3885              :         /* reading the response mode from the resp_text. eg. option 7*/
    3886            2 :         service_opt_str[0] = *(resp_text + GET_LOG_INFO_LENGTH + 1);
    3887            2 :         service_opt_str[1] = *(resp_text + GET_LOG_INFO_LENGTH + 2);
    3888            2 :         service_opt_str[2] = 0;
    3889            2 :         *service_opt = (uint8_t) atoi(service_opt_str);
    3890              :     }
    3891              : 
    3892              :     return ret;
    3893              : }
    3894              : 
    3895           14 : uint16_t dlt_getloginfo_conv_ascii_to_uint16_t(char *rp, int *rp_count)
    3896              : {
    3897           14 :     char num_work[5] = { 0 };
    3898              :     char *endptr;
    3899              : 
    3900           14 :     if ((rp == NULL) || (rp_count == NULL))
    3901              :         return (uint16_t)0xFFFF;
    3902              : 
    3903              :     /* ------------------------------------------------------
    3904              :      *  from: [89 13 ] -> to: ['+0x'1389\0] -> to num
    3905              :      *  ------------------------------------------------------ */
    3906           14 :     num_work[0] = *(rp + *rp_count + 3);
    3907           14 :     num_work[1] = *(rp + *rp_count + 4);
    3908           14 :     num_work[2] = *(rp + *rp_count + 0);
    3909           14 :     num_work[3] = *(rp + *rp_count + 1);
    3910              :     num_work[4] = 0;
    3911           14 :     *rp_count += 6;
    3912              : 
    3913           14 :     return (uint16_t)strtol(num_work, &endptr, 16);
    3914              : }
    3915              : 
    3916           12 : int16_t dlt_getloginfo_conv_ascii_to_int16_t(char *rp, int *rp_count)
    3917              : {
    3918           12 :     char num_work[3] = { 0 };
    3919              :     char *endptr;
    3920              : 
    3921           12 :     if ((rp == NULL) || (rp_count == NULL))
    3922              :         return -1;
    3923              : 
    3924              :     /* ------------------------------------------------------
    3925              :      *  from: [89 ] -> to: ['0x'89\0] -> to num
    3926              :      *  ------------------------------------------------------ */
    3927           12 :     num_work[0] = *(rp + *rp_count + 0);
    3928           12 :     num_work[1] = *(rp + *rp_count + 1);
    3929              :     num_work[2] = 0;
    3930           12 :     *rp_count += 3;
    3931              : 
    3932           12 :     return (signed char)strtol(num_work, &endptr, 16);
    3933              : }
    3934              : 
    3935           11 : void dlt_getloginfo_conv_ascii_to_string(char *rp, int *rp_count, char *wp, int len)
    3936              : {
    3937           11 :     if ((rp == NULL ) || (rp_count == NULL ) || (wp == NULL ))
    3938              :         return;
    3939              :     /* ------------------------------------------------------
    3940              :      *  from: [72 65 6d 6f ] -> to: [0x72,0x65,0x6d,0x6f,0x00]
    3941              :      *  ------------------------------------------------------ */
    3942              : 
    3943           11 :     int count = dlt_getloginfo_conv_ascii_to_id(rp, rp_count, wp, len);
    3944           11 :     *(wp + count) = '\0';
    3945              : 
    3946           11 :     return;
    3947              : }
    3948              : 
    3949           20 : int dlt_getloginfo_conv_ascii_to_id(char *rp, int *rp_count, char *wp, int len)
    3950              : {
    3951           20 :     char number16[3] = { 0 };
    3952              :     char *endptr;
    3953              :     int count;
    3954              : 
    3955           20 :     if ((rp == NULL) || (rp_count == NULL) || (wp == NULL))
    3956              :         return 0;
    3957              : 
    3958              :     /* ------------------------------------------------------
    3959              :      *  from: [72 65 6d 6f ] -> to: [0x72,0x65,0x6d,0x6f]
    3960              :      *  ------------------------------------------------------ */
    3961          289 :     for (count = 0; count < len; count++) {
    3962          269 :         number16[0] = *(rp + *rp_count + 0);
    3963          269 :         number16[1] = *(rp + *rp_count + 1);
    3964          269 :         *(wp + count) = (char) strtol(number16, &endptr, 16);
    3965          269 :         *rp_count += 3;
    3966              :     }
    3967              : 
    3968              :     return count;
    3969              : }
    3970              : 
    3971            0 : void dlt_hex_ascii_to_binary(const char *ptr, uint8_t *binary, int *size)
    3972              : {
    3973            0 :     char ch = *ptr;
    3974              :     int pos = 0;
    3975            0 :     binary[pos] = 0;
    3976              :     int first = 1;
    3977              :     int found;
    3978              : 
    3979              :     for (;;) {
    3980            0 :         if (ch == 0) {
    3981            0 :             *size = pos;
    3982            0 :             return;
    3983              :         }
    3984              : 
    3985              :         found = 0;
    3986              : 
    3987            0 :         if ((ch >= '0') && (ch <= '9')) {
    3988            0 :             binary[pos] = (uint8_t) ((binary[pos] << 4) + (ch - '0'));
    3989              :             found = 1;
    3990              :         }
    3991            0 :         else if ((ch >= 'A') && (ch <= 'F'))
    3992              :         {
    3993            0 :             binary[pos] = (uint8_t) ((binary[pos] << 4) + (ch - 'A' + 10));
    3994              :             found = 1;
    3995              :         }
    3996            0 :         else if ((ch >= 'a') && (ch <= 'f'))
    3997              :         {
    3998            0 :             binary[pos] = (uint8_t) ((binary[pos] << 4) + (ch - 'a' + 10));
    3999              :             found = 1;
    4000              :         }
    4001              : 
    4002              :         if (found) {
    4003            0 :             if (first) {
    4004              :                 first = 0;
    4005              :             }
    4006              :             else {
    4007              :                 first = 1;
    4008            0 :                 pos++;
    4009              : 
    4010            0 :                 if (pos >= *size)
    4011              :                     return;
    4012              : 
    4013            0 :                 binary[pos] = 0;
    4014              :             }
    4015              :         }
    4016              : 
    4017            0 :         ch = *(++ptr);
    4018              :     }
    4019              : }
    4020              : 
    4021            3 : DltReturnValue dlt_file_quick_parsing(DltFile *file, const char *filename,
    4022              :                                       int type, int verbose)
    4023              : {
    4024            3 :     PRINT_FUNCTION_VERBOSE(verbose);
    4025              :     int ret = DLT_RETURN_OK;
    4026            3 :     char text[DLT_CONVERT_TEXTBUFSIZE] = { 0 };
    4027              : 
    4028            3 :     if ((file == NULL) || (filename == NULL))
    4029              :         return DLT_RETURN_WRONG_PARAMETER;
    4030              : 
    4031            1 :     FILE *output = fopen(filename, "w+");
    4032              : 
    4033            1 :     if (output == NULL) {
    4034            0 :         dlt_vlog(LOG_ERR, "Cannot open output file %s for parsing\n", filename);
    4035            0 :         return DLT_RETURN_ERROR;
    4036              :     }
    4037              : 
    4038          106 :     while (ret >= DLT_RETURN_OK && file->file_position < file->file_length) {
    4039              :         /* get file position at start of DLT message */
    4040          105 :         if (verbose)
    4041            0 :             dlt_vlog(LOG_DEBUG, "Position in file: %" PRIu64 "\n", file->file_position);
    4042              : 
    4043              :         /* read all header and payload */
    4044          105 :         ret = dlt_file_read_header(file, verbose);
    4045              : 
    4046          105 :         if (ret < DLT_RETURN_OK)
    4047              :             break;
    4048              : 
    4049          105 :         ret = dlt_file_read_header_extended(file, verbose);
    4050              : 
    4051          105 :         if (ret < DLT_RETURN_OK)
    4052              :             break;
    4053              : 
    4054          105 :         ret = dlt_file_read_data(file, verbose);
    4055              : 
    4056          105 :         if (ret < DLT_RETURN_OK)
    4057              :             break;
    4058              : 
    4059          105 :         if (file->filter) {
    4060              :             /* check the filters if message is used */
    4061            0 :             ret = dlt_message_filter_check(&(file->msg), file->filter, verbose);
    4062              : 
    4063            0 :             if (ret != DLT_RETURN_TRUE)
    4064            0 :                 continue;
    4065              :         }
    4066              : 
    4067          105 :         ret = dlt_message_header(&(file->msg), text,
    4068              :                                  DLT_CONVERT_TEXTBUFSIZE, verbose);
    4069              : 
    4070          105 :         if (ret < DLT_RETURN_OK)
    4071              :             break;
    4072              : 
    4073              :         fprintf(output, "%s", text);
    4074              : 
    4075          105 :         ret = dlt_message_payload(&(file->msg), text,
    4076              :                                   DLT_CONVERT_TEXTBUFSIZE, type, verbose);
    4077              : 
    4078          105 :         if (ret < DLT_RETURN_OK)
    4079              :             break;
    4080              : 
    4081              :         fprintf(output, "[%s]\n", text);
    4082              : 
    4083              :         /* store index pointer to message position in DLT file */
    4084          105 :         file->counter++;
    4085          105 :         file->position = file->counter_total - 1;
    4086              :         /* increase total message counter */
    4087          105 :         file->counter_total++;
    4088              :         /* store position to next message */
    4089          105 :         file->file_position = (uint64_t)ftell(file->handle);
    4090              :     } /* while() */
    4091              : 
    4092            1 :     fclose(output);
    4093            1 :     return ret;
    4094              : }
    4095              : 
    4096              : 
    4097            0 : int dlt_execute_command(char *filename, char *command, ...)
    4098              : {
    4099              :     va_list val;
    4100              :     int argc;
    4101              :     char **args = NULL;
    4102            0 :     int ret = 0;
    4103              : 
    4104            0 :     if (command == NULL)
    4105              :         return -1;
    4106              : 
    4107              :     /* Determine number of variadic arguments */
    4108            0 :     va_start(val, command);
    4109              : 
    4110            0 :     for (argc = 2; va_arg(val, char *) != NULL; argc++);
    4111              : 
    4112            0 :     va_end(val);
    4113              : 
    4114              :     /* Allocate args, put references to command */
    4115            0 :     args = (char **) malloc( (uint32_t) argc * sizeof(char*));
    4116            0 :     args[0] = command;
    4117              : 
    4118            0 :     va_start(val, command);
    4119              : 
    4120            0 :     for (int i = 0; args[i] != NULL; i++)
    4121            0 :         args[i + 1] = va_arg(val, char *);
    4122              : 
    4123            0 :     va_end(val);
    4124              : 
    4125              :     /* Run command in child process */
    4126            0 :     pid_t pid = fork();
    4127              : 
    4128            0 :     if (pid == 0) { /* child process */
    4129              : 
    4130              :         /* Redirect output if required */
    4131            0 :         if (filename != NULL) {
    4132              :             int fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    4133              : 
    4134            0 :             if (fd < 0)
    4135            0 :                 err(-1, "%s failed on open()", __func__);
    4136              : 
    4137            0 :             if (dup2(fd, STDOUT_FILENO) == -1) {
    4138            0 :                 close(fd);
    4139            0 :                 err(-1, "%s failed on dup2()", __func__);
    4140              :             }
    4141              : 
    4142            0 :             close(fd);
    4143              :         }
    4144              : 
    4145              :         /* Run command */
    4146            0 :         execvp(command, (char **)args);
    4147              :     }
    4148            0 :     else if (pid == -1) /* error in fork */
    4149              :     {
    4150            0 :         ret = -1;
    4151              :     }
    4152              :     else /* parent */
    4153              :     {
    4154            0 :         if (wait(&ret) == -1) {
    4155            0 :             err(-1, "%s failed on wait()", __func__);
    4156              :         }
    4157              :     }
    4158              : 
    4159            0 :     free(args);
    4160            0 :     return ret;
    4161              : }
    4162              : 
    4163            5 : char *get_filename_ext(const char *filename)
    4164              : {
    4165            5 :     if (filename == NULL) {
    4166            0 :         fprintf(stderr, "ERROR: %s: invalid arguments\n", __func__);
    4167            0 :         return "";
    4168              :     }
    4169              : 
    4170            5 :     char *dot = strrchr(filename, '.');
    4171            5 :     return (!dot || dot == filename) ? NULL : dot;
    4172              : }
    4173              : 
    4174            6 : bool dlt_extract_base_name_without_ext(const char* const abs_file_name, char* base_name, long base_name_len) {
    4175            6 :     if (abs_file_name == NULL || base_name == NULL) return false;
    4176              : 
    4177            6 :     const char* last_separator = strrchr(abs_file_name, '.');
    4178            6 :     if (!last_separator) return false;
    4179            5 :     long length = last_separator - abs_file_name;
    4180              :         /* Ensure length fits within buffer, leaving room for null terminator */
    4181            5 :     if (length >= base_name_len)
    4182            0 :         length = base_name_len - 1;
    4183              : 
    4184            5 :     strncpy(base_name, abs_file_name, (size_t)length);
    4185            5 :     base_name[length] = '\0';
    4186            5 :     return true;
    4187              : }
    4188              : 
    4189              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4190              : static int32_t dlt_output_soft_limit_over_warning(
    4191              :     DltTraceLoadSettings* const tl_settings,
    4192              :     DltLogInternal log_internal,
    4193              :     void *const log_params)
    4194              : {
    4195              :     char local_str[255];
    4196              : 
    4197              :     if (!tl_settings || !tl_settings->tl_stat.is_over_soft_limit || tl_settings->tl_stat.slot_left_soft_limit_warn)
    4198              :     {
    4199              :         /* No need to output warning message */
    4200              :         return 0;
    4201              :     }
    4202              : 
    4203              :     /* Calculate extra trace load which was over limit */
    4204              :     const uint64_t dropped_message_load
    4205              :         = (tl_settings->tl_stat.hard_limit_over_bytes * DLT_TIMESTAMP_RESOLUTION)
    4206              :           / TIMESTAMP_BASED_WINDOW_SIZE;
    4207              :     const uint64_t curr_trace_load = tl_settings->tl_stat.avg_trace_load + dropped_message_load;
    4208              :     if (curr_trace_load <= tl_settings->soft_limit) {
    4209              :         /* No need to output warning message */
    4210              :         return 0;
    4211              :     }
    4212              : 
    4213              :     /* Warning for exceeded soft limit */
    4214              :     if (tl_settings->ctid[0] == 0) {
    4215              :         snprintf(local_str, sizeof(local_str),
    4216              :                  "Trace load exceeded trace soft limit on apid %.4s "
    4217              :                  "(soft limit: %u bytes/sec, current: %lu bytes/sec)",
    4218              :                  tl_settings->apid,
    4219              :                  tl_settings->soft_limit,
    4220              :                  curr_trace_load);
    4221              :     } else {
    4222              :         snprintf(local_str, sizeof(local_str),
    4223              :                  "Trace load exceeded trace soft limit on apid %.4s, ctid %.4s "
    4224              :                  "(soft limit: %u bytes/sec, current: %lu bytes/sec)",
    4225              :                  tl_settings->apid,
    4226              :                  tl_settings->ctid,
    4227              :                  tl_settings->soft_limit,
    4228              :                  curr_trace_load);
    4229              :     }
    4230              : 
    4231              :     // must be signed int for error return value
    4232              :     int32_t sent_size = log_internal(DLT_LOG_WARN, local_str, log_params);
    4233              :     if (sent_size < DLT_RETURN_OK)
    4234              :     {
    4235              :         /* Output warning message via other route for safety */
    4236              :         dlt_log(DLT_LOG_WARN, local_str);
    4237              :         sent_size = 0;
    4238              :     }
    4239              : 
    4240              :     /* Turn off the flag after sending warning message */
    4241              :     tl_settings->tl_stat.is_over_soft_limit = false;
    4242              :     tl_settings->tl_stat.slot_left_soft_limit_warn = DLT_SOFT_LIMIT_WARN_FREQUENCY;
    4243              : 
    4244              :     return sent_size;
    4245              : }
    4246              : 
    4247              : static int32_t dlt_output_hard_limit_warning(
    4248              :     DltTraceLoadSettings* const tl_settings,
    4249              :     DltLogInternal log_internal,
    4250              :     void *const log_params)
    4251              : {
    4252              :     char local_str[255];
    4253              :     if (!tl_settings || !tl_settings->tl_stat.is_over_hard_limit || tl_settings->tl_stat.slot_left_hard_limit_warn)
    4254              :     {
    4255              :         /* No need to output warning message */
    4256              :         return 0;
    4257              :     }
    4258              : 
    4259              :     /* Calculate extra trace load which was over limit */
    4260              :     const uint64_t dropped_message_load
    4261              :         = (tl_settings->tl_stat.hard_limit_over_bytes * DLT_TIMESTAMP_RESOLUTION)
    4262              :           / TIMESTAMP_BASED_WINDOW_SIZE;
    4263              :     const uint64_t curr_trace_load = tl_settings->tl_stat.avg_trace_load + dropped_message_load;
    4264              :     if (curr_trace_load <= tl_settings->hard_limit) {
    4265              :         /* No need to output warning message */
    4266              :         return 0;
    4267              :     }
    4268              : 
    4269              :     if (tl_settings->ctid[0] == 0) {
    4270              :         snprintf(local_str, sizeof(local_str),
    4271              :                  "Trace load exceeded trace hard limit on apid %.4s "
    4272              :                  "(hard limit: %u bytes/sec, current: %lu bytes/sec) %u messages discarded. ",
    4273              :                  tl_settings->apid,
    4274              :                  tl_settings->hard_limit,
    4275              :                  curr_trace_load,
    4276              :                  tl_settings->tl_stat.hard_limit_over_counter);
    4277              :     } else {
    4278              :         snprintf(local_str, sizeof(local_str),
    4279              :                  "Trace load exceeded trace hard limit on apid %.4s, ctid %.4s."
    4280              :                  "(hard limit: %u bytes/sec, current: %lu bytes/sec) %u messages discarded.",
    4281              :                  tl_settings->apid,
    4282              :                  tl_settings->ctid,
    4283              :                  tl_settings->hard_limit,
    4284              :                  curr_trace_load,
    4285              :                  tl_settings->tl_stat.hard_limit_over_counter);
    4286              :     }
    4287              : 
    4288              :     // must be signed int for error return
    4289              :     int32_t sent_size = log_internal(DLT_LOG_WARN, local_str, log_params);
    4290              :     if (sent_size < DLT_RETURN_OK)
    4291              :     {
    4292              :         /* Output warning message via other route for safety */
    4293              :         dlt_log(DLT_LOG_WARN, local_str);
    4294              :         sent_size = 0;
    4295              :     }
    4296              : 
    4297              :     /* Turn off the flag after sending warning message */
    4298              :     tl_settings->tl_stat.is_over_hard_limit = false;
    4299              :     tl_settings->tl_stat.hard_limit_over_counter = 0;
    4300              :     tl_settings->tl_stat.hard_limit_over_bytes = 0;
    4301              :     tl_settings->tl_stat.slot_left_hard_limit_warn = DLT_HARD_LIMIT_WARN_FREQUENCY;
    4302              : 
    4303              :     return sent_size;
    4304              : }
    4305              : 
    4306              : static bool dlt_user_cleanup_window(DltTraceLoadStat *const tl_stat)
    4307              : {
    4308              :     if (!tl_stat)
    4309              :     {
    4310              :         return false;
    4311              :     }
    4312              : 
    4313              :     uint32_t elapsed_slots  = 0;
    4314              :     /* check if overflow of timestamp happened, after ~119 hours */
    4315              :     if (tl_stat->curr_abs_slot < tl_stat->last_abs_slot) {
    4316              :         /* calculate where the next slot starts according to the last slot
    4317              :          * This works because the value after the uint32 rollover equals is equal to the remainder that did not fit
    4318              :          * into uint32 before. Therefore, we always have slots that are DLT_TIMESTAMP_RESOLUTION long
    4319              :          * */
    4320              :         const uint32_t next_slot_start =
    4321              :             DLT_TIMESTAMP_RESOLUTION + tl_stat->last_abs_slot;
    4322              : 
    4323              :         /* Check if we are already in the next slot */
    4324              :         if (next_slot_start <= tl_stat->curr_abs_slot) {
    4325              :             /* Calculate relative amount of elapsed slots */
    4326              :             elapsed_slots = (tl_stat->curr_abs_slot - next_slot_start) / DLT_TIMESTAMP_RESOLUTION + 1;
    4327              :         }
    4328              :         /* else we are not in the next slot yet */
    4329              :     } else {
    4330              :         /* no rollover, get difference between slots to get amount of elapsed slots  */
    4331              :         elapsed_slots = (tl_stat->curr_abs_slot - tl_stat->last_abs_slot);
    4332              :     }
    4333              : 
    4334              :     if (!elapsed_slots)
    4335              :     {
    4336              :         /* Same slot can be still used. No need to cleanup slot */
    4337              :         return false;
    4338              :     }
    4339              : 
    4340              :     /* Slot-Based Count down for next warning messages */
    4341              :     tl_stat->slot_left_soft_limit_warn = (tl_stat->slot_left_soft_limit_warn > elapsed_slots) ?
    4342              :                                                                                               (tl_stat->slot_left_soft_limit_warn - elapsed_slots) : 0;
    4343              : 
    4344              :     tl_stat->slot_left_hard_limit_warn = (tl_stat->slot_left_hard_limit_warn > elapsed_slots) ?
    4345              :                                                                                               (tl_stat->slot_left_hard_limit_warn - elapsed_slots) : 0;
    4346              : 
    4347              :     /* Clear whole window when time elapsed longer than window size from last message */
    4348              :     if (elapsed_slots >= DLT_TRACE_LOAD_WINDOW_SIZE)
    4349              :     {
    4350              :         tl_stat->total_bytes_of_window = 0;
    4351              :         memset(tl_stat->window, 0, sizeof(tl_stat->window));
    4352              :         return true;
    4353              :     }
    4354              : 
    4355              :     /* Clear skipped no data slots */
    4356              :     uint32_t temp_slot = tl_stat->last_slot;
    4357              :     while (temp_slot != tl_stat->curr_slot)
    4358              :     {
    4359              :         temp_slot++;
    4360              :         temp_slot %= DLT_TRACE_LOAD_WINDOW_SIZE;
    4361              :         tl_stat->total_bytes_of_window -= tl_stat->window[temp_slot];
    4362              :         tl_stat->window[temp_slot] = 0;
    4363              :     }
    4364              : 
    4365              :     return true;
    4366              : }
    4367              : 
    4368              : static int32_t dlt_switch_slot_if_needed(
    4369              :     DltTraceLoadSettings* const tl_settings,
    4370              :     DltLogInternal log_internal,
    4371              :     void* const log_internal_params,
    4372              :     const uint32_t timestamp)
    4373              : {
    4374              :     if (!tl_settings)
    4375              :     {
    4376              :         return 0;
    4377              :     }
    4378              : 
    4379              :     /* Get new window slot No. */
    4380              :     tl_settings->tl_stat.curr_abs_slot = timestamp / DLT_TRACE_LOAD_WINDOW_RESOLUTION;
    4381              :     tl_settings->tl_stat.curr_slot = tl_settings->tl_stat.curr_abs_slot % DLT_TRACE_LOAD_WINDOW_SIZE;
    4382              : 
    4383              :     /* Cleanup window */
    4384              :     if (!dlt_user_cleanup_window(&tl_settings->tl_stat))
    4385              :     {
    4386              :         /* No need to switch slot because same slot can be still used */
    4387              :         return 0;
    4388              :     }
    4389              : 
    4390              :     /* If slot is switched and trace load has been over soft/hard limit
    4391              :      * in previous slot, warning messages may be sent.
    4392              :      * The warning messages will be also counted as trace load.
    4393              :      */
    4394              :     const int32_t sent_warn_msg_bytes =
    4395              :         dlt_output_soft_limit_over_warning(tl_settings, log_internal, log_internal_params) +
    4396              :         dlt_output_hard_limit_warning(tl_settings, log_internal, log_internal_params);
    4397              :     return sent_warn_msg_bytes;
    4398              : }
    4399              : 
    4400              : static void dlt_record_trace_load(DltTraceLoadStat *const tl_stat, const int32_t size)
    4401              : {
    4402              :     if (!tl_stat)
    4403              :     {
    4404              :         return;
    4405              :     }
    4406              : 
    4407              :     /* Record trace load to current slot by message size of
    4408              :      * original message and warning message if it was sent
    4409              :      */
    4410              :     tl_stat->window[tl_stat->curr_slot] += size;
    4411              :     tl_stat->total_bytes_of_window += size;
    4412              : 
    4413              :     /* Keep the latest time information */
    4414              :     tl_stat->last_abs_slot = tl_stat->curr_abs_slot;
    4415              :     tl_stat->last_slot = tl_stat->curr_slot;
    4416              : 
    4417              :     /* Calculate average trace load [bytes/sec] in window
    4418              :      * The division is necessary to normalize the average to bytes per second even if
    4419              :      * the slot size is not equal to 1s
    4420              :      * */
    4421              :     tl_stat->avg_trace_load
    4422              :         = (tl_stat->total_bytes_of_window * DLT_TIMESTAMP_RESOLUTION) / TIMESTAMP_BASED_WINDOW_SIZE;
    4423              : }
    4424              : 
    4425              : static inline bool dlt_is_over_trace_load_soft_limit(DltTraceLoadSettings* const tl_settings)
    4426              : {
    4427              :     if (tl_settings
    4428              :         && (tl_settings->tl_stat.avg_trace_load > tl_settings->soft_limit || tl_settings->soft_limit == 0))
    4429              :     {
    4430              :         /* Mark as soft limit over */
    4431              :         tl_settings->tl_stat.is_over_soft_limit = true;
    4432              :         return true;
    4433              :     }
    4434              : 
    4435              :     return false;
    4436              : }
    4437              : 
    4438              : static inline bool dlt_is_over_trace_load_hard_limit(
    4439              :     DltTraceLoadSettings* const tl_settings, const int size)
    4440              : {
    4441              :     if (tl_settings
    4442              :         && (tl_settings->tl_stat.avg_trace_load > tl_settings->hard_limit
    4443              :             || tl_settings->hard_limit == 0))
    4444              :     {
    4445              :         /* Mark as limit over */
    4446              :         tl_settings->tl_stat.is_over_hard_limit = true;
    4447              :         tl_settings->tl_stat.hard_limit_over_counter++;
    4448              :         tl_settings->tl_stat.hard_limit_over_bytes += size;
    4449              : 
    4450              :         /* Delete size of limit over message from window */
    4451              :         tl_settings->tl_stat.window[tl_settings->tl_stat.curr_slot] -= size;
    4452              :         tl_settings->tl_stat.total_bytes_of_window -= size;
    4453              :         return true;
    4454              :     }
    4455              : 
    4456              :     return false;
    4457              : }
    4458              : 
    4459              : bool dlt_check_trace_load(
    4460              :     DltTraceLoadSettings * const tl_settings,
    4461              :     const int32_t log_level,
    4462              :     const uint32_t timestamp,
    4463              :     const int32_t size,
    4464              :     DltLogInternal internal_dlt_log,
    4465              :     void* const internal_dlt_log_params)
    4466              : {
    4467              :     /* Unconditionally allow message which has log level: Debug/Verbose to be output */
    4468              :     if (log_level == DLT_LOG_DEBUG || log_level == DLT_LOG_VERBOSE)
    4469              :     {
    4470              :         return true;
    4471              :     }
    4472              : 
    4473              :     if (tl_settings == NULL)
    4474              :     {
    4475              :         internal_dlt_log(DLT_LOG_ERROR, "tl_settings is NULL", internal_dlt_log_params);
    4476              :         return false;
    4477              :     }
    4478              : 
    4479              :     if (size < 0)
    4480              :     {
    4481              :         dlt_vlog(LOG_ERR, "Invalid size: %d", size);
    4482              :         return false;
    4483              :     }
    4484              : 
    4485              :     /* Switch window slot according to timestamp
    4486              :      * If warning messages for hard/soft limit over are sent,
    4487              :      * the message size will be returned.
    4488              :      */
    4489              :     const int32_t sent_warn_msg_bytes = dlt_switch_slot_if_needed(
    4490              :         tl_settings, internal_dlt_log, internal_dlt_log_params, timestamp);
    4491              : 
    4492              :     /* Record trace load */
    4493              :     dlt_record_trace_load(&tl_settings->tl_stat, size + sent_warn_msg_bytes);
    4494              : 
    4495              :     /* Check if trace load is over the soft limit.
    4496              :      * Even if trace load is over the soft limit, message will not be discarded.
    4497              :      * Only the warning message will be output
    4498              :      */
    4499              :     dlt_is_over_trace_load_soft_limit(tl_settings);
    4500              : 
    4501              :     /* Check if trace load is over hard limit.
    4502              :      * If trace load is over the limit, message will be discarded.
    4503              :      */
    4504              :     const bool allow_output = !dlt_is_over_trace_load_hard_limit(tl_settings, size);
    4505              : 
    4506              :     return allow_output;
    4507              : }
    4508              : 
    4509              : DltTraceLoadSettings*
    4510              : dlt_find_runtime_trace_load_settings(DltTraceLoadSettings *settings, uint32_t settings_count, const char* apid, const char* ctid) {
    4511              :     if ((apid == NULL) || (strnlen(apid, DLT_ID_SIZE) == 0))
    4512              :         return NULL;
    4513              : 
    4514              :     DltTraceLoadSettings* app_level = NULL;
    4515              :     size_t ctid_len = (ctid != NULL) ? strnlen(ctid, DLT_ID_SIZE) : 0;
    4516              : 
    4517              :     for (uint32_t i = 0; i < settings_count; ++i) {
    4518              :         if (strncmp(apid, settings->apid, DLT_ID_SIZE) != 0) {
    4519              :             if (app_level == NULL)
    4520              :                 continue;
    4521              :             // settings are sorted.
    4522              :             // If we found a configuration entry which matches the app id already
    4523              :             // we can exit here because no more entries with the app id will follow anymore.
    4524              :             break;
    4525              :         }
    4526              : 
    4527              :         if (settings[i].ctid[0] == '\0') {
    4528              :             app_level = &settings[i];
    4529              :             if (ctid_len == 0)
    4530              :                 return &settings[i];
    4531              :             continue;
    4532              :         }
    4533              : 
    4534              :         if ((ctid_len > 0) && (strncmp(ctid, settings[i].ctid, DLT_ID_SIZE) == 0)) {
    4535              :             return &settings[i];
    4536              :         }
    4537              :     }
    4538              : 
    4539              :     return app_level;
    4540              : }
    4541              : 
    4542              : #endif
        

Generated by: LCOV version 2.0-1