Fixed: all possible malloc, sprintf and strcpy problems
[profile/ivi/dlt-daemon.git] / src / shared / dlt_offline_trace.c
1 /**
2  * @licence app begin@
3  * Copyright (C) 2012  BMW AG
4  *
5  * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
6  *
7  * Contributions are licensed to the GENIVI Alliance under one or more
8  * Contribution License Agreements.
9  *
10  * \copyright
11  * This Source Code Form is subject to the terms of the
12  * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed with
13  * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
14  *
15  *
16  * \author Alexander Wenzel <alexander.aw.wenzel@bmw.de> BMW 2011-2012
17  *
18  * \file dlt_offline_trace.c
19  * For further information see http://www.genivi.org/.
20  * @licence end@
21  */
22
23
24 /*******************************************************************************
25 **                                                                            **
26 **  SRC-MODULE: dlt_offline_trace.c                                           **
27 **                                                                            **
28 **  TARGET    : linux                                                         **
29 **                                                                            **
30 **  PROJECT   : DLT                                                           **
31 **                                                                            **
32 **  AUTHOR    : Alexander Wenzel Alexander.AW.Wenzel@bmw.de                   **
33 **                                                                            **
34 **  PURPOSE   :                                                               **
35 **                                                                            **
36 **  REMARKS   :                                                               **
37 **                                                                            **
38 **  PLATFORM DEPENDANT [yes/no]: yes                                          **
39 **                                                                            **
40 **  TO BE CHANGED BY USER [yes/no]: no                                        **
41 **                                                                            **
42 *******************************************************************************/
43
44 /*******************************************************************************
45 **                      Author Identity                                       **
46 ********************************************************************************
47 **                                                                            **
48 ** Initials     Name                       Company                            **
49 ** --------     -------------------------  ---------------------------------- **
50 **  aw          Alexander Wenzel           BMW                                **
51 *******************************************************************************/
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <time.h>
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 #include <fcntl.h>
60 #include <unistd.h>
61 #include <dirent.h>
62    
63 #include <dlt_offline_trace.h>
64
65 int dlt_offline_trace_create_new_file(DltOfflineTrace *trace) {
66     time_t t;
67     struct tm *tmp;
68     char outstr[200];
69
70         /* set filename */
71     t = time(NULL);
72     tmp = localtime(&t);
73     if (NULL == tmp) {
74         printf("dlt_offline_trace_create_new_file: pointer to tmp is NULL!");
75         return -1;
76     }
77     if (strftime(outstr, sizeof(outstr),"%Y%m%d_%H%M%S", tmp) == 0) {
78     }
79         snprintf(trace->filename,NAME_MAX + 1,"%s/dlt_offlinetrace_%s.dlt",trace->directory,outstr);
80
81     /* open DLT output file */
82         trace->ohandle = open(trace->filename,O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
83         if (trace->ohandle == -1)
84         {
85                 /* trace file cannot be opened */
86                 printf("Offline trace file %s cannot be created\n",trace->filename);
87                 return -1;
88         } /* if */
89
90         return 0; /* OK */      
91 }
92
93 unsigned long dlt_offline_trace_get_total_size(DltOfflineTrace *trace) {
94         struct dirent *dp;
95         char filename[256];
96         unsigned long size = 0;
97         struct stat status;
98
99         /* go through all dlt files in directory */
100         DIR *dir = opendir(trace->directory);
101         while ((dp=readdir(dir)) != NULL) {
102         if(strstr(dp->d_name,".dlt"))
103         {
104             int res = snprintf(filename, sizeof(filename), "%s/%s",trace->directory,dp->d_name);
105             // if the total length of the string is greater than the buffer, silently forget it.
106             // snprintf: a return value of size  or more means that the output was truncated
107             //           if an output error is encountered, a negative value is returned.
108             if( (unsigned int)res<sizeof(filename) && res>0 )
109             {
110                 if(0 == stat(filename,&status))
111                 {
112                         size += status.st_size;
113                 }
114                 else
115                         printf("Offline trace file %s cannot be stat-ed",filename);
116             }
117             //else
118             //{
119             //    dlt_log(3, "dlt_offline_trace_get_total_size: long filename ignored");
120             //}
121         }
122     }
123
124         closedir(dir);
125         
126         /* return size */
127         return size; 
128 }
129
130 int dlt_offline_trace_delete_oldest_file(DltOfflineTrace *trace) {
131         struct dirent *dp;
132         char filename[PATH_MAX+1];
133         char filename_oldest[PATH_MAX+1];
134         unsigned long size_oldest = 0;
135         struct stat status;
136         time_t time_oldest = 0;
137
138         filename[0] = 0;
139         filename_oldest[0] = 0;
140
141         /* go through all dlt files in directory */
142         DIR *dir = opendir(trace->directory);
143         while ((dp=readdir(dir)) != NULL) {
144                 if(strstr(dp->d_name,".dlt")) {
145                         int res = snprintf(filename, sizeof(filename), "%s/%s",trace->directory,dp->d_name);
146                                 // if the total length of the string is greater than the buffer, silently forget it.
147                                 // snprintf: a return value of size  or more means that the output was truncated
148                                 //           if an output error is encountered, a negative value is returned.
149                                 if( (unsigned int)res<sizeof(filename) && res>0 )
150                                 {
151                                         if(0 == stat(filename,&status))
152                                         {
153                                                 if(time_oldest == 0 || status.st_mtime < time_oldest) {
154                                                                 time_oldest = status.st_mtime;
155                                                                 size_oldest = status.st_size;
156                                                                 strncpy(filename_oldest,filename,PATH_MAX);
157                                                                 filename_oldest[PATH_MAX]=0;
158                                                 }
159                                         }
160                                         else
161                                                 printf("Old offline trace file %s cannot be stat-ed",filename);
162                                 }
163                 }
164         }       
165         closedir(dir);
166         
167         /* delete file */
168         if(filename_oldest[0]) {
169                 if(remove(filename_oldest)) {
170                         printf("Remove file %s failed!\n",filename_oldest);
171                         return -1; /* ERROR */
172                 }
173         }
174         else {
175                         printf("No file to be removed!\n");
176                         return -1; /* ERROR */
177         }
178         
179         /* return size of deleted file*/
180         return size_oldest; 
181 }
182
183 int dlt_offline_trace_check_size(DltOfflineTrace *trace) {
184         
185         /* check size of complete offline trace */
186         while((int)dlt_offline_trace_get_total_size(trace) > (trace->maxSize-trace->fileSize))
187         {
188                 /* remove oldest files as long as new file will not fit in completely into complete offline trace */
189                 if(dlt_offline_trace_delete_oldest_file(trace)<0) {
190                         return -1;
191                 }
192         }
193         
194         return 0; /* OK */      
195 }
196         
197 int dlt_offline_trace_init(DltOfflineTrace *trace,const char *directory,int fileSize,int maxSize) {
198
199         /* init parameters */
200     strncpy(trace->directory,directory,NAME_MAX);
201     trace->directory[NAME_MAX]=0;
202         trace->fileSize = fileSize;
203         trace->maxSize = maxSize;
204
205         /* check complete offlien trace size, remove old logs if needed */
206         dlt_offline_trace_check_size(trace);
207
208         return dlt_offline_trace_create_new_file(trace);
209 }
210
211 int dlt_offline_trace_write(DltOfflineTrace *trace,unsigned char *data1,int size1,unsigned char *data2,int size2,unsigned char *data3,int size3) {
212
213         if(trace->ohandle <= 0)
214                 return -1;
215
216         /* check file size here */
217         if((lseek(trace->ohandle,0,SEEK_CUR)+size1+size2+size3)>=trace->fileSize)
218         {
219                 /* close old file */
220                 close(trace->ohandle);
221         trace->ohandle = -1;
222                 
223                 /* check complete offline trace size, remove old logs if needed */
224                 dlt_offline_trace_check_size(trace);
225                 
226                 /* create new file */
227                 dlt_offline_trace_create_new_file(trace);
228         }
229         
230         /* write data into log file */
231         if(data1 && (trace->ohandle >= 0)) {
232                 if(write(trace->ohandle,data1,size1)!=size1) {
233                         printf("Offline trace write failed!\n");
234                         return -1;                      
235                 }
236         }
237         if(data2 && (trace->ohandle >= 0)) {
238                 if(write(trace->ohandle,data2,size2)!=size2) {
239                         printf("Offline trace write failed!\n");
240                         return -1;                                              
241                 }
242         }
243         if(data3 && (trace->ohandle >= 0)) {
244                 if(write(trace->ohandle,data3,size3)!=size3) {
245                         printf("Offline trace write failed!\n");
246                         return -1;                                              
247                 }
248         }
249
250         return 0; /* OK */
251 }
252
253 int dlt_offline_trace_free(DltOfflineTrace *trace) {
254
255         if(trace->ohandle <= 0)
256                 return -1;
257         
258         /* close last used log file */
259         close(trace->ohandle);
260
261         return 0; /* OK */
262 }