Merge branch 'tmp'
[profile/ivi/dlt-daemon.git] / src / lib / dlt_filetransfer.c
1 #include "dlt_filetransfer.h"
2
3 //!Defines the buffer size of a single file package which will be logged to dlt
4 #define BUFFER_SIZE 1024
5
6 //!Defines the minimum timeout between two dlt logs. This is important because dlt should not be flooded with too many logs in a short period of time.
7 #define MIN_TIMEOUT 20
8
9
10 #define ERROR_FILE_COMPLETE -300
11 #define ERROR_FILE_COMPLETE1 -301
12 #define ERROR_FILE_COMPLETE2 -302
13 #define ERROR_FILE_COMPLETE3 -303
14 #define ERROR_FILE_HEAD -400
15 #define ERROR_FILE_DATA -500
16 #define ERROR_FILE_END -600
17 #define ERROR_INFO_ABOUT -700
18 #define ERROR_PACKAGE_COUNT -800
19
20
21 //!Buffer for dlt file transfer. The size is defined by BUFFER_SIZE
22 unsigned char buffer[BUFFER_SIZE];
23
24
25 //!Get some information about the file size of a file
26 /**See stat(2) for more informations.
27  * @param file Absolute file path
28  * @return Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
29  */
30 unsigned long getFilesize(const char* file){
31         struct stat st;
32         stat(file, &st);
33         return (unsigned long)st.st_size;
34 }
35
36 //!Get some information about the file serial number of a file
37 /** See stat(2) for more informations.
38  * @param file Absolute file path
39  * @return Returns a unique number associated with each filename
40  */
41 unsigned long getFileSerialNumber(const char* file){
42         struct stat st;
43         stat(file, &st);
44         return (unsigned long)st.st_ino;
45 }
46
47 //!Returns the creation date of a file
48 /** See stat(2) for more informations.
49  * @param file Absolute file path
50  * @return Returns the creation date of a file
51 */
52 time_t getFileCreationDate(const char* file){
53         struct stat st;
54         stat(file, &st);
55         return st.st_ctime;
56 }
57
58 //!Returns the creation date of a file
59 /** Format of the creation date is Day Mon dd hh:mm:ss yyyy
60  * @param file Absolute file path
61  * @return Returns the creation date of a file
62 */
63 char* getFileCreationDate2(const char* file){
64         struct stat st;
65         stat(file, &st);
66         
67         struct tm  *ts= localtime(&st.st_ctime);
68         return asctime(ts);
69 }
70
71 //!Checks if the file exists
72 /**@param file Absolute file path
73  * @return Returns 1 if the file exists, 0 if the file does not exist
74  */
75 int isFile (const char* file)
76 {
77         struct stat   st;   
78         return (stat (file, &st) == 0);
79 }
80
81 //!Waits a period of time
82 /**Waits a period of time. The minimal time to wait is MIN_TIMEOUT. This makes sure that the FIFO of dlt is not flooded.
83  * @param timeout Timeout to wait in seconds in ms but can not be smaller as MIN_TIMEOUT
84  */
85 void doTimeout(int timeout)
86 {
87         int total_size, used_size;
88         
89         dlt_user_check_buffer(&total_size, &used_size);
90         
91         /* sleep only if more than 50% of buffer used */
92         if((total_size - used_size) < (total_size/2))
93         {
94                 printf("Wait %d of %d already used\n",used_size,total_size);
95
96                 if(timeout>MIN_TIMEOUT)
97                 {       
98                         usleep(timeout * 1000);
99                 }
100                 else
101                 {
102                         usleep(MIN_TIMEOUT * 1000);
103                 }                               
104         }
105 }
106
107 //!Deletes the given file
108 /**
109  * @param filename Absolute file path
110  * @return If the file is successfully deleted, a zero value is returned.If the file can not be deleted a nonzero value is returned.
111  */
112 int doRemoveFile(const char*filename){
113         return remove( filename); 
114 }
115
116 void dlt_user_log_file_errorMessage(DltContext *fileContext, const char *filename, int errorCode){
117
118         if(errno != ENOENT)
119         {
120                 DLT_LOG(*fileContext,DLT_LOG_ERROR,
121                         DLT_STRING("FLER"),
122                         DLT_INT(errorCode),
123                         DLT_INT(-errno),
124                         DLT_UINT(getFileSerialNumber(filename)),
125                         DLT_STRING(filename),
126                         DLT_UINT(getFilesize(filename)),
127                         DLT_STRING(getFileCreationDate2(filename)),
128                         DLT_UINT(dlt_user_log_file_packagesCount(fileContext,filename)),
129                         DLT_UINT(BUFFER_SIZE),
130                         DLT_STRING("FLER")
131                 );              
132         } else {
133                 DLT_LOG(*fileContext,DLT_LOG_ERROR,
134                         DLT_STRING("FLER"),
135                         DLT_INT(errorCode),
136                         DLT_INT(-errno),
137                         DLT_STRING(filename),
138                         DLT_STRING("FLER")
139                 );
140         }
141 }
142
143
144
145 //!Logs specific file inforamtions to dlt
146 /**The filename, file size, file serial number and the number of packages will be logged to dlt.
147  * @param fileContext Specific context
148  * @param filename Absolute file path
149  * @return Returns 0 if everything was okey.If there was a failure a value < 0 will be returned.
150  */
151 int dlt_user_log_file_infoAbout(DltContext *fileContext, const char *filename){
152         
153         if(isFile(filename))
154         {
155                 DLT_LOG(*fileContext,DLT_LOG_INFO,
156                         DLT_STRING("FLIF"),
157                         DLT_STRING("file serialnumber"),DLT_UINT(getFileSerialNumber(filename)),
158                         DLT_STRING("filename"),DLT_STRING(filename),
159                         DLT_STRING("file size in bytes"),DLT_UINT(getFilesize(filename)),
160                         DLT_STRING("file creation date"),DLT_STRING(getFileCreationDate2(filename)),
161                         DLT_STRING("number of packages"),DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)),
162                         DLT_STRING("FLIF")
163                 );
164                 return 0;
165         } else {
166                 dlt_user_log_file_errorMessage(fileContext,filename,ERROR_INFO_ABOUT);
167                 return ERROR_INFO_ABOUT;
168         }
169 }
170
171 //!Transfer the complete file as several dlt logs.
172 /**This method transfer the complete file as several dlt logs. At first it will be checked that the file exist.
173  * In the next step some generic informations about the file will be logged to dlt.
174  * Now the header will be logged to dlt. See the method dlt_user_log_file_header for more informations.
175  * Then the method dlt_user_log_data will be called with the parameter to log all packages in a loop with some timeout.
176  * At last dlt_user_log_end is called to signal that the complete file transfer was okey. This is important for the plugin of the dlt viewer. 
177  * @param fileContext Specific context to log the file to dlt
178  * @param filename Absolute file path
179  * @param deleteFlag Flag if the file will be deleted after transfer. 1->delete, 0->notDelete
180  * @param timeout Timeout in ms to wait between some logs. Important that the FIFO of dlt will not be flooded with to many messages in a short period of time.
181  * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
182  */
183 int dlt_user_log_file_complete(DltContext *fileContext, const char *filename, int deleteFlag, int timeout)
184 {       
185         if(!isFile(filename))
186         {
187                 dlt_user_log_file_errorMessage(fileContext,filename, ERROR_FILE_COMPLETE);
188                 return ERROR_FILE_COMPLETE;
189         }
190         
191         if(dlt_user_log_file_header(fileContext,filename) != 0)
192         {
193                 return ERROR_FILE_COMPLETE1;
194         }
195                 
196         if(dlt_user_log_file_data(fileContext, filename,LONG_MAX,timeout) != 0)
197         {
198                 return ERROR_FILE_COMPLETE2;
199         }
200                 
201         if(dlt_user_log_file_end(fileContext,filename, deleteFlag) != 0)
202         {
203                 return ERROR_FILE_COMPLETE3;
204         }               
205                         
206         return 0;
207 }
208
209 //!This method gives information about the number of packages the file have
210 /**Every file will be divided into several packages. Every package will be logged as a single dlt log.
211  * The number of packages depends on the BUFFER_SIZE.
212  * At first it will be checked if the file exist. Then the file will be divided into
213  * several packages depending on the buffer size.
214  * @param fileContext Specific context to log the file to dlt
215  * @param filename Absolute file path
216  * @return Returns the number of packages if everything was okey. If there was a failure a value < 0 will be returned.
217  */
218 int dlt_user_log_file_packagesCount(DltContext *fileContext, const char *filename){
219         int packages;
220         long filesize;
221         
222         if(isFile(filename))
223         {
224                 packages = 1;
225                 filesize = getFilesize(filename);
226                 if(filesize < BUFFER_SIZE)
227                 {       
228                         return packages;
229                 } 
230                 else 
231                 {
232                         packages = filesize/BUFFER_SIZE;
233                         
234                         if(filesize%BUFFER_SIZE == 0)
235                         {       
236                                 return packages;
237                         }
238                         else
239                         {
240                                 return packages+1;
241                         }
242                 }
243         } else {
244                 dlt_user_log_file_errorMessage(fileContext,filename,ERROR_PACKAGE_COUNT);
245                 return -1;
246         }
247 }
248
249 //!Transfer the head of the file as a dlt logs.
250 /**The head of the file must be logged to dlt because the head contains inforamtion about the file serial number,
251  * the file name, the file size, package number the file have and the buffer size.
252  * All these informations are needed from the plugin of the dlt viewer.
253  * See the Mainpages.c for more informations.
254  * @param fileContext Specific context to log the file to dlt
255  * @param filename Absolute file path
256  * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
257  */
258 int dlt_user_log_file_header(DltContext *fileContext,const char *filename){
259
260         if(isFile(filename))
261         {
262                 DLT_LOG(*fileContext,DLT_LOG_INFO,
263                                         DLT_STRING("FLST"),
264                                         DLT_UINT(getFileSerialNumber(filename)),
265                                         DLT_STRING(filename),
266                                         DLT_UINT(getFilesize(filename)),
267                                         DLT_STRING(getFileCreationDate2(filename));
268                                         DLT_UINT(dlt_user_log_file_packagesCount(fileContext,filename)),
269                                         DLT_UINT(BUFFER_SIZE),
270                                         DLT_STRING("FLST")              
271                                 );
272
273                 return 0;
274         }
275         else
276         {
277                 dlt_user_log_file_errorMessage(fileContext,filename, ERROR_FILE_HEAD);
278                 return ERROR_FILE_HEAD;
279         }
280 }
281
282 //!Transfer the content data of a file.
283 /**See the Mainpages.c for more informations.
284  * @param fileContext Specific context to log the file to dlt
285  * @param filename Absolute file path
286  * @param packageToTransfer Package number to transfer. If this param is LONG_MAX, the whole file will be transferred with a specific timeout
287  * @param timeout Timeout to wait between dlt logs. Important because the dlt FIFO should not be flooded. Default is defined by MIN_TIMEOUT. The given timeout in ms can not be smaller than MIN_TIMEOUT.
288  * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
289  */
290 int dlt_user_log_file_data(DltContext *fileContext,const char *filename, int packageToTransfer, int timeout){
291         FILE *file;
292         int pkgNumber;
293         long readBytes;
294                 
295         if(isFile(filename))
296         {
297         
298                 file = fopen (filename,"rb");
299                 if (file == NULL)
300                 {
301                         dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_DATA);
302                         return ERROR_FILE_DATA;
303                 }
304                 
305                 if( (packageToTransfer != LONG_MAX && packageToTransfer > dlt_user_log_file_packagesCount(fileContext,filename)) || packageToTransfer <= 0)
306                 {
307                         DLT_LOG(*fileContext,DLT_LOG_ERROR,
308                                 DLT_STRING("Error at dlt_user_log_file_data: packageToTransfer out of scope"),
309                                 DLT_STRING("packageToTransfer:"),
310                                 DLT_UINT(packageToTransfer),
311                                 DLT_STRING("numberOfMaximalPackages:"),
312                                 DLT_UINT(dlt_user_log_file_packagesCount(fileContext,filename)),
313                                 DLT_STRING("for File:"),
314                                 DLT_STRING(filename)
315                         );
316                         return ERROR_FILE_DATA;
317                 }
318
319                 readBytes = 0;
320                 
321                 if(packageToTransfer != LONG_MAX)
322                 {
323                                 fseek ( file , (packageToTransfer-1)*BUFFER_SIZE , SEEK_SET );
324                                 readBytes = fread(buffer, sizeof(char), BUFFER_SIZE, file);
325                                 
326                                 DLT_LOG(*fileContext,DLT_LOG_INFO,
327                                         DLT_STRING("FLDA"),
328                                         DLT_UINT(getFileSerialNumber(filename)),
329                                         DLT_UINT(packageToTransfer),
330                                         DLT_RAW(buffer,readBytes),
331                                         DLT_STRING("FLDA")      
332                                 );
333                                 
334                                 //doTimeout(timeout);
335                                         
336                 } else {
337                         pkgNumber = 0;
338                         while( !feof( file ) )
339                         {
340                                 pkgNumber++;
341                                 readBytes = fread(buffer, sizeof(char), BUFFER_SIZE, file);     
342                                 
343                                 DLT_LOG(*fileContext,DLT_LOG_INFO,
344                                         DLT_STRING("FLDA"),
345                                         DLT_UINT(getFileSerialNumber(filename)),
346                                         DLT_UINT(pkgNumber),
347                                         DLT_RAW(buffer,readBytes),
348                                         DLT_STRING("FLDA")              
349                                 );
350                                 
351                                 //doTimeout(timeout); 
352                         }
353                 }
354                 
355                 fclose(file);
356                 
357                 return 0;
358                 
359         } else {
360                 dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_DATA);
361                 return ERROR_FILE_DATA;
362         }
363         
364 }
365 //!Transfer the end of the file as a dlt logs.
366 /**The end of the file must be logged to dlt because the end contains inforamtion about the file serial number.
367  * This informations is needed from the plugin of the dlt viewer.
368  * See the Mainpages.c for more informations.
369  * @param fileContext Specific context to log the file to dlt
370  * @param filename Absolute file path
371  * @param deleteFlag Flag to delete the file after the whole file is transferred (logged to dlt).1->delete,0->NotDelete
372  * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
373  */
374 int dlt_user_log_file_end(DltContext *fileContext,const char *filename,int deleteFlag){
375
376         if(isFile(filename))
377         {
378
379                 DLT_LOG(*fileContext,DLT_LOG_INFO,
380                                 DLT_STRING("FLFI"),
381                                 DLT_UINT(getFileSerialNumber(filename)),
382                                 DLT_STRING("FLFI")
383                 );
384                 
385                 if(deleteFlag){
386                                 if( doRemoveFile(filename) != 0 ){
387                                         dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_END);
388                                         return -1;
389                                 }
390                 }
391         
392                 return 0;
393         }else{
394                 dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_END);
395                 return ERROR_FILE_END;
396         }
397 }