LCOV - code coverage report
Current view: top level - console - dlt-convert.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 20.8 % 197 41
Test Date: 2025-12-23 11:07:30 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",
     154            0 :                         dir, strerror(errno));
     155            0 :                 if (files) {
     156            0 :                     for (int i = 0; i < n; i++)
     157            0 :                         if (files[i])
     158            0 :                             free(files[i]);
     159            0 :                     free(files);
     160              :                 }
     161            0 :                 return;
     162              :             }
     163            0 :             else if (n == 2)
     164              :                 printf("%s is already empty\n", dir);
     165              :             else {
     166            0 :                 for (int i = 2; i < n; i++) {
     167              :                     memset(tmp_filename, 0, FILENAME_SIZE);
     168              :                     /* Validate filename to prevent path traversal */
     169            0 :                     if (strstr(files[i]->d_name, "/") == NULL && strstr(files[i]->d_name, "..") == NULL) {
     170              :                         snprintf(tmp_filename, FILENAME_SIZE, "%s%s", dir, files[i]->d_name);
     171            0 :                         if (remove(tmp_filename) != 0)
     172            0 :                             fprintf(stderr, "ERROR: Failed to delete %s with error %s\n",
     173            0 :                                     tmp_filename, strerror(errno));
     174              :                     } else {
     175            0 :                         fprintf(stderr, "WARNING: Skipping suspicious filename: %s\n", files[i]->d_name);
     176              :                     }
     177              :                 }
     178              :             }
     179            0 :             if (files) {
     180            0 :                 for (int i = 0; i < n ; i++)
     181            0 :                     if (files[i]) {
     182            0 :                         free(files[i]);
     183            0 :                         files[i] = NULL;
     184              :                     }
     185            0 :                 free(files);
     186              :                 files = NULL;
     187              :             }
     188              :         }
     189              :         else
     190            0 :             fprintf(stderr, "ERROR: %s is not a directory\n", dir);
     191              :     }
     192              :     else
     193            0 :         fprintf(stderr, "ERROR: Failed to stat %s with error %s\n", dir, strerror(errno));
     194              : }
     195              : 
     196              : /**
     197              :  * Main function of tool.
     198              :  */
     199           18 : int main(int argc, char *argv[])
     200              : {
     201              :     int vflag = 0;
     202              :     int cflag = 0;
     203              :     int aflag = 0;
     204              :     int sflag = 0;
     205              :     int xflag = 0;
     206              :     int mflag = 0;
     207              :     int wflag = 0;
     208              :     int tflag = 0;
     209              :     char *fvalue = 0;
     210              :     char *bvalue = 0;
     211              :     char *evalue = 0;
     212              :     char *ovalue = 0;
     213              : 
     214              :     int index;
     215              :     int c;
     216              : 
     217              :     DltFile file;
     218              :     DltFilter filter;
     219              : 
     220              :     int ohandle = -1;
     221              : 
     222              :     int num, begin, end;
     223              : 
     224           18 :     char text[DLT_CONVERT_TEXTBUFSIZE] = { 0 };
     225              : 
     226              :     /* For handling compressed files */
     227           18 :     char tmp_filename[FILENAME_SIZE] = { 0 };
     228              :     struct stat st;
     229              :     memset(&st, 0, sizeof(struct stat));
     230           18 :     struct dirent **files = { 0 };
     231              :     int n = 0;
     232              : 
     233              :     struct iovec iov[2];
     234              :     int bytes_written = 0;
     235              :     int syserr = 0;
     236              : 
     237           18 :     opterr = 0;
     238              : 
     239           36 :     while ((c = getopt (argc, argv, "vcashxmwtf:b:e:o:")) != -1) {
     240           18 :         switch (c)
     241              :         {
     242              :         case 'v':
     243              :         {
     244              :             vflag = 1;
     245              :             break;
     246              :         }
     247            0 :         case 'c':
     248              :         {
     249              :             cflag = 1;
     250            0 :             break;
     251              :         }
     252           18 :         case 'a':
     253              :         {
     254              :             aflag = 1;
     255           18 :             break;
     256              :         }
     257            0 :         case 's':
     258              :         {
     259              :             sflag = 1;
     260            0 :             break;
     261              :         }
     262            0 :         case 'x':
     263              :         {
     264              :             xflag = 1;
     265            0 :             break;
     266              :         }
     267            0 :         case 'm':
     268              :         {
     269              :             mflag = 1;
     270            0 :             break;
     271              :         }
     272            0 :         case 'w':
     273              :         {
     274              :             wflag = 1;
     275            0 :             break;
     276              :         }
     277            0 :         case 't':
     278              :         {
     279              :             tflag = 1;
     280            0 :             break;
     281              :         }
     282            0 :         case 'h':
     283              :         {
     284            0 :             usage();
     285            0 :             return -1;
     286              :         }
     287            0 :         case 'f':
     288              :         {
     289            0 :             fvalue = optarg;
     290            0 :             break;
     291              :         }
     292            0 :         case 'b':
     293              :         {
     294            0 :             bvalue = optarg;
     295            0 :             break;
     296              :         }
     297            0 :         case 'e':
     298              :         {
     299            0 :             evalue = optarg;
     300            0 :             break;
     301              :         }
     302            0 :         case 'o':
     303              :         {
     304            0 :             ovalue = optarg;
     305            0 :             break;
     306              :         }
     307            0 :         case '?':
     308              :         {
     309            0 :             if ((optopt == 'f') || (optopt == 'b') || (optopt == 'e') || (optopt == 'o'))
     310            0 :                 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
     311            0 :             else if (isprint (optopt))
     312            0 :                 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
     313              :             else
     314            0 :                 fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
     315              : 
     316              :             /* unknown or wrong option used, show usage information and terminate */
     317            0 :             usage();
     318            0 :             return -1;
     319              :         }
     320              :         default:
     321              :         {
     322              :             return -1;    /*for parasoft */
     323              :         }
     324              :         }
     325              :     }
     326              : 
     327              :     /* Initialize structure to use DLT file */
     328           18 :     dlt_file_init(&file, vflag);
     329              : 
     330              :     /* first parse filter file if filter parameter is used */
     331           18 :     if (fvalue) {
     332            0 :         if (dlt_filter_load(&filter, fvalue, vflag) < DLT_RETURN_OK) {
     333            0 :             dlt_file_free(&file, vflag);
     334            0 :             return -1;
     335              :         }
     336              : 
     337            0 :         dlt_file_set_filter(&file, &filter, vflag);
     338              :     }
     339              : 
     340           18 :     if (ovalue) {
     341              :         ohandle = open(ovalue, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
     342              : 
     343            0 :         if (ohandle == -1) {
     344            0 :             dlt_file_free(&file, vflag);
     345            0 :             fprintf(stderr, "ERROR: Output file %s cannot be opened!\n", ovalue);
     346            0 :             return -1;
     347              :         }
     348              :     }
     349              : 
     350           18 :     if (tflag) {
     351              :         /* Prepare the temp dir to untar compressed files */
     352            0 :         if (mkdir(DLT_CONVERT_WS, 0700) != 0) {
     353            0 :             if (errno != EEXIST) {
     354            0 :                 fprintf(stderr,"ERROR: Cannot create temp dir %s!\n", DLT_CONVERT_WS);
     355            0 :                 if (ovalue) {
     356            0 :                     close(ohandle);
     357              :                     ohandle = -1;
     358              :                 }
     359            0 :                 return -1;
     360              :             }
     361              :         }
     362              :         else {
     363              :             if (S_ISDIR(st.st_mode))
     364              :                 empty_dir(DLT_CONVERT_WS);
     365              :             else
     366            0 :                 fprintf(stderr, "ERROR: %s is not a directory", DLT_CONVERT_WS);
     367              :         }
     368              : 
     369            0 :         for (index = optind; index < argc; index++) {
     370              :             /* Check extension of input file
     371              :              * If it is a compressed file, uncompress it
     372              :              */
     373            0 :             const char *file_ext = get_filename_ext(argv[index]);
     374            0 :             if (file_ext && strcmp(file_ext, DLT_EXTENSION) != 0) {
     375            0 :                 syserr = dlt_execute_command(NULL, "tar", "xf", argv[index], "-C", DLT_CONVERT_WS, NULL);
     376            0 :                 if (syserr != 0)
     377            0 :                     fprintf(stderr, "ERROR: Failed to uncompress %s to %s with error [%d]\n",
     378            0 :                             argv[index], DLT_CONVERT_WS, WIFEXITED(syserr));
     379              :             }
     380              :             else {
     381            0 :                 syserr = dlt_execute_command(NULL, "cp", argv[index], DLT_CONVERT_WS, NULL);
     382            0 :                 if (syserr != 0)
     383            0 :                     fprintf(stderr, "ERROR: Failed to copy %s to %s with error [%d]\n",
     384            0 :                             argv[index], DLT_CONVERT_WS, WIFEXITED(syserr));
     385              :             }
     386              : 
     387              :         }
     388              : 
     389            0 :         n = scandir(DLT_CONVERT_WS, &files, NULL, alphasort);
     390            0 :         if (n == -1) {
     391            0 :             fprintf(stderr,"ERROR: Cannot scan temp dir %s!\n", DLT_CONVERT_WS);
     392            0 :             if (ovalue) {
     393            0 :                 close(ohandle);
     394              :                 ohandle = -1;
     395              :             }
     396            0 :             return -1;
     397              :         }
     398              : 
     399              :         /* do not include ./ and ../ in the files */
     400            0 :         argc = optind + (n - 2);
     401              :     }
     402              : 
     403           35 :     for (index = optind; index < argc; index++) {
     404           18 :         if (tflag) {
     405              :             memset(tmp_filename, 0, FILENAME_SIZE);
     406              :             snprintf(tmp_filename, FILENAME_SIZE, "%s%s",
     407            0 :                     DLT_CONVERT_WS, files[index - optind + 2]->d_name);
     408              : 
     409            0 :             argv[index] = tmp_filename;
     410              :         }
     411              : 
     412              :         /* load, analyze data file and create index list */
     413           18 :         if (dlt_file_open(&file, argv[index], vflag) >= DLT_RETURN_OK) {
     414          526 :             while (dlt_file_read(&file, vflag) >= DLT_RETURN_OK) {
     415              :             }
     416              :         }
     417              : 
     418           18 :         if (aflag || sflag || xflag || mflag || ovalue) {
     419           18 :             if (bvalue)
     420              :                 begin = atoi(bvalue);
     421              :             else
     422              :                 begin = 0;
     423              : 
     424           18 :             if (evalue && (wflag == 0))
     425              :                 end = atoi(evalue);
     426              :             else
     427           18 :                 end = file.counter - 1;
     428              : 
     429           18 :             if ((begin < 0) || (begin >= file.counter)) {
     430            1 :                 fprintf(stderr, "ERROR: Selected first message %d is out of range!\n", begin);
     431            1 :                 if (ovalue) {
     432            0 :                     close(ohandle);
     433              :                     ohandle = -1;
     434              :                 }
     435            1 :                 dlt_file_free(&file, vflag);
     436            1 :                 return -1;
     437              :             }
     438              : 
     439           17 :             if ((end < 0) || (end >= file.counter) || (end < begin)) {
     440            0 :                 fprintf(stderr, "ERROR: Selected end message %d is out of range!\n", end);
     441            0 :                 if (ovalue) {
     442            0 :                     close(ohandle);
     443              :                     ohandle = -1;
     444              :                 }
     445            0 :                 dlt_file_free(&file, vflag);
     446            0 :                 return -1;
     447              :             }
     448              : 
     449          526 :             for (num = begin; num <= end; num++) {
     450          509 :                 if (dlt_file_message(&file, num, vflag) < DLT_RETURN_OK)
     451            0 :                     continue;
     452              : 
     453          509 :                 if (xflag) {
     454              :                     printf("%d ", num);
     455            0 :                     if (dlt_message_print_hex(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK)
     456            0 :                         continue;
     457              :                 }
     458          509 :                 else if (aflag) {
     459              :                     printf("%d ", num);
     460              : 
     461          509 :                     if (dlt_message_header(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK)
     462            0 :                         continue;
     463              : 
     464              :                     printf("%s ", text);
     465              : 
     466          509 :                     if (dlt_message_payload(&file.msg, text, DLT_CONVERT_TEXTBUFSIZE, DLT_OUTPUT_ASCII, vflag) < DLT_RETURN_OK)
     467            0 :                         continue;
     468              : 
     469              :                     printf("[%s]\n", text);
     470              :                 }
     471            0 :                 else if (mflag) {
     472              :                     printf("%d ", num);
     473            0 :                     if (dlt_message_print_mixed_plain(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK)
     474            0 :                         continue;
     475              :                 }
     476            0 :                 else if (sflag) {
     477              :                     printf("%d ", num);
     478              : 
     479            0 :                     if (dlt_message_header(&(file.msg), text, DLT_CONVERT_TEXTBUFSIZE, vflag) < DLT_RETURN_OK)
     480            0 :                         continue;
     481              : 
     482              :                     printf("%s \n", text);
     483              :                 }
     484              : 
     485              :                 /* if file output enabled write message */
     486          509 :                 if (ovalue) {
     487            0 :                     iov[0].iov_base = file.msg.headerbuffer;
     488            0 :                     iov[0].iov_len = (uint32_t) file.msg.headersize;
     489            0 :                     iov[1].iov_base = file.msg.databuffer;
     490            0 :                     iov[1].iov_len = (uint32_t) file.msg.datasize;
     491              : 
     492            0 :                     bytes_written =(int) writev(ohandle, iov, 2);
     493              : 
     494            0 :                     if (0 > bytes_written) {
     495              :                         printf("in main: writev(ohandle, iov, 2); returned an error!");
     496            0 :                         close(ohandle);
     497              :                         ohandle = -1;
     498            0 :                         dlt_file_free(&file, vflag);
     499            0 :                         return -1;
     500              :                     }
     501              :                 }
     502              : 
     503              :                 /* check for new messages if follow flag set */
     504          509 :                 if (wflag && (num == end)) {
     505              :                     while (1) {
     506            0 :                         while (dlt_file_read(&file, 0) >= 0){
     507              :                         }
     508              : 
     509            0 :                         if (end == (file.counter - 1)) {
     510              :                             /* Sleep if no new message was received */
     511              :                             struct timespec req;
     512            0 :                             req.tv_sec = 0;
     513            0 :                             req.tv_nsec = 100000000;
     514            0 :                             nanosleep(&req, NULL);
     515              :                         }
     516              :                         else {
     517              :                             /* set new end of log file and continue reading */
     518              :                             end = file.counter - 1;
     519              :                             break;
     520              :                         }
     521              :                     }
     522              :                 }
     523              :             }
     524              :         }
     525              : 
     526           17 :         if (cflag) {
     527            0 :             printf("Total number of messages: %d\n", file.counter_total);
     528              : 
     529            0 :             if (file.filter)
     530            0 :                 printf("Filtered number of messages: %d\n", file.counter);
     531              :         }
     532              :     }
     533              : 
     534           17 :     if (ovalue) {
     535            0 :         close(ohandle);
     536              :         ohandle = -1;
     537              :     }
     538              : 
     539           17 :     if (tflag) {
     540            0 :         empty_dir(DLT_CONVERT_WS);
     541            0 :         if (files) {
     542            0 :             for (int i = 0; i < n ; i++)
     543            0 :                 if (files[i])
     544            0 :                     free(files[i]);
     545              : 
     546            0 :             free(files);
     547              :         }
     548            0 :         rmdir(DLT_CONVERT_WS);
     549              :     }
     550           17 :     if (index == optind) {
     551              :         /* no file selected, show usage and terminate */
     552            0 :         fprintf(stderr, "ERROR: No file selected\n");
     553            0 :         usage();
     554            0 :         return -1;
     555              :     }
     556              : 
     557           17 :     dlt_file_free(&file, vflag);
     558              : 
     559           17 :     return 0;
     560              : }
        

Generated by: LCOV version 2.0-1