/* * FileSystem.c * * Created on: Oct 23, 2018 * Author: shlomo */ #include "include.h" #include "Communication/CommunicationTask.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "third_party/fatfs/src/ffconf.h" #include "third_party/fatfs/src/diskio.h" #include "drivers/Flash_Memory/Flash_Memory.h" #include "drivers/Flash_Memory/fatfs/ff.h" #include "third_party/fatfs/src/ffconf.h" ErrorCode FileError_to_ErrorCode[FR_INVALID_PARAMETER+1] = {ERROR_CODE__NONE,ERROR_CODE__FILE_REQUEST_DISK_ERR,ERROR_CODE__FILE_REQUEST_INT_ERR,ERROR_CODE__FILE_REQUEST_NOT_READY,ERROR_CODE__FILE_REQUEST_NO_FILE, ERROR_CODE__FILE_REQUEST_NO_PATH,ERROR_CODE__FILE_REQUEST_INVALID_NAME,ERROR_CODE__FILE_REQUEST_DENIED,ERROR_CODE__FILE_REQUEST_EXIST,ERROR_CODE__FILE_REQUEST_INVALID_OBJECT, ERROR_CODE__FILE_REQUEST_WRITE_PROTECTED,ERROR_CODE__FILE_REQUEST_INVALID_DRIVE,ERROR_CODE__FILE_REQUEST_NOT_ENABLED,ERROR_CODE__FILE_REQUEST_NO_FILESYSTEM, ERROR_CODE__FILE_REQUEST_MKFS_ABORTED,ERROR_CODE__FILE_REQUEST_TIMEOUT,ERROR_CODE__FILE_REQUEST_LOCKED,ERROR_CODE__FILE_REQUEST_NOT_ENOUGH_CORE,ERROR_CODE__FILE_REQUEST_TOO_MANY_OPEN_FILES, ERROR_CODE__FILE_REQUEST_INVALID_PARAMETER}; FIL *UploadFileHandle = 0; //the system supports a single active file FIL *DownloadFileHandle = 0; //the system supports a single active file char FileHandleChar[5]; char ErrorMsg[100]; #define MAX_CHUNK_LENGTH 4000 int32_t FileLength = 0; int32_t FileReceivedLength = 0; int32_t FileSentLength = 0; static char g_cCwdBuf[50] = "/"; uint32_t WrittenBytes = 0; uint32_t ReadBytes = 0; ErrorCode getErrorCode(FRESULT Fresult) { return FileError_to_ErrorCode[Fresult]; } bool isDirectory(FileAttribute FileAtt) { if (FileAtt&&FILE_ATTRIBUTE__Directory) return true; return false; } uint32_t FileUploadRequestFunc(MessageContainer* requestContainer) { //uint32_t status = OK; FRESULT Fresult = FR_OK; MessageContainer responseContainer; FileUploadRequest* request = file_upload_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); FileUploadResponse response = FILE_UPLOAD_RESPONSE__INIT; WrittenBytes=0; UploadFileHandle = my_malloc(sizeof(FIL)); if (UploadFileHandle == 0) Fresult = FR_DENIED; else { Fresult = f_open(UploadFileHandle,request->path,FA_READ | FA_WRITE | FA_OPEN_ALWAYS ); if (Fresult == FR_OK) { FileLength = request->length; response.has_maxchunklength = true; response.maxchunklength = MAX_CHUNK_LENGTH; strcpy(FileHandleChar, "1234"); response.uploadid = FileHandleChar; //supporting only single file at each time. } else { free (UploadFileHandle); UploadFileHandle = 0; } } responseContainer = createContainer(MESSAGE_TYPE__FileUploadResponse, requestContainer->token, false, &response, &file_upload_response__pack, &file_upload_response__get_packed_size); if (Fresult!= FR_OK) { responseContainer.error = getErrorCode(Fresult); responseContainer.errormessage = "File operation error"; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); my_free(responseContainer.data.data); file_upload_request__free_unpacked(request,NULL); SendChars(container_buffer, container_size); return OK; } uint32_t FileChunkUploadRequestFunc(MessageContainer* requestContainer) { //uint32_t status = OK; FRESULT Fresult = FR_OK; MessageContainer responseContainer; FileChunkUploadRequest* request = file_chunk_upload_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); FileChunkUploadResponse response = FILE_CHUNK_UPLOAD_RESPONSE__INIT; FIL *ReceivedFileHandle; //the system supports a single active file // if (request->uploadid == 1) ReceivedFileHandle = UploadFileHandle; // memcpy (&ReceivedFileHandle,request->uploadid,sizeof(ReceivedFileHandle)); //if (ReceivedFileHandle == FileHandle) //{ Fresult = f_write(ReceivedFileHandle,request->buffer.data,request->buffer.len,&WrittenBytes ); if(Fresult != FR_OK) { LOG_ERROR (Fresult,"f_write error"); } else { FileReceivedLength += WrittenBytes; if (FileReceivedLength == FileLength) { REPORT_MSG (FileReceivedLength,"file upload ended successfully"); f_close(ReceivedFileHandle); free (UploadFileHandle); FileReceivedLength = 0; } else { if (FileReceivedLength > FileLength) { REPORT_MSG (FileReceivedLength,"file upload too much data!"); f_close(ReceivedFileHandle); free (UploadFileHandle); FileReceivedLength = 0; } } } /*} else { LOG_ERROR (ReceivedFileHandle,"file id error"); f_close(FileHandle); free (FileHandle); status = ERROR_CODE__FILE_NOT_FOUND; }*/ responseContainer = createContainer(MESSAGE_TYPE__FileChunkUploadResponse, requestContainer->token, false, &response, &file_chunk_upload_response__pack, &file_chunk_upload_response__get_packed_size); if (Fresult!= OK) { responseContainer.error = getErrorCode(Fresult); responseContainer.errormessage = "File operation error"; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); file_chunk_upload_request__free_unpacked(request,NULL); my_free(responseContainer.data.data); SendChars(container_buffer, container_size); return OK; } uint32_t FileDownloadRequestFunc(MessageContainer* requestContainer) { //uint32_t status = OK; FRESULT Fresult = FR_OK; FILINFO* fno; MessageContainer responseContainer; FileDownloadRequest* request = file_download_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); FileDownloadResponse response = FILE_DOWNLOAD_RESPONSE__INIT; ReadBytes=0; FileSentLength = 0; fno = my_malloc(sizeof(FILINFO)); if (fno == 0) Fresult = FR_DENIED; else { memset (fno,0,sizeof(FILINFO)); Fresult = f_stat(request->filename,fno); FileLength = fno->fsize; DownloadFileHandle = my_malloc(sizeof(FIL)); if (DownloadFileHandle == 0) Fresult = FR_DENIED; else { Fresult = f_open(DownloadFileHandle,request->filename,FA_READ ); if (Fresult == FR_OK) { response.has_maxchunklength = true; response.maxchunklength = MAX_CHUNK_LENGTH; strcpy(FileHandleChar, "1234"); response.downloadid = FileHandleChar; //supporting only single file at each time. } } } responseContainer = createContainer(MESSAGE_TYPE__FileDownloadResponse, requestContainer->token, false, &response, &file_download_response__pack, &file_download_response__get_packed_size); if (Fresult!= FR_OK) { responseContainer.error = getErrorCode(Fresult); responseContainer.errormessage = "File operation error"; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); my_free(responseContainer.data.data); file_download_request__free_unpacked(request,NULL); SendChars(container_buffer, container_size); my_free(fno); return OK; } uint32_t FileChunkDownloadRequestFunc(MessageContainer* requestContainer) { MessageContainer responseContainer; FileChunkDownloadRequest* request = file_chunk_download_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); FileChunkDownloadResponse response = FILE_CHUNK_DOWNLOAD_RESPONSE__INIT; FRESULT Fresult = FR_OK; FIL *SentFileHandle; //the system supports a single active file SentFileHandle = DownloadFileHandle; char *Buffer = 0; Buffer = my_malloc (MAX_CHUNK_LENGTH); if (Buffer != NULL) { Fresult = f_read(SentFileHandle,Buffer,2000,&ReadBytes ); if(Fresult != FR_OK) { LOG_ERROR (Fresult,"f_write error"); } else { response.has_buffer = true; response.buffer.len = ReadBytes; response.buffer.data = Buffer; FileSentLength += ReadBytes; if (FileSentLength == FileLength) { REPORT_MSG (FileSentLength,"file download ended successfully"); f_close(SentFileHandle); free (DownloadFileHandle); FileSentLength = 0; } else { if (FileSentLength > FileLength) { REPORT_MSG (FileSentLength,"file download too much data!"); f_close(SentFileHandle); free (DownloadFileHandle); FileSentLength = 0; } } } } responseContainer = createContainer(MESSAGE_TYPE__FileChunkDownloadResponse, requestContainer->token, false, &response, &file_chunk_download_response__pack, &file_chunk_download_response__get_packed_size); if (Fresult!= OK) { responseContainer.error = getErrorCode(Fresult); responseContainer.errormessage = "File operation error"; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); file_chunk_download_request__free_unpacked(request,NULL); my_free(responseContainer.data.data); my_free(Buffer); SendChars(container_buffer, container_size); return OK; } uint32_t ExecuteProcessRequestFunc(MessageContainer* requestContainer) { uint32_t status = OK; MessageContainer responseContainer; ExecuteProcessRequest* request = execute_process_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); ExecuteProcessResponse response = EXECUTE_PROCESS_RESPONSE__INIT; responseContainer = createContainer(MESSAGE_TYPE__ExecuteProcessResponse, requestContainer->token, false, &response, &execute_process_response__pack, &execute_process_response__get_packed_size); if (status!= OK) { responseContainer.error = ERROR_CODE__GENERAL_ERROR;//getErrorCode(Fresult); responseContainer.errormessage = "File operation error"; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); execute_process_request__free_unpacked(request,NULL); my_free(responseContainer.data.data); SendChars(container_buffer, container_size); return OK; } uint32_t KillProcessRequestFunc(MessageContainer* requestContainer) { uint32_t status = OK; MessageContainer responseContainer; KillProcessRequest* request = kill_process_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); KillProcessResponse response = KILL_PROCESS_RESPONSE__INIT; responseContainer = createContainer(MESSAGE_TYPE__KillProcessResponse, requestContainer->token, false, &response, &kill_process_response__pack, &kill_process_response__get_packed_size); if (status!= OK) { responseContainer.error = ERROR_CODE__GENERAL_ERROR;//getErrorCode(Fresult); responseContainer.errormessage = "File operation error"; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); my_free(responseContainer.data.data); kill_process_request__free_unpacked(request,NULL); SendChars(container_buffer, container_size); return OK; } uint32_t CreateRequestFunc(MessageContainer* requestContainer) { //uint32_t status = OK; FRESULT Fresult = FR_OK; MessageContainer responseContainer; CreateRequest* request = create_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); CreateResponse response = CREATE_RESPONSE__INIT; if (isDirectory(request->attribute)) { Fresult = f_mkdir(request->path); } else { UploadFileHandle = my_malloc(sizeof(FIL)); if (UploadFileHandle == 0) Fresult = FR_DENIED; else { Fresult = f_open(UploadFileHandle,request->path,FA_CREATE_NEW); if (Fresult == FR_OK) { if (f_close (UploadFileHandle)!= FR_OK) { Fresult = FR_LOCKED; } } } } if (Fresult != FR_OK) { //status = ERROR_CODE__FILE_NOT_FOUND; usnprintf(ErrorMsg, 100, "File Operation failed error code %d",Fresult); } free (UploadFileHandle); responseContainer = createContainer(MESSAGE_TYPE__CreateResponse, requestContainer->token, false, &response, &create_response__pack, &create_response__get_packed_size); if (Fresult!= OK) { responseContainer.error = getErrorCode(Fresult); responseContainer.errormessage = "File operation error"; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); my_free(responseContainer.data.data); create_request__free_unpacked(request,NULL); SendChars(container_buffer, container_size); return OK; } uint32_t DeleteRequestFunc(MessageContainer* requestContainer) { //uint32_t status = OK; MessageContainer responseContainer; DeleteRequest* request = delete_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); DeleteResponse response = DELETE_RESPONSE__INIT; FILINFO* fno = 0; //int NumOfFiles = 0; FRESULT Fresult = FR_OK; Fresult = f_unlink(request->path); REPORT_MSG(Fresult, "File Delete"); responseContainer = createContainer(MESSAGE_TYPE__DeleteResponse, requestContainer->token, false, &response, &delete_response__pack, &delete_response__get_packed_size); if (Fresult!= OK) { usnprintf(ErrorMsg, 100, "File Operation failed error code %d",Fresult); responseContainer.error = getErrorCode(Fresult); responseContainer.errormessage = ErrorMsg; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); my_free(responseContainer.data.data); my_free(fno); delete_request__free_unpacked(request,NULL); SendChars(container_buffer, container_size); return OK; } uint32_t GetStorageInfoRequestFunc(MessageContainer* requestContainer) { //uint32_t status = OK; MessageContainer responseContainer; GetStorageInfoRequest* request = get_storage_info_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); GetStorageInfoResponse response = GET_STORAGE_INFO_RESPONSE__INIT; FATFS *fs; DWORD fre_clust, fre_sect, tot_sect; FRESULT Fresult = FR_OK; /* Get volume information and free clusters of drive 1 */ Fresult = f_getfree("0:", &fre_clust, &fs); if (Fresult == FR_OK) { /* Get total sectors and free sectors */ tot_sect = (fs->n_fatent - 2) * fs->csize; fre_sect = fre_clust * fs->csize; response.has_capacity = true; response.capacity = tot_sect/2*1024; response.has_freespace = true; response.freespace = fre_sect/2*1024; response.root = "/"; } responseContainer = createContainer(MESSAGE_TYPE__GetStorageInfoResponse, requestContainer->token, false, &response, &get_storage_info_response__pack, &get_storage_info_response__get_packed_size); if (Fresult!= OK) { responseContainer.error = getErrorCode(Fresult); responseContainer.errormessage = "File operation error"; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); my_free(responseContainer.data.data); get_storage_info_request__free_unpacked(request,NULL); SendChars(container_buffer, container_size); return OK; } uint32_t GetFilesRequestFunc(MessageContainer* requestContainer) { //uint32_t status = OK; MessageContainer responseContainer; GetFilesRequest* request = get_files_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); GetFilesResponse response = GET_FILES_RESPONSE__INIT; #define MAX_NUM_OF_FILES 10 DIR dir; FILINFO* fno[MAX_NUM_OF_FILES]; char FullPath[MAX_NUM_OF_FILES][50]; int i,NumOfFiles = 0; FRESULT Fresult = FR_OK; Fresult |= f_opendir(&dir, g_cCwdBuf); if(Fresult != FR_OK) { return(Fresult); } memset (fno,0,sizeof(fno)); FileInfo **FilesInfo = (FileInfo**)my_malloc(sizeof(FileInfo *)*(MAX_NUM_OF_FILES)); FileInfo Data[MAX_NUM_OF_FILES]; memset(fno,0,sizeof(fno)); fno[0] = my_malloc(sizeof(FILINFO)); memset (fno[0],0,sizeof(FILINFO)); //============================ Fresult = f_opendir(&dir, request->path); /* Open the directory */ if (Fresult == FR_OK) { for (NumOfFiles = 1;NumOfFiles < MAX_NUM_OF_FILES;NumOfFiles++) { fno[NumOfFiles] = my_malloc(sizeof(FILINFO)); memset (fno[NumOfFiles],0,sizeof(FILINFO)); Fresult = f_readdir(&dir, fno[NumOfFiles]); /* Read a directory item */ if (Fresult == FR_OK) { if(fno[NumOfFiles]->fname[0] ==0) { break; } } } } if ((Fresult == FR_OK)&&(NumOfFiles)) { for (i = 0;i < NumOfFiles;i++) { file_info__init(&Data[i]); FilesInfo[i] = &Data[i]; Data[i].has_attribute = true; Data[i].attribute = fno[i]->fattrib; Data[i].name = fno[i]->fname; Data[i].has_length = true; Data[i].length = fno[i]->fsize; Data[i].lastmodifieddate = fno[i]->fdate; Data[i].lastmodifiedtime = fno[i]->ftime; if (i==0) usnprintf(&FullPath[i], 50, "%s", request->path); else if (strlen(request->path)==1) //info under the root usnprintf(&FullPath[i], 50, "%s%s", request->path, fno[i]->fname); else usnprintf(&FullPath[i], 50, "%s%s%s", request->path,"/", fno[i]->fname); Data[i].fullpath = &FullPath[i]; } response.n_items = NumOfFiles; response.items = FilesInfo; } else { response.n_items = 0; response.items = NULL; } responseContainer = createContainer(MESSAGE_TYPE__GetFilesResponse, requestContainer->token, false, &response, &get_files_response__pack, &get_files_response__get_packed_size); if (Fresult!= OK) { responseContainer.error = getErrorCode(Fresult); responseContainer.errormessage = "File operation error"; } responseContainer.continuous = false; uint8_t* container_buffer = my_malloc(message_container__get_packed_size(&responseContainer)); size_t container_size = message_container__pack(&responseContainer, container_buffer); my_free(responseContainer.data.data); my_free(FilesInfo); get_files_request__free_unpacked(request,NULL); SendChars(container_buffer, container_size); for (i = 0;i < NumOfFiles;i++) { if (fno[i]) my_free (fno[i]); } return Fresult; } FRESULT FileWrite(void * buffer, uint16_t size,char *path) { FRESULT Fresult = FR_OK; FIL *FileHandle = 0; //the system supports a single active file uint32_t Bytes = 0; if (buffer) { FileHandle = my_malloc(sizeof(FIL)); if (FileHandle == 0) Fresult = FR_DENIED; else { Fresult = f_open(FileHandle,path,FA_WRITE | FA_OPEN_ALWAYS); if (Fresult == FR_OK) { Fresult = f_write(FileHandle,buffer,size,&Bytes ); if(Fresult != FR_OK) { LOG_ERROR (Fresult,"fread error"); } f_close(FileHandle); } else { LOG_ERROR (Fresult,"fopen error"); } my_free(FileHandle); } } return Fresult; } FRESULT FileRead(char *path, uint32_t *Size, void **Buffer) { FRESULT Fresult = FR_OK; FIL *FileHandle = 0; //the system supports a single active file FILINFO* fno = 0; void* buffer = NULL; uint32_t Bytes = 0; //uint32_t status = 0; fno = my_malloc(sizeof(FILINFO)); if (fno == 0) return ERROR; memset (fno,0,sizeof(FILINFO)); Fresult = f_stat(path,fno); if (Fresult == FR_OK) { buffer = my_malloc (fno->fsize); if (buffer) { FileHandle = my_malloc(sizeof(FIL)); if (FileHandle == 0) Fresult = FR_DENIED; else { Fresult = f_open(FileHandle,path,FA_READ); if (Fresult == FR_OK) { Fresult = f_read(FileHandle,buffer,fno->fsize,&Bytes ); if(Fresult == FR_OK) { *Buffer = buffer; *Size = (uint32_t)fno->fsize; } else { LOG_ERROR (Fresult,"fread error"); my_free (buffer); } f_close(FileHandle); } else { LOG_ERROR (Fresult,"fopen error"); my_free (buffer); } my_free(FileHandle); } } else { LOG_ERROR (Fresult,"malloc error"); } } else { LOG_ERROR (Fresult,"f_stat error"); } my_free(fno); return Fresult; } FRESULT FileOpen(char *path, uint32_t *Size, FIL *FileHandle) { FRESULT Fresult = FR_OK; FILINFO* fno = 0; fno = my_malloc(sizeof(FILINFO)); if (fno == 0) return ERROR; memset (fno,0,sizeof(FILINFO)); Fresult = f_stat(path,fno); *Size = (uint32_t)fno->fsize; if (Fresult == FR_OK) { //FileHandle = my_malloc(sizeof(FIL)); if (FileHandle == 0) Fresult = FR_DENIED; else Fresult = f_open(FileHandle,path,FA_READ); } else { LOG_ERROR (Fresult,"f_stat error"); } my_free(fno); return Fresult; }