diff options
author | Alexander Wenzel <Alexander.AW.Wenzel@bmw.de> | 2011-09-29 13:36:57 +0200 |
---|---|---|
committer | Alexander Wenzel <Alexander.AW.Wenzel@bmw.de> | 2011-09-29 13:36:57 +0200 |
commit | 8fd55260f1d572939f185e014aef34a53b50de8b (patch) | |
tree | 88ab496b6e7b6f24ea8f502f5594a003c6472f40 /src/lib | |
parent | 966bffa7397f0479640f2232c6a2d1667026952e (diff) | |
download | DLT-daemon-8fd55260f1d572939f185e014aef34a53b50de8b.tar.gz |
Add Filetransfer feature to DLT user library.
Added missing offline trace files.
Diffstat (limited to 'src/lib')
-rwxr-xr-x | src/lib/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/lib/dlt_filetransfer.c | 406 |
2 files changed, 407 insertions, 1 deletions
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 1d33d21..7956e1f 100755 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -35,7 +35,7 @@ # @licence end@ ######## -set(dlt_LIB_SRCS dlt_user dlt_client ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c) +set(dlt_LIB_SRCS dlt_user dlt_client dlt_filetransfer ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c) add_library(dlt ${dlt_LIB_SRCS}) diff --git a/src/lib/dlt_filetransfer.c b/src/lib/dlt_filetransfer.c new file mode 100644 index 0000000..a78c418 --- /dev/null +++ b/src/lib/dlt_filetransfer.c @@ -0,0 +1,406 @@ +#include "dlt_filetransfer.h" + +//!Defines the buffer size of a single file package which will be logged to dlt +#define BUFFER_SIZE 1024 + +//!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. +#define MIN_TIMEOUT 20 + + +#define ERROR_FILE_COMPLETE -300 +#define ERROR_FILE_COMPLETE1 -301 +#define ERROR_FILE_COMPLETE2 -302 +#define ERROR_FILE_COMPLETE3 -303 +#define ERROR_FILE_HEAD -400 +#define ERROR_FILE_DATA -500 +#define ERROR_FILE_END -600 +#define ERROR_INFO_ABOUT -700 +#define ERROR_PACKAGE_COUNT -800 + + +//!Buffer for dlt file transfer. The size is defined by BUFFER_SIZE +unsigned char buffer[BUFFER_SIZE]; + + +//!Get some information about the file size of a file +/**See stat(2) for more informations. + * @param file Absolute file path + * @return Returns the size of the file (if it is a regular file or a symbolic link) in bytes. + */ +unsigned long getFilesize(const char* file){ + struct stat st; + stat(file, &st); + return (unsigned long)st.st_size; +} + +//!Get some information about the file serial number of a file +/** See stat(2) for more informations. + * @param file Absolute file path + * @return Returns a unique number associated with each filename + */ +unsigned long getFileSerialNumber(const char* file){ + struct stat st; + stat(file, &st); + return (unsigned long)st.st_ino; +} + +//!Returns the creation date of a file +/** See stat(2) for more informations. + * @param file Absolute file path + * @return Returns the creation date of a file +*/ +time_t getFileCreationDate(const char* file){ + struct stat st; + stat(file, &st); + return st.st_ctime; +} +char* getFileCreationDate2(const char* file){ + struct stat st; + stat(file, &st); + + struct tm *ts= localtime(&st.st_ctime); + //char buf[80]; + /* Format and print the time, "ddd yyyy-mm-dd hh:mm:ss zzz" */ + //strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", ts); + return asctime(ts); +} + + + + +//void sighandler(int sig) +//{ +// +// fprintf(stderr, "Signal handler called with %d\n", sig); +// signal(sig, &sighandler); +// exit(1); +// +//} + + + +//!Checks if the file exists +/**@param file Absolute file path + * @return Returns 1 if the file exists, 0 if the file does not exist + */ +int isFile (const char* file) +{ + struct stat st; + return (stat (file, &st) == 0); +} + +//!Waits a period of time +/**Waits a period of time. The minimal time to wait is MIN_TIMEOUT. This makes sure that the FIFO of dlt is not flooded. + * @param timeout Timeout to wait in seconds in ms but can not be smaller as MIN_TIMEOUT + */ +void doTimeout(int timeout) +{ + if(timeout>MIN_TIMEOUT) + { + usleep(timeout * 1000); + } + else + { + usleep(MIN_TIMEOUT * 1000); + } +} + +//!Deletes the given file +/** + * @param filename Absolute file path + * @return If the file is successfully deleted, a zero value is returned.If the file can not be deleted a nonzero value is returned. + */ +int doRemoveFile(const char*filename){ + return remove( filename); +} + +void dlt_user_log_file_errorMessage(DltContext *fileContext, const char *filename, int errorCode){ + + if(-errno != -2) + { + DLT_LOG(*fileContext,DLT_LOG_ERROR, + DLT_STRING("FLER"), + DLT_INT(errorCode), + DLT_INT(-errno), + DLT_UINT(getFileSerialNumber(filename)), + DLT_STRING(filename), + DLT_UINT(getFilesize(filename)), + DLT_STRING(getFileCreationDate2(filename)), + DLT_UINT(dlt_user_log_file_packagesCount(fileContext,filename)), + DLT_UINT(BUFFER_SIZE), + DLT_STRING("FLER") + ); + } else { + DLT_LOG(*fileContext,DLT_LOG_ERROR, + DLT_STRING("FLER"), + DLT_INT(errorCode), + DLT_INT(-errno), + DLT_STRING(filename), + DLT_STRING("FLER") + ); + } +} + + + +//!Logs specific file inforamtions to dlt +/**The filename, file size, file serial number and the number of packages will be logged to dlt. + * @param fileContext Specific context + * @param filename Absolute file path + * @return Returns 0 if everything was okey.If there was a failure a value < 0 will be returned. + */ +int dlt_user_log_file_infoAbout(DltContext *fileContext, const char *filename){ + + if(isFile(filename)) + { + DLT_LOG(*fileContext,DLT_LOG_INFO, + DLT_STRING("FLIF"), + DLT_STRING("file serialnumber"),DLT_UINT(getFileSerialNumber(filename)), + DLT_STRING("filename"),DLT_STRING(filename), + DLT_STRING("file size in bytes"),DLT_UINT(getFilesize(filename)), + DLT_STRING("file creation date"),DLT_STRING(getFileCreationDate2(filename)), + DLT_STRING("number of packages"),DLT_UINT(dlt_user_log_file_packagesCount(fileContext, filename)), + DLT_STRING("FLIF") + ); + return 0; + } else { + + dlt_user_log_file_errorMessage(fileContext,filename,ERROR_INFO_ABOUT); + return ERROR_INFO_ABOUT; + } +} + +//!Transfer the complete file as several dlt logs. +/**This method transfer the complete file as several dlt logs. At first it will be checked that the file exist. + * In the next step some generic informations about the file will be logged to dlt. + * Now the header will be logged to dlt. See the method dlt_user_log_file_header for more informations. + * Then the method dlt_user_log_data will be called with the parameter to log all packages in a loop with some timeout. + * 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. + * @param fileContext Specific context to log the file to dlt + * @param filename Absolute file path + * @param deleteFlag Flag if the file will be deleted after transfer. 1->delete, 0->notDelete + * @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. + * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned. + */ +int dlt_user_log_file_complete(DltContext *fileContext, const char *filename, int deleteFlag, int timeout) +{ + //No signal handling in library - part of the main program! + //signal(SIGABRT, &sighandler); + //signal(SIGTERM, &sighandler); + //signal(SIGINT, &sighandler); + + if(!isFile(filename)) + { + dlt_user_log_file_errorMessage(fileContext,filename, ERROR_FILE_COMPLETE); + return ERROR_FILE_COMPLETE; + } + + //dlt_user_log_file_infoAbout(fileContext,filename); + + if(dlt_user_log_file_header(fileContext,filename) != 0) + { + return ERROR_FILE_COMPLETE1; + } + + if(dlt_user_log_file_data(fileContext, filename,LONG_MAX,timeout) != 0) + { + return ERROR_FILE_COMPLETE2; + } + + if(dlt_user_log_file_end(fileContext,filename, deleteFlag) != 0) + { + return ERROR_FILE_COMPLETE3; + } + + return 0; +} + +//!This method gives information about the number of packages the file have +/**Every file will be divided into several packages. Every package will be logged as a single dlt log. + * The number of packages depends on the BUFFER_SIZE. + * At first it will be checked if the file exist. Then the file will be divided into + * several packages depending on the buffer size. + * @param fileContext Specific context to log the file to dlt + * @param filename Absolute file path + * @return Returns the number of packages if everything was okey. If there was a failure a value < 0 will be returned. + */ +int dlt_user_log_file_packagesCount(DltContext *fileContext, const char *filename){ + int packages; + long filesize; + + if(isFile(filename)) + { + packages = 1; + filesize = getFilesize(filename); + if(filesize < BUFFER_SIZE) + { + return packages; + } + else + { + packages = filesize/BUFFER_SIZE; + + if(filesize%BUFFER_SIZE == 0) + { + return packages; + } + else + { + return packages+1; + } + } + } else { + dlt_user_log_file_errorMessage(fileContext,filename,ERROR_PACKAGE_COUNT); + return -1; + } +} + +//!Transfer the head of the file as a dlt logs. +/**The head of the file must be logged to dlt because the head contains inforamtion about the file serial number, + * the file name, the file size, package number the file have and the buffer size. + * All these informations are needed from the plugin of the dlt viewer. + * See the Mainpages.c for more informations. + * @param fileContext Specific context to log the file to dlt + * @param filename Absolute file path + * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned. + */ +int dlt_user_log_file_header(DltContext *fileContext,const char *filename){ + + if(isFile(filename)) + { + DLT_LOG(*fileContext,DLT_LOG_INFO, + DLT_STRING("FLST"), + DLT_UINT(getFileSerialNumber(filename)), + DLT_STRING(filename), + DLT_UINT(getFilesize(filename)), + DLT_STRING(getFileCreationDate2(filename)); + DLT_UINT(dlt_user_log_file_packagesCount(fileContext,filename)), + DLT_UINT(BUFFER_SIZE), + DLT_STRING("FLST") + ); + + return 0; + } + else + { + dlt_user_log_file_errorMessage(fileContext,filename, ERROR_FILE_HEAD); + return ERROR_FILE_HEAD; + } +} + +//!Transfer the content data of a file. +/**See the Mainpages.c for more informations. + * @param fileContext Specific context to log the file to dlt + * @param filename Absolute file path + * @param packageToTransfer Package number to transfer. If this param is LONG_MAX, the whole file will be transferred with a specific timeout + * @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. + * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned. + */ +int dlt_user_log_file_data(DltContext *fileContext,const char *filename, int packageToTransfer, int timeout){ + FILE *file; + int i,pkgNumber; + long positionIndicator,readBytes; + + if(isFile(filename)) + { + + file = fopen (filename,"rb"); + if (file == NULL) + { + dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_DATA); + return ERROR_FILE_DATA; + } + + if( (packageToTransfer != LONG_MAX && packageToTransfer > dlt_user_log_file_packagesCount(fileContext,filename)) || packageToTransfer <= 0) + { + DLT_LOG(*fileContext,DLT_LOG_ERROR, + DLT_STRING("Error at dlt_user_log_file_data: packageToTransfer out of scope"), + DLT_STRING("packageToTransfer:"), + DLT_UINT(packageToTransfer), + DLT_STRING("numberOfMaximalPackages:"), + DLT_UINT(dlt_user_log_file_packagesCount(fileContext,filename)), + DLT_STRING("for File:"), + DLT_STRING(filename) + ); + return ERROR_FILE_DATA; + } + + readBytes = 0; + + if(packageToTransfer != LONG_MAX) + { + fseek ( file , (packageToTransfer-1)*BUFFER_SIZE , SEEK_SET ); + readBytes = fread(buffer, sizeof(char), BUFFER_SIZE, file); + + DLT_LOG(*fileContext,DLT_LOG_INFO, + DLT_STRING("FLDA"), + DLT_UINT(getFileSerialNumber(filename)), + DLT_UINT(packageToTransfer), + DLT_RAW(buffer,readBytes), + DLT_STRING("FLDA") + ); + + doTimeout(timeout); + + } else { + pkgNumber = 0; + while( !feof( file ) ) + { + pkgNumber++; + readBytes = fread(buffer, sizeof(char), BUFFER_SIZE, file); + + DLT_LOG(*fileContext,DLT_LOG_INFO, + DLT_STRING("FLDA"), + DLT_UINT(getFileSerialNumber(filename)), + DLT_UINT(pkgNumber), + DLT_RAW(buffer,readBytes), + DLT_STRING("FLDA") + ); + + doTimeout(timeout); + } + } + + fclose(file); + + return 0; + + } else { + dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_DATA); + return ERROR_FILE_DATA; + } + +} +//!Transfer the end of the file as a dlt logs. +/**The end of the file must be logged to dlt because the end contains inforamtion about the file serial number. + * This informations is needed from the plugin of the dlt viewer. + * See the Mainpages.c for more informations. + * @param fileContext Specific context to log the file to dlt + * @param filename Absolute file path + * @param deleteFlag Flag to delete the file after the whole file is transferred (logged to dlt).1->delete,0->NotDelete + * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned. + */ +int dlt_user_log_file_end(DltContext *fileContext,const char *filename,int deleteFlag){ + + if(isFile(filename)) + { + + DLT_LOG(*fileContext,DLT_LOG_INFO, + DLT_STRING("FLFI"), + DLT_UINT(getFileSerialNumber(filename)), + DLT_STRING("FLFI") + ); + + if(deleteFlag){ + if( doRemoveFile(filename) != 0 ){ + dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_END); + return -1; + } + } + + return 0; + }else{ + dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_END); + return ERROR_FILE_END; + } +} |