LCOV - code coverage report
Current view: top level - console - dlt-convert.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 18.9 % 196 37
Test Date: 2026-08-27 10:11:10 Functions: 33.3 % 3 1

            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 Alexander Wenzel <alexander.aw.wenzel@bmw.de>
      18              :  *
      19              :  * \copyright Copyright © 2011-2015 BMW AG. \n
      20              :  * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
      21              :  *
      22              :  * \file dlt-convert.c
      23              :  */
      24              : 
      25              : /*******************************************************************************
      26              : **                                                                            **
      27              : **  SRC-MODULE: dlt-convert.c                                                 **
      28              : **                                                                            **
      29              : **  TARGET    : linux                                                         **
      30              : **                                                                            **
      31              : **  PROJECT   : DLT                                                           **
      32              : **                                                                            **
      33              : **  AUTHOR    : Alexander Wenzel Alexander.AW.Wenzel@bmw.de                   **
      34              : **              Markus Klein                                                  **
      35              : **                                                                            **
      36              : **  PURPOSE   :                                                               **
      37              : **                                                                            **
      38              : **  REMARKS   :                                                               **
      39              : **                                                                            **
      40              : **  PLATFORM DEPENDANT [yes/no]: yes                                          **
      41              : **                                                                            **
      42              : **  TO BE CHANGED BY USER [yes/no]: no                                        **
      43              : **                                                                            **
      44              : *******************************************************************************/
      45              : 
      46              : /*******************************************************************************
      47              : **                      Author Identity                                       **
      48              : ********************************************************************************
      49              : **                                                                            **
      50              : ** Initials     Name                       Company                            **
      51              : ** --------     -------------------------  ---------------------------------- **
      52              : **  aw          Alexander Wenzel           BMW                                **
      53              : **  mk          Markus Klein               Fraunhofer ESK                     **
      54              : *******************************************************************************/
      55              : 
      56              : /*******************************************************************************
      57              : **                      Author Identity                                       **
      58              : ********************************************************************************
      59              : **                                                                            **
      60              : ** Initials     Name                       Company                            **
      61              : ** --------     -------------------------  ---------------------------------- **
      62              : **  aw          Alexander Wenzel           BMW                                **
      63              : *******************************************************************************/
      64              : 
      65              : /*******************************************************************************
      66              : **                      Revision Control History                              **
      67              : *******************************************************************************/
      68              : 
      69              : /*
      70              :  * $LastChangedRevision: 1670 $
      71              :  * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $
      72              :  * $LastChangedBy$
      73              :  * Initials    Date         Comment
      74              :  * aw          13.01.2010   initial
      75              :  */
      76              : 
      77              : #include <dirent.h>
      78              : #include <getopt.h>
      79              : #include <stdio.h>
      80              : #include <stdlib.h>
      81              : #include <unistd.h>
      82              : #include <string.h>
      83              : #include <ctype.h>
      84              : #include <errno.h>
      85              : 
      86              : #include <sys/stat.h>
      87              : #include <fcntl.h>
      88              : 
      89              : #include <sys/uio.h> /* writev() */
      90              : 
      91              : #include "dlt_common.h"
      92              : 
      93              : #define COMMAND_SIZE 1024  /* Size of command */
      94              : #define FILENAME_SIZE 1024 /* Size of filename */
      95              : #define DLT_EXTENSION "dlt"
      96              : #define DLT_CONVERT_WS "/tmp/dlt_convert_workspace/"
      97              : 
      98              : /**
      99              :  * Print usage information of tool.
     100              :  */
     101            0 : void usage(void)
     102              : {
     103              :     char version[DLT_CONVERT_TEXTBUFSIZE];
     104              : 
     105            0 :     dlt_get_version(version, 255);
     106              : 
     107              :     printf("Usage: dlt-convert [options] [commands] file1 [file2]\n");
     108              :     printf("Read DLT files, print DLT messages as ASCII and store the messages again.\n");
     109              :     printf("Use filters to filter DLT messages.\n");
     110              :     printf("Use Ranges and Output file to cut DLT files.\n");
     111              :     printf("Use two files and Output file to join DLT files.\n");
     112              :     printf("%s \n", version);
     113              :     printf("Commands:\n");
     114              :     printf("  -h            Usage\n");
     115              :     printf("  -a            Print DLT file; payload as ASCII\n");
     116              :     printf("  -x            Print DLT file; payload as hex\n");
     117              :     printf("  -m            Print DLT file; payload as hex and ASCII\n");
     118              :     printf("  -s            Print DLT file; only headers\n");
     119              :     printf("  -o filename   Output messages in new DLT file\n");
     120              :     printf("Options:\n");
     121              :     printf("  -v            Verbose mode\n");
     122              :     printf("  -c            Count number of messages\n");
     123              :     printf("  -f filename   Enable filtering of messages\n");
     124              :     printf("  -b number     First <number> messages to be handled\n");
     125              :     printf("  -e number     Last <number> messages to be handled\n");
     126              :     printf("  -w            Follow dlt file while file is increasing\n");
     127              :     printf("  -t            Handling input compressed files (tar.gz)\n");
     128            0 : }
     129              : 
     130            0 : void empty_dir(const char* dir)
     131              : {
     132            0 :     struct dirent** files = {0};
     133              :     struct stat st;
     134            0 :     char tmp_filename[FILENAME_SIZE] = {0};
     135              : 
     136            0 :     if (dir == NULL) {
     137            0 :         fprintf(stderr, "ERROR: %s: invalid arguments\n", __func__);
     138            0 :         return;
     139              :     }
     140              : 
     141            0 :     if (stat(dir, &st) == 0) {
     142            0 :         if (S_ISDIR(st.st_mode)) {
     143            0 :             int n = scandir(dir, &files, NULL, alphasort);
     144            0 :             if (n < 0) {
     145            0 :                 fprintf(stderr, "ERROR: Failed to scan %s with error %s\n", dir, strerror(errno));
     146            0 :                 if (files) {
     147            0 :                     free(files);
     148              :                 }
     149            0 :                 return;
     150              :             }
     151              :             /* Do not include /. and /.. */
     152            0 :             if (n < 2) {
     153            0 :                 fprintf(stderr, "ERROR: Failed to scan %s with error %s\n", dir, strerror(errno));
     154            0 :                 if (files) {
     155            0 :                     for (int i = 0; i < n; i++)
     156            0 :                         if (files[i])
     157            0 :                             free(files[i]);
     158            0 :                     free(files);
     159              :                 }
     160            0 :                 return;
     161            0 :             } else if (n == 2)
     162              :                 printf("%s is already empty\n", dir);
     163              :             else {
     164            0 :                 for (int i = 2; i < n; i++) {
     165              :                     memset(tmp_filename, 0, FILENAME_SIZE);
     166              :                     /* Validate filename to prevent path traversal */
     167            0 :                     if (strstr(files[i]->d_name, "/") == NULL && strstr(files[i]->d_name, "..") == NULL) {
     168              :                         snprintf(tmp_filename, FILENAME_SIZE, "%s%s", dir, files[i]->d_name);
     169            0 :                         if (remove(tmp_filename) != 0)
     170            0 :                             fprintf(
     171            0 :                                 stderr, "ERROR: Failed to delete %s with error %s\n", tmp_filename, strerror(errno));
     172              :                     } else {
     173            0 :                         fprintf(stderr, "WARNING: Skipping suspicious filename: %s\n", files[i]->d_name);
     174              :                     }
     175              :                 }
     176              :             }
     177            0 :             if (files) {
     178            0 :                 for (int i = 0; i < n; i++)
     179            0 :                     if (files[i]) {
     180            0 :                         free(files[i]);
     181            0 :                         files[i] = NULL;
     182              :                     }
     183            0 :                 free(files);
     184              :                 files = NULL;
     185              :             }
     186              :         } else
     187            0 :             fprintf(stderr, "ERROR: %s is not a directory\n", dir);
     188              :     } else
     189            0 :         fprintf(stderr, "ERROR: Failed to stat %s with error %s\n", dir, strerror(errno));
     190              : }
     191              : 
     192              : /**
     193              :  * Main function of tool.
     194              :  */
     195            6 : int main(int argc, char* argv[])
     196              : {
     197              :     int vflag = 0;
     198              :     int cflag = 0;
     199              :     int aflag = 0;
     200              :     int sflag = 0;
     201              :     int xflag = 0;
     202              :     int mflag = 0;
     203              :     int wflag = 0;
     204              :     int tflag = 0;
     205              :     char* fvalue = 0;
     206              :     char* bvalue = 0;
     207              :     char* evalue = 0;
     208              :     char* ovalue = 0;
     209              : 
     210              :     int index;
     211              :     int c;
     212              : 
     213              :     DltFile file;
     214              :     DltFilter filter;
     215              : 
     216              :     int ohandle = -1;
     217              : 
     218              :     int num, begin, end;
     219              : 
     220            6 :     char text[DLT_CONVERT_TEXTBUFSIZE] = {0};
     221              : 
     222              :     /* For handling compressed files */
     223            6 :     char tmp_filename[FILENAME_SIZE] = {0};
     224              :     struct stat st;
     225              :     memset(&st, 0, sizeof(struct stat));
     226            6 :     struct dirent** files = {0};
     227              :     int n = 0;
     228              : 
     229              :     struct iovec iov[2];
     230              :     int bytes_written = 0;
     231              :     int syserr = 0;
     232              : 
     233            6 :     opterr = 0;
     234              : 
     235           12 :     while ((c = getopt(argc, argv, "vcashxmwtf:b:e:o:")) != -1) {
     236            6 :         switch (c) {
     237              :         case 'v': {
     238              :             vflag = 1;
     239              :             break;
     240              :         }
     241            0 :         case 'c': {
     242              :             cflag = 1;
     243            0 :             break;
     244              :         }
     245            6 :         case 'a': {
     246              :             aflag = 1;
     247            6 :             break;
     248              :         }
     249            0 :         case 's': {
     250              :             sflag = 1;
     251            0 :             break;
     252              :         }
     253            0 :         case 'x': {
     254              :             xflag = 1;
     255            0 :             break;
     256              :         }
     257            0 :         case 'm': {
     258              :             mflag = 1;
     259            0 :             break;
     260              :         }
     261            0 :         case 'w': {
     262              :             wflag = 1;
     263            0 :             break;
     264              :         }
     265            0 :         case 't': {
     266              :             tflag = 1;
     267            0 :             break;
     268              :         }
     269            0 :         case 'h': {
     270            0 :             usage();
     271            0 :             return -1;
     272              :         }
     273            0 :         case 'f': {
     274            0 :             fvalue = optarg;
     275            0 :             break;
     276              :         }
     277            0 :         case 'b': {
     278            0 :             bvalue = optarg;
     279            0 :             break;
     280              :         }
     281            0 :         case 'e': {
     282            0 :             evalue = optarg;
     283            0 :             break;
     284              :         }
     285            0 :         case 'o': {
     286            0 :             ovalue = optarg;
     287            0 :             break;
     288              :         }
     289            0 :         case '?': {
     290            0 :             if ((optopt == 'f') || (optopt == 'b') || (optopt == 'e') || (optopt == 'o'))
     291            0 :                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
     292            0 :             else if (isprint(optopt))
     293            0 :                 fprintf(stderr, "Unknown option `-%c'.\n", optopt);
     294              :             else
     295            0 :                 fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
     296              : 
     297              :             /* unknown or wrong option used, show usage information and terminate */
     298            0 :             usage();
     299            0 :             return -1;
     300              :         }
     301              :         default: {
     302              :             return -1; /*for parasoft */
     303              :         }
     304              :         }
     305              :     }
     306              : 
     307              :     /* Initialize structure to use DLT file */
     308            6 :     dlt_file_init(&file, vflag);
     309              : 
     310              :     /* first parse filter file if filter parameter is used */
     311            6 :     if (fvalue) {
     312            0 :         if (dlt_filter_load(&filter, fvalue, vflag) < DLT_RETURN_OK) {
     313            0 :             dlt_file_free(&file, vflag);
     314            0 :             return -1;
     315              :         }
     316              : 
     317            0 :         dlt_file_set_filter(&file, &filter, vflag);
     318              :     }
     319              : 
     320            6 :     if (ovalue) {
     321              :         ohandle = open(ovalue, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
     322              : 
     323            0 :         if (ohandle == -1) {
     324            0 :             dlt_file_free(&file, vflag);
     325            0 :             fprintf(stderr, "ERROR: Output file %s cannot be opened!\n", ovalue);
     326            0 :             return -1;
     327              :         }
     328              :     }
     329              : 
     330            6 :     if (tflag) {
     331              :         /* Prepare the temp dir to untar compressed files */
     332            0 :         if (mkdir(DLT_CONVERT_WS, 0700) != 0) {
     333            0 :             if (errno != EEXIST) {
     334            0 :                 fprintf(stderr, "ERROR: Cannot create temp dir %s!\n", DLT_CONVERT_WS);
     335            0 :                 if (ovalue) {
     336            0 :                     close(ohandle);
     337              :                     ohandle = -1;
     338              :                 }
     339            0 :                 return -1;
     340              :             }
     341              :         } else {
     342              :             if (S_ISDIR(st.st_mode))
     343              :                 empty_dir(DLT_CONVERT_WS);
     344              :             else
     345            0 :                 fprintf(stderr, "ERROR: %s is not a directory", DLT_CONVERT_WS);
     346              :         }
     347              : 
     348            0 :         for (index = optind; index < argc; index++) {
     349              :             /* Check extension of input file
     350              :              * If it is a compressed file, uncompress it
     351              :              */
     352            0 :             const char* file_ext = get_filename_ext(argv[index]);
     353            0 :             if (file_ext && strcmp(file_ext, DLT_EXTENSION) != 0) {
     354            0 :                 syserr = dlt_execute_command(NULL, "tar", "xf", argv[index], "-C", DLT_CONVERT_WS, NULL);
     355            0 :                 if (syserr != 0)
     356            0 :                     fprintf(
     357              :                         stderr, "ERROR: Failed to uncompress %s to %s with error [%d]\n", argv[index], DLT_CONVERT_WS,
     358            0 :                         WIFEXITED(syserr));
     359              :             } else {
     360            0 :                 syserr = dlt_execute_command(NULL, "cp", argv[index], DLT_CONVERT_WS, NULL);
     361            0 :                 if (syserr != 0)
     362            0 :                     fprintf(
     363              :                         stderr, "ERROR: Failed to copy %s to %s with error [%d]\n", argv[index], DLT_CONVERT_WS,
     364            0 :                         WIFEXITED(syserr));
     365              :             }
     366              :         }
     367              : 
     368            0 :         n = scandir(DLT_CONVERT_WS, &files, NULL, alphasort);
     369            0 :         if (n == -1) {
     370            0 :             fprintf(stderr, "ERROR: Cannot scan temp dir %s!\n", DLT_CONVERT_WS);
     371            0 :             if (ovalue) {
     372            0 :                 close(ohandle);
     373              :                 ohandle = -1;
     374              :             }
     375            0 :             return -1;
     376              :         }
     377              : 
     378              :         /* do not include ./ and ../ in the files */
     379            0 :         argc = optind + (n - 2);
     380              :     }
     381              : 
     382           37 :     for (index = optind; index < argc; index++) {
     383           31 :         if (tflag) {
     384              :             memset(tmp_filename, 0, FILENAME_SIZE);
     385              : #if defined(__GNUC__) && __GNUC__ >= 7
     386              : #pragma GCC diagnostic push
     387              : #pragma GCC diagnostic ignored "-Wformat-truncation"
     388              : #endif
     389            0 :             snprintf(tmp_filename, FILENAME_SIZE, "%s%s", DLT_CONVERT_WS, files[index - optind + 2]->d_name);
     390              : #if defined(__GNUC__) && __GNUC__ >= 7
     391              : #pragma GCC diagnostic pop
     392              : #endif
     393              : 
     394            0 :             argv[index] = tmp_filename;
     395              :         }
     396              : 
     397              :         /* load, analyze data file and create index list */
     398           31 :         if (dlt_file_open(&file, argv[index], vflag) >= DLT_RETURN_OK) {
     399          643 :             while (dlt_file_read(&file, vflag) >= DLT_RETURN_OK) { }
     400              :         }
     401              : 
     402           31 :         if (aflag || sflag || xflag || mflag || ovalue) {
     403           31 :             if (bvalue)
     404              :                 begin = atoi(bvalue);
     405              :             else
     406              :                 begin = 0;
     407              : 
     408           31 :             if (evalue && (wflag == 0))
     409              :                 end = atoi(evalue);
     410              :             else
     411           31 :                 end = file.counter - 1;
     412              : 
     413           31 :             if ((begin < 0) || (begin >= file.counter)) {
     414            0 :                 fprintf(stderr, "ERROR: Selected first message %d is out of range!\n", begin);
     415            0 :                 if (ovalue) {
     416            0 :                     close(ohandle);
     417              :                     ohandle = -1;
     418              :                 }
     419            0 :                 dlt_file_free(&file, vflag);
     420            0 :                 return -1;
     421              :             }
     422              : 
     423           31 :             if ((end < 0) || (end >= file.counter) || (end < begin)) {
     424            0 :                 fprintf(stderr, "ERROR: Selected end message %d is out of range!\n", end);
     425            0 :                 if (ovalue) {
     426            0 :                     close(ohandle);
     427              :                     ohandle = -1;
     428              :                 }
     429            0 :                 dlt_file_free(&file, vflag);
     430            0 :                 return -1;
     431              :             }
     432              : 
     433          643 :             for (num = begin; num <= end; num++) {
     434          612 :                 if (dlt_file_message(&file, num, vflag) < DLT_RETURN_OK)
     435            0 :                     continue;
     436              : 
     437          612 :                 if (xflag) {
     438              :                     printf("%d ", num);
     439            0 :                     if (dlt_message_print_hex(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK)
     440            0 :                         continue;
     441          612 :                 } else if (aflag) {
     442              :                     printf("%d ", num);
     443              : 
     444          612 :                     if (dlt_message_header(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK)
     445            0 :                         continue;
     446              : 
     447              :                     printf("%s ", text);
     448              : 
     449          612 :                     if (dlt_message_payload(&file.msg, text, DLT_CONVERT_TEXTBUFSIZE, DLT_OUTPUT_ASCII, vflag)
     450              :                         < DLT_RETURN_OK)
     451            0 :                         continue;
     452              : 
     453              :                     printf("[%s]\n", text);
     454            0 :                 } else if (mflag) {
     455              :                     printf("%d ", num);
     456            0 :                     if (dlt_message_print_mixed_plain(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag)
     457              :                         < DLT_RETURN_OK)
     458            0 :                         continue;
     459            0 :                 } else if (sflag) {
     460              :                     printf("%d ", num);
     461              : 
     462            0 :                     if (dlt_message_header(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK)
     463            0 :                         continue;
     464              : 
     465              :                     printf("%s \n", text);
     466              :                 }
     467              : 
     468              :                 /* if file output enabled write message */
     469          612 :                 if (ovalue) {
     470            0 :                     iov[0].iov_base = file.msg.headerbuffer;
     471            0 :                     iov[0].iov_len = (uint32_t)file.msg.headersize;
     472            0 :                     iov[1].iov_base = file.msg.databuffer;
     473            0 :                     iov[1].iov_len = (uint32_t)file.msg.datasize;
     474              : 
     475            0 :                     bytes_written = (int)writev(ohandle, iov, 2);
     476              : 
     477            0 :                     if (0 > bytes_written) {
     478              :                         printf("in main: writev(ohandle, iov, 2); returned an error!");
     479            0 :                         close(ohandle);
     480              :                         ohandle = -1;
     481            0 :                         dlt_file_free(&file, vflag);
     482            0 :                         return -1;
     483              :                     }
     484              :                 }
     485              : 
     486              :                 /* check for new messages if follow flag set */
     487          612 :                 if (wflag && (num == end)) {
     488              :                     while (1) {
     489            0 :                         while (dlt_file_read(&file, 0) >= 0) { }
     490              : 
     491            0 :                         if (end == (file.counter - 1)) {
     492              :                             /* Sleep if no new message was received */
     493              :                             struct timespec req;
     494            0 :                             req.tv_sec = 0;
     495            0 :                             req.tv_nsec = 100000000;
     496            0 :                             nanosleep(&req, NULL);
     497              :                         } else {
     498              :                             /* set new end of log file and continue reading */
     499              :                             end = file.counter - 1;
     500              :                             break;
     501              :                         }
     502              :                     }
     503              :                 }
     504              :             }
     505              :         }
     506              : 
     507           31 :         if (cflag) {
     508            0 :             printf("Total number of messages: %d\n", file.counter_total);
     509              : 
     510            0 :             if (file.filter)
     511            0 :                 printf("Filtered number of messages: %d\n", file.counter);
     512              :         }
     513              :     }
     514              : 
     515            6 :     if (ovalue) {
     516            0 :         close(ohandle);
     517              :         ohandle = -1;
     518              :     }
     519              : 
     520            6 :     if (tflag) {
     521            0 :         empty_dir(DLT_CONVERT_WS);
     522            0 :         if (files) {
     523            0 :             for (int i = 0; i < n; i++)
     524            0 :                 if (files[i])
     525            0 :                     free(files[i]);
     526              : 
     527            0 :             free(files);
     528              :         }
     529            0 :         rmdir(DLT_CONVERT_WS);
     530              :     }
     531            6 :     if (index == optind) {
     532              :         /* no file selected, show usage and terminate */
     533            0 :         fprintf(stderr, "ERROR: No file selected\n");
     534            0 :         usage();
     535            0 :         return -1;
     536              :     }
     537              : 
     538            6 :     dlt_file_free(&file, vflag);
     539              : 
     540            6 :     return 0;
     541              : }
        

Generated by: LCOV version 2.0-1