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_filetransfer.c
23 : */
24 :
25 : /*******************************************************************************
26 : ** **
27 : ** SRC-MODULE: dlt-test-client.c **
28 : ** **
29 : ** TARGET : linux **
30 : ** **
31 : ** PROJECT : DLT **
32 : ** **
33 : ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de **
34 : ** **
35 : ** PURPOSE : **
36 : ** **
37 : ** REMARKS : **
38 : ** **
39 : ** PLATFORM DEPENDANT [yes/no]: yes **
40 : ** **
41 : ** TO BE CHANGED BY USER [yes/no]: no **
42 : ** **
43 : *******************************************************************************/
44 :
45 : /*******************************************************************************
46 : ** Author Identity **
47 : ********************************************************************************
48 : ** **
49 : ** Initials Name Company **
50 : ** -------- ------------------------- ---------------------------------- **
51 : ** aw Alexander Wenzel BMW **
52 : *******************************************************************************/
53 :
54 : #include <errno.h>
55 : #include <stdio.h>
56 : #include <string.h>
57 : #include "dlt_filetransfer.h"
58 : #include "dlt_common.h"
59 : #include "dlt_user_macros.h"
60 :
61 : /*!Defines the buffer size of a single file package which will be logged to dlt */
62 : #define BUFFER_SIZE 1024
63 :
64 : /*!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. */
65 : #define MIN_TIMEOUT 20
66 :
67 :
68 : #define DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES INT_MAX
69 :
70 : #define NANOSEC_PER_MILLISEC 1000000
71 : #define NANOSEC_PER_SEC 1000000000
72 :
73 :
74 : /*!Buffer for dlt file transfer. The size is defined by BUFFER_SIZE */
75 : unsigned char buffer[BUFFER_SIZE];
76 :
77 :
78 : /*!Get some information about the file size of a file */
79 : /**See stat(2) for more informations.
80 : * @param file Absolute file path
81 : * @param ok Result of stat
82 : * @return Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
83 : */
84 0 : uint32_t getFilesize(const char *file, int *ok)
85 : {
86 : struct stat st;
87 :
88 0 : if (-1 == stat(file, &st)) {
89 : /*we can only return 0, as the value is unsigned */
90 0 : *ok = 0;
91 0 : return 0;
92 : }
93 :
94 0 : *ok = 1;
95 0 : return (uint32_t)st.st_size;
96 : }
97 :
98 : /** A simple Hash function for C-strings
99 : * @param str input string. E.g. a file path.
100 : * @param hash start and result value for hash computation
101 : *
102 : */
103 0 : void stringHash(const char *str, uint32_t *hash)
104 : {
105 0 : if (!str || !hash) {
106 : return;
107 : }
108 :
109 0 : unsigned int len = strlen(str);
110 :
111 : unsigned int i = 0;
112 :
113 0 : if (len <= 0) {
114 : return;
115 : }
116 :
117 0 : for (i = 0; i < len; i++) {
118 0 : *hash = 53 * *hash + str[i];
119 : }
120 : }
121 :
122 :
123 : /*!Get some information about the file serial number of a file */
124 : /** See stat(2) for more informations.
125 : * @param file Absolute file path
126 : * @param ok *ok == 0 -> error; *ok == 1 -> ok
127 : * @return Returns a unique number associated with each filename
128 : */
129 0 : uint32_t getFileSerialNumber(const char *file, int *ok)
130 : {
131 : struct stat st;
132 : uint32_t ret;
133 :
134 0 : if (-1 == stat(file, &st)) {
135 0 : *ok = 0;
136 0 : ret = 0;
137 : } else {
138 0 : *ok = 1;
139 0 : ret = st.st_ino;
140 0 : ret = ret << (sizeof(ret) * 8) / 2;
141 0 : ret |= st.st_size;
142 0 : ret ^= st.st_ctime;
143 0 : stringHash(file, &ret);
144 : }
145 :
146 0 : return ret;
147 : }
148 :
149 : /*!Returns the creation date of a file */
150 : /** See stat(2) for more informations.
151 : * @param file Absolute file path
152 : * @param ok Result of stat
153 : * @return Returns the creation date of a file
154 : */
155 0 : time_t getFileCreationDate(const char *file, int *ok)
156 : {
157 : struct stat st;
158 :
159 0 : if (-1 == stat(file, &st)) {
160 0 : *ok = 0;
161 0 : return 0;
162 : }
163 :
164 0 : *ok = 1;
165 0 : return st.st_ctime;
166 : }
167 :
168 : /*!Returns the creation date of a file */
169 : /** Format of the creation date is Day Mon dd hh:mm:ss yyyy
170 : * @param file Absolute file path
171 : * @param ok Result of stat
172 : * @param date Local time
173 : * @return Returns the creation date of a file
174 : */
175 0 : void getFileCreationDate2(const char *file, int *ok, char *date)
176 : {
177 : struct stat st;
178 : struct tm ts;
179 :
180 0 : if (-1 == stat(file, &st)) {
181 0 : *ok = 0;
182 : date = 0;
183 0 : return;
184 : }
185 :
186 0 : *ok = 1;
187 0 : tzset();
188 0 : localtime_r(&st.st_ctime, &ts);
189 0 : asctime_r(&ts, date);
190 : }
191 :
192 : /*!Checks if the file exists */
193 : /**@param file Absolute file path
194 : * @return Returns 1 if the file exists, 0 if the file does not exist
195 : */
196 0 : int isFile (const char *file)
197 : {
198 : struct stat st;
199 0 : return stat (file, &st) == 0;
200 : }
201 :
202 : /*!Waits a period of time */
203 : /**Waits a period of time. The minimal time to wait is MIN_TIMEOUT. This makes sure that the FIFO of dlt is not flooded.
204 : * @param timeout Timeout to in ms but can not be smaller as MIN_TIMEOUT
205 : */
206 0 : void doTimeout(int timeout)
207 : {
208 : struct timespec ts;
209 0 : ts.tv_sec = (timeout * NANOSEC_PER_MILLISEC) / NANOSEC_PER_SEC;
210 0 : ts.tv_nsec = (timeout * NANOSEC_PER_MILLISEC) % NANOSEC_PER_SEC;
211 0 : nanosleep(&ts, NULL);
212 0 : }
213 :
214 : /*!Checks free space of the user buffer */
215 : /**
216 : * @return -1 if more than 50% space in the user buffer is free. Otherwise 1 will be returned.
217 : */
218 0 : int checkUserBufferForFreeSpace()
219 : {
220 : int total_size, used_size;
221 :
222 0 : dlt_user_check_buffer(&total_size, &used_size);
223 :
224 0 : if ((total_size - used_size) < (total_size / 2)) {
225 0 : return -1;
226 : }
227 :
228 : return 1;
229 : }
230 :
231 : /*!Deletes the given file */
232 : /**
233 : * @param filename Absolute file path
234 : * @return If the file is successfully deleted, a zero value is returned.If the file can not be deleted a nonzero value is returned.
235 : */
236 0 : int doRemoveFile(const char *filename)
237 : {
238 0 : return remove(filename);
239 : }
240 :
241 0 : void dlt_user_log_file_errorMessage(DltContext *fileContext, const char *filename, int errorCode)
242 : {
243 :
244 0 : if (errno != ENOENT) {
245 0 : int ok = 0;
246 0 : uint32_t fserial = getFileSerialNumber(filename, &ok);
247 :
248 0 : if (!ok) {
249 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
250 : DLT_STRING("dlt_user_log_file_errorMessage, error in getFileSerialNumber for: "),
251 : DLT_STRING(filename));
252 : }
253 :
254 0 : uint32_t fsize = getFilesize(filename, &ok);
255 :
256 0 : if (!ok) {
257 0 : DLT_LOG(*fileContext,
258 : DLT_LOG_ERROR,
259 : DLT_STRING("dlt_user_log_file_errorMessage, error in getFilesize for: "),
260 : DLT_STRING(filename));
261 : }
262 :
263 0 : char fcreationdate[50] = {0};
264 0 : getFileCreationDate2(filename, &ok, fcreationdate);
265 :
266 0 : if (!ok) {
267 0 : DLT_LOG(*fileContext,
268 : DLT_LOG_ERROR,
269 : DLT_STRING("dlt_user_log_file_errorMessage, error in getFilesize for: "),
270 : DLT_STRING(filename));
271 : }
272 :
273 0 : int package_count = dlt_user_log_file_packagesCount(fileContext, filename);
274 :
275 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
276 : DLT_STRING("FLER"),
277 : DLT_INT(errorCode),
278 : DLT_INT(-errno),
279 : DLT_UINT(fserial),
280 : DLT_STRING(filename),
281 : DLT_UINT(fsize),
282 : DLT_STRING(fcreationdate),
283 : DLT_INT(package_count),
284 : DLT_UINT(BUFFER_SIZE),
285 : DLT_STRING("FLER")
286 : );
287 : } else {
288 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
289 : DLT_STRING("FLER"),
290 : DLT_INT(errorCode),
291 : DLT_INT(-errno),
292 : DLT_STRING(filename),
293 : DLT_STRING("FLER")
294 : );
295 : }
296 0 : }
297 :
298 :
299 :
300 : /*!Logs specific file inforamtions to dlt */
301 : /**The filename, file size, file serial number and the number of packages will be logged to dlt.
302 : * @param fileContext Specific context
303 : * @param filename Absolute file path
304 : * @return Returns 0 if everything was okey.If there was a failure a value < 0 will be returned.
305 : */
306 0 : int dlt_user_log_file_infoAbout(DltContext *fileContext, const char *filename)
307 : {
308 :
309 0 : if (isFile(filename)) {
310 : int ok;
311 :
312 0 : uint32_t fsize = getFilesize(filename, &ok);
313 :
314 0 : if (!ok) {
315 0 : DLT_LOG(*fileContext,
316 : DLT_LOG_ERROR,
317 : DLT_STRING("dlt_user_log_file_infoAbout, Error getting size of file:"),
318 : DLT_STRING(filename));
319 : }
320 :
321 0 : uint32_t fserialnumber = getFileSerialNumber(filename, &ok);
322 :
323 0 : if (!ok) {
324 0 : DLT_LOG(*fileContext,
325 : DLT_LOG_ERROR,
326 : DLT_STRING("dlt_user_log_file_infoAbout, Error getting serial number of file:"),
327 : DLT_STRING(filename));
328 : }
329 :
330 0 : char creationdate[50] = {0};
331 0 : getFileCreationDate2(filename, &ok, creationdate);
332 :
333 0 : if (!ok) {
334 0 : DLT_LOG(*fileContext,
335 : DLT_LOG_ERROR,
336 : DLT_STRING("dlt_user_log_file_infoAbout, Error getting creation date of file:"),
337 : DLT_STRING(filename));
338 : }
339 :
340 0 : DLT_LOG(*fileContext, DLT_LOG_INFO,
341 : DLT_STRING("FLIF"),
342 : DLT_STRING("file serialnumber"), DLT_UINT(fserialnumber),
343 : DLT_STRING("filename"), DLT_STRING(filename),
344 : DLT_STRING("file size in bytes"), DLT_UINT(fsize),
345 : DLT_STRING("file creation date"), DLT_STRING(creationdate),
346 : DLT_STRING("number of packages"),
347 : DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)),
348 : DLT_STRING("FLIF")
349 : );
350 : return 0;
351 : } else {
352 0 : dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_INFO_ABOUT);
353 0 : return DLT_FILETRANSFER_ERROR_INFO_ABOUT;
354 : }
355 : }
356 :
357 : /*!Transfer the complete file as several dlt logs. */
358 : /**This method transfer the complete file as several dlt logs. At first it will be checked that the file exist.
359 : * In the next step some generic informations about the file will be logged to dlt.
360 : * Now the header will be logged to dlt. See the method dlt_user_log_file_header for more informations.
361 : * Then the method dlt_user_log_data will be called with the parameter to log all packages in a loop with some timeout.
362 : * 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.
363 : * @param fileContext Specific context to log the file to dlt
364 : * @param filename Absolute file path
365 : * @param deleteFlag Flag if the file will be deleted after transfer. 1->delete, 0->notDelete
366 : * @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.
367 : * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
368 : */
369 0 : int dlt_user_log_file_complete(DltContext *fileContext,
370 : const char *filename,
371 : int deleteFlag,
372 : int timeout)
373 : {
374 0 : if (!isFile(filename)) {
375 0 : dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_COMPLETE);
376 0 : return DLT_FILETRANSFER_ERROR_FILE_COMPLETE;
377 : }
378 :
379 0 : if (dlt_user_log_file_header(fileContext, filename) != 0) {
380 : return DLT_FILETRANSFER_ERROR_FILE_COMPLETE1;
381 : }
382 :
383 0 : if (dlt_user_log_file_data(fileContext, filename, DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES,
384 : timeout) != 0) {
385 : return DLT_FILETRANSFER_ERROR_FILE_COMPLETE2;
386 : }
387 :
388 0 : if (dlt_user_log_file_end(fileContext, filename, deleteFlag) != 0) {
389 0 : return DLT_FILETRANSFER_ERROR_FILE_COMPLETE3;
390 : }
391 :
392 : return 0;
393 : }
394 :
395 : /*!This method gives information about the number of packages the file have */
396 : /**Every file will be divided into several packages. Every package will be logged as a single dlt log.
397 : * The number of packages depends on the BUFFER_SIZE.
398 : * At first it will be checked if the file exist. Then the file will be divided into
399 : * several packages depending on the buffer size.
400 : * @param fileContext Specific context to log the file to dlt
401 : * @param filename Absolute file path
402 : * @return Returns the number of packages if everything was okey. If there was a failure a value < 0 will be returned.
403 : */
404 0 : int dlt_user_log_file_packagesCount(DltContext *fileContext, const char *filename)
405 : {
406 : int packages;
407 : uint32_t filesize;
408 :
409 0 : if (isFile(filename)) {
410 : packages = 1;
411 : int ok;
412 0 : filesize = getFilesize(filename, &ok);
413 :
414 0 : if (!ok) {
415 0 : DLT_LOG(*fileContext,
416 : DLT_LOG_ERROR,
417 : DLT_STRING("Error in: dlt_user_log_file_packagesCount, isFile"),
418 : DLT_STRING(filename),
419 : DLT_INT(DLT_FILETRANSFER_ERROR_PACKAGE_COUNT));
420 0 : return -1;
421 : }
422 :
423 0 : if (filesize < BUFFER_SIZE) {
424 : return packages;
425 : } else {
426 0 : packages = filesize / BUFFER_SIZE;
427 :
428 0 : if (filesize % BUFFER_SIZE == 0) {
429 : return packages;
430 : } else {
431 0 : return packages + 1;
432 : }
433 : }
434 : } else {
435 0 : DLT_LOG(*fileContext,
436 : DLT_LOG_ERROR,
437 : DLT_STRING("Error in: dlt_user_log_file_packagesCount, !isFile"),
438 : DLT_STRING(filename),
439 : DLT_INT(DLT_FILETRANSFER_ERROR_PACKAGE_COUNT));
440 0 : return -1;
441 : }
442 : }
443 :
444 : /*!Transfer the head of the file as a dlt logs. */
445 : /**The head of the file must be logged to dlt because the head contains inforamtion about the file serial number,
446 : * the file name, the file size, package number the file have and the buffer size.
447 : * All these informations are needed from the plugin of the dlt viewer.
448 : * See the Mainpages.c for more informations.
449 : * @param fileContext Specific context to log the file to dlt
450 : * @param filename Absolute file path
451 : * @param alias Alias for the file. An alternative name to show in the receiving end
452 : * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
453 : */
454 0 : int dlt_user_log_file_header_alias(DltContext *fileContext, const char *filename, const char *alias)
455 : {
456 :
457 0 : if (isFile(filename)) {
458 : int ok;
459 :
460 0 : uint32_t fserialnumber = getFileSerialNumber(filename, &ok);
461 :
462 0 : if (!ok) {
463 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
464 : DLT_STRING(
465 : "dlt_user_log_file_header_alias, Error getting serial number of file:"),
466 : DLT_STRING(filename));
467 0 : return DLT_FILETRANSFER_FILE_SERIAL_NUMBER;
468 : }
469 :
470 0 : uint32_t fsize = getFilesize(filename, &ok);
471 :
472 0 : if (!ok) {
473 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
474 : DLT_STRING(
475 : "dlt_user_log_file_header_alias, Error getting size of file:"),
476 : DLT_STRING(filename));
477 : }
478 :
479 0 : char fcreationdate[50] = {0};
480 0 : getFileCreationDate2(filename, &ok, fcreationdate);
481 :
482 0 : if (!ok) {
483 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
484 : DLT_STRING(
485 : "dlt_user_log_file_header_alias, Error getting creation date of file:"),
486 : DLT_STRING(filename));
487 : }
488 :
489 0 : DLT_LOG(*fileContext, DLT_LOG_INFO,
490 : DLT_STRING("FLST"),
491 : DLT_UINT(fserialnumber),
492 : DLT_STRING(alias),
493 : DLT_UINT(fsize),
494 : DLT_STRING(fcreationdate);
495 : DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)),
496 : DLT_UINT(BUFFER_SIZE),
497 : DLT_STRING("FLST")
498 : );
499 :
500 0 : return 0;
501 : } else {
502 0 : dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_HEAD);
503 0 : return DLT_FILETRANSFER_ERROR_FILE_HEAD;
504 : }
505 : }
506 :
507 : /*!Transfer the head of the file as a dlt logs. */
508 : /**The head of the file must be logged to dlt because the head contains inforamtion about the file serial number,
509 : * the file name, the file size, package number the file have and the buffer size.
510 : * All these informations are needed from the plugin of the dlt viewer.
511 : * See the Mainpages.c for more informations.
512 : * @param fileContext Specific context to log the file to dlt
513 : * @param filename Absolute file path
514 : * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
515 : */
516 0 : int dlt_user_log_file_header(DltContext *fileContext, const char *filename)
517 : {
518 :
519 0 : if (isFile(filename)) {
520 : int ok;
521 :
522 0 : uint32_t fserialnumber = getFileSerialNumber(filename, &ok);
523 :
524 0 : if (!ok) {
525 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
526 : DLT_STRING(
527 : "dlt_user_log_file_header, Error getting serial number of file:"),
528 : DLT_STRING(filename));
529 : }
530 :
531 0 : uint32_t fsize = getFilesize(filename, &ok);
532 :
533 0 : if (!ok) {
534 0 : DLT_LOG(*fileContext,
535 : DLT_LOG_ERROR,
536 : DLT_STRING("dlt_user_log_file_header, Error getting size of file:"),
537 : DLT_STRING(filename));
538 : }
539 :
540 0 : char fcreationdate[50] = {0};
541 0 : getFileCreationDate2(filename, &ok, fcreationdate);
542 :
543 0 : if (!ok) {
544 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
545 : DLT_STRING(
546 : "dlt_user_log_file_header, Error getting creation date of file:"),
547 : DLT_STRING(filename));
548 : }
549 :
550 0 : DLT_LOG(*fileContext, DLT_LOG_INFO,
551 : DLT_STRING("FLST"),
552 : DLT_UINT(fserialnumber),
553 : DLT_STRING(filename),
554 : DLT_UINT(fsize),
555 : DLT_STRING(fcreationdate);
556 : DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)),
557 : DLT_UINT(BUFFER_SIZE),
558 : DLT_STRING("FLST")
559 : );
560 :
561 : return 0;
562 : } else {
563 0 : dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_HEAD);
564 0 : return DLT_FILETRANSFER_ERROR_FILE_HEAD;
565 : }
566 : }
567 :
568 : /*!Transfer the content data of a file. */
569 : /**See the Mainpages.c for more informations.
570 : * @param fileContext Specific context to log the file to dlt
571 : * @param filename Absolute file path
572 : * @param packageToTransfer Package number to transfer. If this param is LONG_MAX, the whole file will be transferred with a specific timeout
573 : * @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.
574 : * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
575 : */
576 0 : int dlt_user_log_file_data(DltContext *fileContext,
577 : const char *filename,
578 : int packageToTransfer,
579 : int timeout)
580 : {
581 0 : bool fileCancelTransferFlag = false;
582 0 : return dlt_user_log_file_data_cancelable(fileContext, filename, packageToTransfer, timeout, &fileCancelTransferFlag);
583 : }
584 :
585 : /* !Transfer the content data of a cancelable file*/
586 : /**See the Mainpages.c for more informations.
587 : * @param fileContext Specific context to log the file to dlt
588 : * @param filename Absolute file path
589 : * @param packageToTransfer Package number to transfer. If this param is LONG_MAX, the whole file will be transferred with a specific timeout
590 : * @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.
591 : * @param fileCancelTransferFlag is a bool pointer to cancel the filetransfer on demand. For example in case of application shutdown event outstanding file transfer should abort and return
592 : * @return Returns 0 if everything was okey. If there was a failure value < 0 will be returned.
593 : */
594 0 : int dlt_user_log_file_data_cancelable(DltContext *fileContext,
595 : const char *filename,
596 : int packageToTransfer,
597 : int timeout,
598 : bool *const fileCancelTransferFlag)
599 : {
600 : FILE *file;
601 : int pkgNumber;
602 : uint32_t readBytes;
603 :
604 0 : if (isFile(filename)) {
605 :
606 0 : file = fopen (filename, "rb");
607 :
608 0 : if (file == NULL) {
609 0 : dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_DATA);
610 0 : return DLT_FILETRANSFER_ERROR_FILE_DATA;
611 : }
612 :
613 0 : if (((packageToTransfer != DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES) &&
614 : (packageToTransfer >
615 0 : dlt_user_log_file_packagesCount(fileContext,
616 0 : filename))) || (packageToTransfer <= 0)) {
617 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
618 : DLT_STRING("Error at dlt_user_log_file_data: packageToTransfer out of scope"),
619 : DLT_STRING("packageToTransfer:"),
620 : DLT_UINT(packageToTransfer),
621 : DLT_STRING("numberOfMaximalPackages:"),
622 : DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)),
623 : DLT_STRING("for File:"),
624 : DLT_STRING(filename)
625 : );
626 0 : fclose(file);
627 0 : return DLT_FILETRANSFER_ERROR_FILE_DATA;
628 : }
629 :
630 : readBytes = 0;
631 :
632 0 : if (packageToTransfer != DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES) {
633 : /* If a single package should be transferred. The user has to check that the free space in the user buffer > 50% */
634 : /* if(checkUserBufferForFreeSpace()<0) */
635 : /* return DLT_FILETRANSFER_ERROR_FILE_DATA_USER_BUFFER_FAILED; */
636 :
637 0 : if (0 != fseek (file, (packageToTransfer - 1) * BUFFER_SIZE, SEEK_SET)) {
638 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
639 : DLT_STRING("failed to fseek in file: "),
640 : DLT_STRING(filename),
641 : DLT_STRING("ferror:"),
642 : DLT_INT(ferror(file))
643 : );
644 :
645 0 : fclose (file);
646 0 : return -1;
647 : }
648 :
649 : readBytes = fread(buffer, sizeof(char), BUFFER_SIZE, file);
650 : int ok;
651 :
652 0 : uint32_t fserial = getFileSerialNumber(filename, &ok);
653 :
654 0 : if (1 != ok) {
655 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
656 : DLT_STRING("failed to get FileSerialNumber for: "),
657 : DLT_STRING(filename));
658 0 : fclose (file);
659 0 : return DLT_FILETRANSFER_FILE_SERIAL_NUMBER;
660 : }
661 :
662 0 : DLT_LOG(*fileContext, DLT_LOG_INFO,
663 : DLT_STRING("FLDA"),
664 : DLT_UINT(fserial),
665 : DLT_UINT(packageToTransfer),
666 : DLT_RAW(buffer, readBytes),
667 : DLT_STRING("FLDA")
668 : );
669 :
670 0 : if(*fileCancelTransferFlag) {
671 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
672 : DLT_STRING("FLER"),
673 : DLT_INT(DLT_FILETRANSFER_ERROR_FILE_END_USER_CANCELLED)
674 : );
675 0 : return DLT_FILETRANSFER_ERROR_FILE_END_USER_CANCELLED;
676 : }
677 0 : doTimeout(timeout);
678 : } else {
679 : pkgNumber = 0;
680 :
681 0 : while (!feof(file)) {
682 : /* If the complete file should be transferred, the user buffer will be checked. */
683 : /* If free space < 50% the package won't be transferred. */
684 0 : if (checkUserBufferForFreeSpace() > 0) {
685 0 : pkgNumber++;
686 0 : readBytes = fread(buffer, sizeof(char), BUFFER_SIZE, file);
687 :
688 0 : if (readBytes == 0) {
689 : // If the file size is divisible by the package size don't send
690 : // one empty FLDA. Also we send the correct number of FLDAs too.
691 : break;
692 : }
693 :
694 : int ok;
695 :
696 0 : uint32_t fserial = getFileSerialNumber(filename, &ok);
697 :
698 0 : if (1 != ok) {
699 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
700 : DLT_STRING("failed to get FileSerialNumber for: "),
701 : DLT_STRING(filename));
702 0 : fclose(file);
703 0 : return DLT_FILETRANSFER_FILE_SERIAL_NUMBER;
704 : }
705 :
706 0 : DLT_LOG(*fileContext, DLT_LOG_INFO,
707 : DLT_STRING("FLDA"),
708 : DLT_UINT(fserial),
709 : DLT_UINT(pkgNumber),
710 : DLT_RAW(buffer, readBytes),
711 : DLT_STRING("FLDA")
712 : );
713 0 : if(*fileCancelTransferFlag) {
714 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
715 : DLT_STRING("FLER"),
716 : DLT_INT(DLT_FILETRANSFER_ERROR_FILE_END_USER_CANCELLED)
717 : );
718 0 : return DLT_FILETRANSFER_ERROR_FILE_END_USER_CANCELLED;
719 : }
720 : } else {
721 0 : fclose(file);
722 0 : return DLT_FILETRANSFER_ERROR_FILE_DATA_USER_BUFFER_FAILED;
723 : }
724 0 : doTimeout(timeout);
725 : }
726 : }
727 :
728 0 : fclose(file);
729 :
730 0 : return 0;
731 : } else {
732 0 : dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_DATA);
733 0 : return DLT_FILETRANSFER_ERROR_FILE_DATA;
734 : }
735 : }
736 : /*!Transfer the end of the file as a dlt logs. */
737 : /**The end of the file must be logged to dlt because the end contains inforamtion about the file serial number.
738 : * This informations is needed from the plugin of the dlt viewer.
739 : * See the Mainpages.c for more informations.
740 : * @param fileContext Specific context to log the file to dlt
741 : * @param filename Absolute file path
742 : * @param deleteFlag Flag to delete the file after the whole file is transferred (logged to dlt).1->delete,0->NotDelete
743 : * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
744 : */
745 0 : int dlt_user_log_file_end(DltContext *fileContext, const char *filename, int deleteFlag)
746 : {
747 :
748 0 : if (isFile(filename)) {
749 :
750 : int ok;
751 0 : uint32_t fserial = getFileSerialNumber(filename, &ok);
752 :
753 0 : if (1 != ok) {
754 0 : DLT_LOG(*fileContext, DLT_LOG_ERROR,
755 : DLT_STRING("failed to get FileSerialNumber for: "),
756 : DLT_STRING(filename));
757 0 : return DLT_FILETRANSFER_FILE_SERIAL_NUMBER;
758 : }
759 :
760 0 : DLT_LOG(*fileContext, DLT_LOG_INFO,
761 : DLT_STRING("FLFI"),
762 : DLT_UINT(fserial),
763 : DLT_STRING("FLFI")
764 : );
765 :
766 0 : if (deleteFlag) {
767 0 : if (doRemoveFile(filename) != 0) {
768 0 : dlt_user_log_file_errorMessage(fileContext,
769 : filename,
770 : DLT_FILETRANSFER_ERROR_FILE_END);
771 0 : return -1;
772 : }
773 : }
774 :
775 0 : return 0;
776 : } else {
777 0 : dlt_user_log_file_errorMessage(fileContext, filename, DLT_FILETRANSFER_ERROR_FILE_END);
778 0 : return DLT_FILETRANSFER_ERROR_FILE_END;
779 : }
780 : }
|