LCOV - code coverage report
Current view: top level - shared - dlt_config_file_parser.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 83.8 % 167 140
Test Date: 2025-03-25 20:53:42 Functions: 100.0 % 15 15

            Line data    Source code
       1              : /*
       2              :  * SPDX license identifier: MPL-2.0
       3              :  *
       4              :  * Copyright (C) 2015, Advanced Driver Information Technology
       5              :  * This code is developed by Advanced Driver Information Technology.
       6              :  * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
       7              :  *
       8              :  * This file is part of COVESA Project DLT - Diagnostic Log and Trace.
       9              :  *
      10              :  * This Source Code Form is subject to the terms of the
      11              :  * Mozilla Public License (MPL), v. 2.0.
      12              :  * If a copy of the MPL was not distributed with this file,
      13              :  * You can obtain one at http://mozilla.org/MPL/2.0/.
      14              :  *
      15              :  * For further information see http://www.covesa.org/.
      16              :  */
      17              : 
      18              : /*!
      19              :  * \author
      20              :  * Christoph Lipka <clipka@jp.adit-jv.com>
      21              :  *
      22              :  * \copyright Copyright © 2015 Advanced Driver Information Technology. \n
      23              :  * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
      24              :  *
      25              :  * \file dlt_config_file_parser.c
      26              :  */
      27              : 
      28              : #include "dlt_config_file_parser.h"
      29              : #include <stdlib.h>
      30              : #include <stdio.h>
      31              : #include <string.h>
      32              : #include <ctype.h>
      33              : #include <syslog.h>
      34              : #include "dlt_common.h"
      35              : #include "dlt_log.h"
      36              : #include "dlt-daemon_cfg.h"
      37              : 
      38              : /* internal defines */
      39              : #define DLT_CONFIG_FILE_NEW_SECTION 0x0a
      40              : #define DLT_CONFIG_FILE_NEW_DATA    0x0b
      41              : 
      42              : 
      43              : /* internal helper functions */
      44              : 
      45              : /**
      46              :  * dlt_config_file_trim_line
      47              :  *
      48              :  * Trim all whitespace from a string
      49              :  *
      50              :  * @param line  String to remove whitespace from
      51              :  */
      52          379 : static void dlt_config_file_trim_line(char *line)
      53              : {
      54          379 :     if (line == NULL)
      55              :         return;
      56              : 
      57              :     char *i = line;
      58              :     char *j = line;
      59              : 
      60         6683 :     while (*j != '\0') {
      61         6304 :         *i = *j++;
      62              : 
      63         6304 :         if (!isspace(*i))
      64         5925 :             i++;
      65              :     }
      66              : 
      67          379 :     *i = '\0';
      68              : }
      69              : 
      70              : /**
      71              :  * dlt_config_file_ignore_line
      72              :  *
      73              :  * Check if a line has to be ignored, because it contains a comment or is empty
      74              :  *
      75              :  * @param line  Line of configuration file
      76              :  * @return 0 if ignore, -1 do not ignore
      77              :  */
      78              : static int dlt_config_file_ignore_line(char *line)
      79              : {
      80          406 :     if ((line[0] == '#') || (line[0] == ';') || (line[0] == '\n') ||
      81              :         (line[0] == '\0'))
      82              :         return 0; /* ignore */
      83              :     else
      84              :         return -1; /* do not ignore */
      85              : }
      86              : 
      87              : /**
      88              :  * dlt_config_file_is_section_name
      89              :  *
      90              :  * Check if section name already used
      91              :  *
      92              :  * @param file  DltConfigFile
      93              :  * @param name  Name of section
      94              :  * @return 0, section name not used, -1 section name already used
      95              :  */
      96           40 : static int dlt_config_file_is_section_name(DltConfigFile *file, char *name)
      97              : {
      98              :     int i = 0;
      99              : 
     100           40 :     if ((file == NULL) || (name == NULL))
     101              :         return -1;
     102              : 
     103          179 :     for (i = 0; i < file->num_sections; i++) {
     104          139 :         DltConfigFileSection *s = &file->sections[i];
     105              : 
     106          139 :         if (strncmp(s->name, name, DLT_CONFIG_FILE_ENTRY_MAX_LEN) == 0)
     107              :             return -1;
     108              :     }
     109              : 
     110              :     return 0; /* section name not used */
     111              : }
     112              : 
     113              : /**
     114              :  * dlt_config_file_set_section
     115              :  *
     116              :  * Store section in internal data structure
     117              :  *
     118              :  * @param file  DltConfigFile
     119              :  * @param name  Name of section
     120              :  * @return 0 on success, else -1
     121              :  */
     122           40 : static int dlt_config_file_set_section(DltConfigFile *file, char *name)
     123              : {
     124           40 :     int section = file->num_sections;
     125              : 
     126              :     /* check if adding another section would exceed max number of sections */
     127           40 :     if (section >= DLT_CONFIG_FILE_SECTIONS_MAX) {
     128            0 :         dlt_log(LOG_WARNING, "Cannot store more sections\n");
     129            0 :         return -1; /* reached max number of sections */
     130              :     }
     131              : 
     132              :     /* do not store section with same name again */
     133           40 :     if (dlt_config_file_is_section_name(file, name) != 0) {
     134            0 :         dlt_log(LOG_WARNING, "Cannot store section name again\n");
     135            0 :         return -1;
     136              :     }
     137              : 
     138           40 :     DltConfigFileSection *s = &file->sections[section];
     139              : 
     140              :     /* alloc data for entries */
     141           40 :     s->name = calloc(sizeof(char), DLT_CONFIG_FILE_ENTRY_MAX_LEN + 1);
     142              : 
     143           40 :     if (s->name == NULL) {
     144            0 :         dlt_log(LOG_ERR, "Cannot allocate memory for internal data structure\n");
     145            0 :         return -1;
     146              :     }
     147              : 
     148           40 :     s->keys = calloc(sizeof(char), DLT_CONFIG_FILE_ENTRY_MAX_LEN * DLT_CONFIG_FILE_KEYS_MAX + 1);
     149              : 
     150           40 :     if (s->keys == NULL) {
     151            0 :         free(s->name);
     152            0 :         s->name = NULL;
     153            0 :         dlt_log(LOG_ERR, "Cannot allocate memory for internal data structure\n");
     154            0 :         return -1;
     155              :     }
     156              : 
     157              :     strncpy(file->sections[section].name, name, DLT_CONFIG_FILE_ENTRY_MAX_LEN);
     158           40 :     file->num_sections += 1;
     159           40 :     return 0;
     160              : }
     161              : 
     162              : /**
     163              :  * dlt_config_file_set_section_data
     164              :  *
     165              :  * Store data pair of a section
     166              :  *
     167              :  * @param file DltConfigFile
     168              :  * @param str1 string used for key
     169              :  * @param str2 string used for value
     170              :  * @return 0 on success, else -1
     171              :  */
     172          339 : static int dlt_config_file_set_section_data(DltConfigFile *file, char *str1, char *str2)
     173              : {
     174              :     DltConfigKeyData **tmp = NULL;
     175              : 
     176          339 :     if ((file == NULL) || (str1 == NULL) || (str2 == NULL))
     177              :         return -1;
     178              : 
     179          339 :     DltConfigFileSection *s = &file->sections[file->num_sections - 1];
     180          339 :     int key_number = s->num_entries;
     181              : 
     182          339 :     if (key_number + 1 >= DLT_CONFIG_FILE_KEYS_MAX) {
     183            0 :         dlt_log(LOG_WARNING, "Cannot store more keys in section\n");
     184            0 :         return -1; /* reached max number of keys per section */
     185              :     }
     186              : 
     187              :     /* copy data into structure */
     188          339 :     strncpy(&s->keys[key_number * DLT_CONFIG_FILE_ENTRY_MAX_LEN], str1, DLT_CONFIG_FILE_ENTRY_MAX_LEN);
     189              : 
     190          339 :     if (s->list == NULL) {
     191              :         /* creating a list if it doesnt exists */
     192           40 :         s->list = malloc(sizeof(DltConfigKeyData));
     193              : 
     194           40 :         if (s->list == NULL) {
     195            0 :             dlt_log(LOG_WARNING, "Could not allocate initial memory to list \n");
     196            0 :             return -1;
     197              :         }
     198              : 
     199           40 :         tmp = &s->list;
     200              :     }
     201              :     else {
     202          299 :         tmp = &s->list;
     203              : 
     204         1589 :         while (*(tmp) != NULL)
     205         1290 :             tmp = &(*tmp)->next;
     206              : 
     207              :         /* Adding new entry to the list */
     208          299 :         *tmp = malloc(sizeof(DltConfigKeyData));
     209              : 
     210          299 :         if (*tmp == NULL) {
     211            0 :             dlt_log(LOG_WARNING, "Could not allocate memory to list \n");
     212            0 :             return -1;
     213              :         }
     214              :     }
     215              : 
     216          339 :     (*tmp)->key = strdup(str1);
     217          339 :     (*tmp)->data = strdup(str2);
     218          339 :     (*tmp)->next = NULL;
     219              : 
     220          339 :     s->num_entries += 1;
     221              : 
     222          339 :     return 0;
     223              : }
     224              : 
     225              : /**
     226              :  * dlt_config_file_has_section
     227              :  *
     228              :  * Check if a certain line in config file is a section header
     229              :  *
     230              :  * @param line  Line in configuration file
     231              :  * @return 0 if section header, else -1
     232              :  */
     233              : static int dlt_config_file_line_has_section(char *line)
     234              : {
     235              :     (void)line; /* avoid compiler warnings */
     236              : 
     237          379 :     if (line[0] == '[') /* section found */
     238              :         return 0;
     239              :     else
     240              :         return -1;
     241              : }
     242              : 
     243              : /**
     244              :  * dlt_config_file_get_section_name_from_string
     245              :  *
     246              :  * Extract section name from line
     247              :  *
     248              :  * @param line  Line in configuration file containing a section header
     249              :  * @param name  Section name
     250              :  * @return 0 on success, else -1
     251              :  */
     252           40 : static int dlt_config_file_get_section_name_from_string(char *line, char *name)
     253              : {
     254              :     int i = 0;
     255              :     int j = 0;
     256              : 
     257           40 :     if ((line == NULL) || (name == NULL))
     258              :         return -1;
     259              : 
     260          386 :     for (i = 0; i < DLT_CONFIG_FILE_ENTRY_MAX_LEN; i++) {
     261          386 :         if ((line[i] == '[') || isspace(line[i]))
     262           40 :             continue;
     263          346 :         else if ((line[i] == ']') || (line[i] == '\n') || (line[i] == '\0'))
     264              :             break;
     265              :         else
     266          306 :             name[j++] = line[i];
     267              :     }
     268              : 
     269              :     return 0;
     270              : }
     271              : 
     272              : /**
     273              :  * dlt_config_file_get_key_value
     274              :  *
     275              :  * Get key and value from a line of configuration file
     276              :  *
     277              :  * @param line      Line on configuration file
     278              :  * @param[out] str1 String to be used as key
     279              :  * @param[out] str2 String to be used as value
     280              :  * @return 0 on success, else -1
     281              :  */
     282          339 : static int dlt_config_file_get_key_value(char *line, char *str1, char *str2)
     283              : {
     284              :     char *delimiter = "=";
     285              :     char *ptr;
     286              :     char *save_ptr;
     287              : 
     288          339 :     if ((line == NULL) || (str1 == NULL) || (str2 == NULL))
     289              :         return -1;
     290              : 
     291          339 :     ptr = strtok_r(line, delimiter, &save_ptr);
     292              : 
     293          339 :     if (ptr != NULL) { /* get key */
     294              :         strncpy(str1, ptr, DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1);
     295          339 :         str1[DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1] = '\0';
     296              :     } else {
     297              :         return -1;
     298              :     }
     299              : 
     300          339 :     ptr = strtok_r(NULL, delimiter, &save_ptr);
     301              : 
     302          339 :     if (ptr != NULL) {
     303              :         strncpy(str2, ptr, DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1);
     304          339 :         str2[DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1] = '\0';
     305              :     } else {
     306              :         return -1;
     307              :     }
     308              : 
     309          339 :     return 0;
     310              : }
     311              : 
     312              : /**
     313              :  * dlt_config_file_read_line
     314              :  *
     315              :  * Read line from configuration file
     316              :  *
     317              :  * @param       line Line from configuration file
     318              :  * @param[out]  str1 String contains section header or key
     319              :  * @param[out]  str2 String contains value or is empty
     320              :  * @return 0 on success, else -1
     321              :  */
     322          379 : static int dlt_config_file_read_line(char *line, char *str1, char *str2)
     323              : {
     324          379 :     if ((line == NULL) || (str1 == NULL) || (str2 == NULL))
     325              :         return -1;
     326              : 
     327              :     /* reset values to zero */
     328              :     memset(str1, 0, DLT_CONFIG_FILE_ENTRY_MAX_LEN);
     329              :     memset(str2, 0, DLT_CONFIG_FILE_ENTRY_MAX_LEN);
     330              : 
     331              :     /* check if line contains a section */
     332              :     if ((dlt_config_file_line_has_section(line)) == 0) {
     333              :         /* retrieve section name */
     334           40 :         if (dlt_config_file_get_section_name_from_string(line, str1) != 0)
     335              :             return -1;
     336              : 
     337              :         return DLT_CONFIG_FILE_NEW_SECTION;
     338              :     }
     339              : 
     340              :     /* copy strings as key value pair into str1, str2 */
     341          339 :     if (dlt_config_file_get_key_value(line, str1, str2) != 0)
     342              :         return -1;
     343              : 
     344              :     return DLT_CONFIG_FILE_NEW_DATA;
     345              : }
     346              : 
     347              : /**
     348              :  * dlt_config_file_read_file
     349              :  *
     350              :  * Read configuration file line by line and fill internal structures
     351              :  *
     352              :  * @param file DltConfigFile
     353              :  * @param hdl  FILE handle of opened configuration file
     354              :  */
     355           14 : static void dlt_config_file_read_file(DltConfigFile *file, FILE *hdl)
     356              : {
     357              :     int ret = 0;
     358           14 :     char line[DLT_CONFIG_FILE_LINE_MAX_LEN] = { '\0' };
     359           14 :     char str1[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = { '\0' };
     360           14 :     char str2[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = { '\0' };
     361              :     int line_number = 0;
     362              :     int is_section_valid = -1; /* to check if section name is given twice or invalid */
     363              : 
     364              :     /* read configuration file line by line */
     365          434 :     while (fgets(line, DLT_CONFIG_FILE_LINE_MAX_LEN, hdl) != NULL) {
     366          406 :         line_number++;
     367              : 
     368              :         /* ignore empty and comment lines */
     369           27 :         if (dlt_config_file_ignore_line(line) == 0)
     370           27 :             continue;
     371              : 
     372              :         /* trim line end */
     373          379 :         dlt_config_file_trim_line(line);
     374              : 
     375              :         /* parse content of line */
     376          379 :         ret = dlt_config_file_read_line(line, str1, str2);
     377              : 
     378          379 :         switch (ret) {
     379           40 :         case DLT_CONFIG_FILE_NEW_SECTION:     /* store str1 as new section */
     380              :             is_section_valid = -1;
     381              : 
     382           40 :             if ((ret = dlt_config_file_set_section(file, str1)) == 0)
     383              :                 is_section_valid = 0;
     384              : 
     385              :             break;
     386          339 :         case DLT_CONFIG_FILE_NEW_DATA:     /* store str1 and str2 as new data for section */
     387              : 
     388          339 :             if (is_section_valid == 0)
     389          339 :                 dlt_config_file_set_section_data(file, str1, str2);
     390              : 
     391              :             break;
     392            0 :         default:     /* something is wrong with the line */
     393            0 :             dlt_vlog(LOG_WARNING, "Line (%d) \"%s\" is invalid\n", line_number,
     394              :                      line);
     395              :         }
     396              :     }
     397           14 : }
     398              : 
     399              : /**
     400              :  * dlt_config_file_find_section
     401              :  *
     402              :  * Find a section
     403              :  *
     404              :  * @param file      DltConfigFile
     405              :  * @param section   Name of section
     406              :  * @return number of section on success, else -1
     407              :  */
     408          540 : static int dlt_config_file_find_section(const DltConfigFile *file,
     409              :                                         const char *section)
     410              : {
     411              :     int i = 0;
     412              : 
     413          540 :     if ((file == NULL) || (section == NULL) || (file->num_sections <= 0)) {
     414            0 :         dlt_log(LOG_WARNING, "Section cannot be found due to invalid parameters\n");
     415            0 :         return -1;
     416              :     }
     417              : 
     418         2490 :     for (i = 0; i < file->num_sections; i++) {
     419         2486 :         DltConfigFileSection *s = &file->sections[i];
     420              : 
     421         2486 :         if (strncmp(s->name, section, DLT_CONFIG_FILE_ENTRY_MAX_LEN) == 0)
     422          536 :             return i;
     423              :     }
     424              : 
     425              :     return -1;
     426              : }
     427              : 
     428              : /************************** interface implementation ***************************/
     429           14 : DltConfigFile *dlt_config_file_init(char *file_name)
     430              : {
     431              :     DltConfigFile *file;
     432              :     FILE *hdl = NULL;
     433              : 
     434           14 :     if ((file_name == NULL) || (strlen(file_name) >= DLT_PATH_MAX)) {
     435            0 :         dlt_log(LOG_ERR, "Given configuration file invalid\n");
     436            0 :         return NULL;
     437              :     }
     438              : 
     439           14 :     file = calloc(sizeof(DltConfigFile), 1);
     440              : 
     441           14 :     if (file == NULL) {
     442            0 :         dlt_log(LOG_ERR, "Setup internal data structure to parse config file failed\n");
     443            0 :         return NULL;
     444              :     }
     445              : 
     446           14 :     file->sections = calloc(sizeof(DltConfigFileSection), DLT_CONFIG_FILE_SECTIONS_MAX);
     447              : 
     448              :     /* open file */
     449           14 :     if ((hdl = fopen(file_name, "r")) == NULL) {
     450            0 :         dlt_log(LOG_ERR, "Cannot open configuration file\n");
     451            0 :         free(file);
     452            0 :         return NULL;
     453              :     }
     454              : 
     455           14 :     dlt_config_file_read_file(file, hdl);
     456              : 
     457              :     /* all information stored internally */
     458           14 :     fclose(hdl);
     459              : 
     460           14 :     return file;
     461              : }
     462              : 
     463           14 : void dlt_config_file_release(DltConfigFile *file)
     464              : {
     465              :     int i = 0;
     466              : 
     467           14 :     if (file != NULL) {
     468           14 :         int max = file->num_sections;
     469              : 
     470           54 :         for (i = 0; i < max; i++) {
     471           40 :             DltConfigFileSection *s = &file->sections[i];
     472           40 :             DltConfigKeyData *node = file->sections[i].list;
     473           40 :             free(s->name);
     474              : 
     475           40 :             if (s->keys != NULL)
     476           40 :                 free(s->keys);
     477              : 
     478          379 :             while (node) {
     479              :                 DltConfigKeyData *tmp = node;
     480          339 :                 node = node->next;
     481          339 :                 free(tmp->key);
     482          339 :                 free(tmp->data);
     483          339 :                 free(tmp);
     484              :             }
     485              :         }
     486              : 
     487           14 :         free(file->sections);
     488           14 :         free(file);
     489              :     }
     490           14 : }
     491              : 
     492           40 : int dlt_config_file_get_section_name(const DltConfigFile *file,
     493              :                                      int num,
     494              :                                      char *name)
     495              : {
     496           40 :     if ((file == NULL) || (name == NULL) || (num < 0) || (num >= file->num_sections))
     497              :         return -1;
     498              : 
     499           40 :     strncpy(name, (file->sections + num)->name, DLT_CONFIG_FILE_ENTRY_MAX_LEN);
     500           40 :     name[DLT_CONFIG_FILE_ENTRY_MAX_LEN - 1] = '\0';
     501              : 
     502           40 :     return 0;
     503              : }
     504              : 
     505           14 : int dlt_config_file_get_num_sections(const DltConfigFile *file, int *num)
     506              : {
     507           14 :     if ((file == NULL) || (file->num_sections < 0))
     508              :         return -1;
     509              : 
     510              :     /*
     511              :      * Note: Since General section could be used in configuration file,
     512              :      * this number could be also containing General section.
     513              :      */
     514           14 :     *num = file->num_sections;
     515              : 
     516           14 :     return 0;
     517              : }
     518              : 
     519          536 : int dlt_config_file_get_value(const DltConfigFile *file,
     520              :                               const char *section,
     521              :                               const char *key, char *value)
     522              : {
     523              :     DltConfigFileSection *s = NULL;
     524              :     DltConfigKeyData **tmp = NULL;
     525              :     int num_section = 0;
     526              : 
     527          536 :     if ((file == NULL) || (section == NULL) || (key == NULL) || (value == NULL))
     528              :         return -1;
     529              : 
     530              :     /* clean value */
     531              :     memset(value, 0, DLT_CONFIG_FILE_ENTRY_MAX_LEN);
     532              : 
     533          536 :     num_section = dlt_config_file_find_section(file, section);
     534              : 
     535          536 :     if (num_section == -1)
     536              :         return -1;
     537              : 
     538          536 :     s = (file->sections + num_section);
     539              : 
     540          536 :     tmp = &s->list;
     541              : 
     542         3465 :     while (*(tmp) != NULL) {
     543         3264 :         if (strncmp((*tmp)->key, key, DLT_CONFIG_FILE_ENTRY_MAX_LEN) == 0) {
     544          335 :             strncpy(value, (*tmp)->data, DLT_CONFIG_FILE_ENTRY_MAX_LEN);
     545          335 :             return 0;
     546              :         }
     547              :         else { /* not found yet see list for more */
     548         2929 :             tmp = &(*tmp)->next;
     549              :         }
     550              :     }
     551              : 
     552          201 :     dlt_vlog(LOG_WARNING, "Entry does not exist in section: %s\n", key);
     553          201 :     return -1;
     554              : }
     555              : 
     556            4 : int dlt_config_file_check_section_name_exists(const DltConfigFile *file,
     557              :                                              const char *name)
     558              : {
     559              :     int ret = 0;
     560              : 
     561            4 :     if ((file == NULL) || (file->num_sections <= 0) || (name == NULL))
     562              :         return -1;
     563              : 
     564            4 :     ret = dlt_config_file_find_section(file, name);
     565            4 :     if (ret == -1)
     566              :         return ret;
     567              : 
     568              :     return 0;
     569              : }
        

Generated by: LCOV version 2.0-1