+/**
+ * @licence app begin@
+ * Copyright (C) 2012 BMW AG
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ * Contributions are licensed to the GENIVI Alliance under one or more
+ * Contribution License Agreements.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Alexander Wenzel <alexander.aw.wenzel@bmw.de> BMW 2011-2012
+ *
+ * \file dlt_filetransfer.c
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt-test-client.c **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de **
+** **
+** PURPOSE : **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** aw Alexander Wenzel BMW **
+*******************************************************************************/
+
#include "dlt_filetransfer.h"
//!Defines the buffer size of a single file package which will be logged to dlt
#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
+#define DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES LONG_MAX
//!Buffer for dlt file transfer. The size is defined by BUFFER_SIZE
return (unsigned long)st.st_size;
}
+/** A simple Hash function for C-strings
+ * @param str input string. E.g. a file path.
+ * @param hash start and result value for hash computation
+ *
+ */
+void stringHash(const char* str, unsigned long *hash )
+{
+ if (!str || !hash)
+ return;
+ unsigned int len = strlen(str);
+
+ unsigned int i = 0;
+ if (len <= 0){
+ return;
+ }
+
+ for(i = 0; i < len; i++)
+ {
+ *hash = 53 * *hash + str[i];
+ }
+
+}
+
+
//!Get some information about the file serial number of a file
/** See stat(2) for more informations.
* @param file Absolute file path
*/
unsigned long getFileSerialNumber(const char* file){
struct stat st;
+ unsigned long ret;
stat(file, &st);
- return (unsigned long)st.st_ino;
+ ret = st.st_ino;
+ ret = ret << (sizeof(ret)*8)/2;
+ ret |= st.st_size;
+ ret ^= st.st_ctime;
+ stringHash(file, &ret);
+ return ret;
}
//!Returns the creation date of a file
stat(file, &st);
return st.st_ctime;
}
+
+//!Returns the creation date of a file
+/** Format of the creation date is Day Mon dd hh:mm:ss yyyy
+ * @param file Absolute file path
+ * @return Returns the creation date of a file
+*/
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
//!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
+ * @param timeout Timeout to in ms but can not be smaller as MIN_TIMEOUT
*/
void doTimeout(int timeout)
{
+ usleep(timeout * 1000);
+}
+
+//!Checks free space of the user buffer
+/**
+ * @param returns -1 if more than 50% space in the user buffer is free. Otherwise 1 will be returned.
+ */
+int checkUserBufferForFreeSpace()
+{
int total_size, used_size;
-
+
dlt_user_check_buffer(&total_size, &used_size);
-
- /* sleep only if more than 50% of buffer used */
+
if((total_size - used_size) < (total_size/2))
{
- printf("Wait %d of %d already used\n",used_size,total_size);
-
- if(timeout>MIN_TIMEOUT)
- {
- usleep(timeout * 1000);
- }
- else
- {
- usleep(MIN_TIMEOUT * 1000);
- }
+ return -1;
}
+ return 1;
}
//!Deletes the given file
void dlt_user_log_file_errorMessage(DltContext *fileContext, const char *filename, int errorCode){
- if(-errno != -2)
+ if(errno != ENOENT)
{
DLT_LOG(*fileContext,DLT_LOG_ERROR,
DLT_STRING("FLER"),
);
return 0;
} else {
-
- dlt_user_log_file_errorMessage(fileContext,filename,ERROR_INFO_ABOUT);
- return ERROR_INFO_ABOUT;
+ dlt_user_log_file_errorMessage(fileContext,filename,DLT_FILETRANSFER_ERROR_INFO_ABOUT);
+ return DLT_FILETRANSFER_ERROR_INFO_ABOUT;
}
}
*/
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_errorMessage(fileContext,filename, DLT_FILETRANSFER_ERROR_FILE_COMPLETE);
+ return DLT_FILETRANSFER_ERROR_FILE_COMPLETE;
}
- //dlt_user_log_file_infoAbout(fileContext,filename);
-
if(dlt_user_log_file_header(fileContext,filename) != 0)
{
- return ERROR_FILE_COMPLETE1;
+ return DLT_FILETRANSFER_ERROR_FILE_COMPLETE1;
}
- if(dlt_user_log_file_data(fileContext, filename,LONG_MAX,timeout) != 0)
+ if(dlt_user_log_file_data(fileContext, filename,DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES,timeout) != 0)
{
- return ERROR_FILE_COMPLETE2;
+ return DLT_FILETRANSFER_ERROR_FILE_COMPLETE2;
}
if(dlt_user_log_file_end(fileContext,filename, deleteFlag) != 0)
{
- return ERROR_FILE_COMPLETE3;
+ return DLT_FILETRANSFER_ERROR_FILE_COMPLETE3;
}
return 0;
}
}
} else {
- dlt_user_log_file_errorMessage(fileContext,filename,ERROR_PACKAGE_COUNT);
+ dlt_user_log_file_errorMessage(fileContext,filename,DLT_FILETRANSFER_ERROR_PACKAGE_COUNT);
return -1;
}
}
* See the Mainpages.c for more informations.
* @param fileContext Specific context to log the file to dlt
* @param filename Absolute file path
+ * @param alias Alias for the file. An alternative name to show in the receiving end
+ * @return Returns 0 if everything was okey. If there was a failure a value < 0 will be returned.
+ */
+int dlt_user_log_file_header_alias(DltContext *fileContext,const char *filename, const char *alias){
+
+ if(isFile(filename))
+ {
+ DLT_LOG(*fileContext,DLT_LOG_INFO,
+ DLT_STRING("FLST"),
+ DLT_UINT(getFileSerialNumber(filename)),
+ DLT_STRING(alias),
+ 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, DLT_FILETRANSFER_ERROR_FILE_HEAD);
+ return DLT_FILETRANSFER_ERROR_FILE_HEAD;
+ }
+}
+
+//!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){
}
else
{
- dlt_user_log_file_errorMessage(fileContext,filename, ERROR_FILE_HEAD);
- return ERROR_FILE_HEAD;
+ dlt_user_log_file_errorMessage(fileContext,filename, DLT_FILETRANSFER_ERROR_FILE_HEAD);
+ return DLT_FILETRANSFER_ERROR_FILE_HEAD;
}
}
file = fopen (filename,"rb");
if (file == NULL)
{
- dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_DATA);
- return ERROR_FILE_DATA;
+ dlt_user_log_file_errorMessage(fileContext,filename,DLT_FILETRANSFER_ERROR_FILE_DATA);
+ return DLT_FILETRANSFER_ERROR_FILE_DATA;
}
- if( (packageToTransfer != LONG_MAX && packageToTransfer > dlt_user_log_file_packagesCount(fileContext,filename)) || packageToTransfer <= 0)
+ if( (packageToTransfer != DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES && 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("for File:"),
DLT_STRING(filename)
);
- return ERROR_FILE_DATA;
+ fclose(file);
+ return DLT_FILETRANSFER_ERROR_FILE_DATA;
}
readBytes = 0;
- if(packageToTransfer != LONG_MAX)
+ if(packageToTransfer != DLT_FILETRANSFER_TRANSFER_ALL_PACKAGES)
{
+// If a single package should be transferred. The user has to check that the free space in the user buffer > 50%
+// if(checkUserBufferForFreeSpace()<0)
+// return DLT_FILETRANSFER_ERROR_FILE_DATA_USER_BUFFER_FAILED;
+
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")
+ 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")
- );
+// If the complete file should be transferred, the user buffer will be checked.
+// If free space < 50% the package won't be transferred.
+ if(checkUserBufferForFreeSpace()>0)
+ {
+ pkgNumber++;
+ readBytes = fread(buffer, sizeof(char), BUFFER_SIZE, file);
- doTimeout(timeout);
+ 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);
}
}
return 0;
} else {
- dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_DATA);
- return ERROR_FILE_DATA;
+ dlt_user_log_file_errorMessage(fileContext,filename,DLT_FILETRANSFER_ERROR_FILE_DATA);
+ return DLT_FILETRANSFER_ERROR_FILE_DATA;
}
}
if(deleteFlag){
if( doRemoveFile(filename) != 0 ){
- dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_END);
+ dlt_user_log_file_errorMessage(fileContext,filename,DLT_FILETRANSFER_ERROR_FILE_END);
return -1;
}
}
return 0;
}else{
- dlt_user_log_file_errorMessage(fileContext,filename,ERROR_FILE_END);
- return ERROR_FILE_END;
+ dlt_user_log_file_errorMessage(fileContext,filename,DLT_FILETRANSFER_ERROR_FILE_END);
+ return DLT_FILETRANSFER_ERROR_FILE_END;
}
}