Toyomasa Watarai
/
Mbed-example-WS-W27
Mbed Cloud example program for workshop in W27 2018.
Embed:
(wiki syntax)
Show/hide line numbers
pal_plat_fileSystem.c
00001 #include "pal.h" 00002 #include "pal_plat_fileSystem.h" 00003 #include "pal_plat_rtos.h" 00004 00005 00006 #if defined(__GNUC__) && !defined(__CC_ARM) 00007 #include <sys/stat.h> 00008 #include <sys/types.h> 00009 #endif // defined(__GNUC__) && !defined(__CC_ARM) 00010 #include <stdio.h> 00011 #include <string.h> 00012 #include <stdlib.h> 00013 #include "fsl_mpu.h" 00014 #include "ff.h" 00015 #include "diskio.h" 00016 #include "sdhc_config.h" 00017 00018 00019 #define CHK_FD_VALIDITY(x) ((FIL *)x)->fs->id != ((FIL *)x)->id 00020 #define PAL_FS_ALIGNMENT_TO_SIZE 4 //!< This Size control the number of bytes written to the file (bug fix for writing unaligned memory to file) 00021 #define PAL_FS_COPY_BUFFER_SIZE 256 //!< Size of the chunk to copy files 00022 PAL_PRIVATE BYTE g_platOpenModeConvert[] = 00023 { 00024 0, 00025 FA_READ | FA_OPEN_EXISTING, //"r" 00026 FA_WRITE | FA_READ| FA_OPEN_EXISTING, //"r+" 00027 FA_WRITE | FA_READ| FA_CREATE_NEW, //"w+x" 00028 FA_WRITE | FA_READ| FA_CREATE_ALWAYS //"w+" 00029 }; //!< platform convert table for \b fopen() modes 00030 00031 00032 /*! \brief This function find the next file in a directory 00033 * 00034 * @param[in] *dh - Directory handler to an open DIR 00035 * @param[out] CurrentEntry - entry for the file found in Directory (pre allocated) 00036 * 00037 * \return true - upon successful operation.\n 00038 * 00039 */ 00040 PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, FILINFO * CurrentEntry); 00041 00042 /*! \brief This function translate the platform errors opcode to pal error codes 00043 * 00044 * @param[in] errorOpCode - platform opcode to be translated 00045 * 00046 * \return PAL_SUCCESS upon successful operation.\n 00047 */ 00048 PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode); 00049 00050 /*! \brief This function build the full path name by adding the filename to the working path given in pathName arg 00051 * 00052 * @param[in] *pathName - pointer to the null-terminated string that specifies the directory name. 00053 * @param[in] *fileName - pointer to the file name 00054 * @param[out] *fullPath - pointer to the full path including the filename (pre allocated) 00055 * 00056 * \return PAL_SUCCESS upon successful operation.\n 00057 * PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t 00058 * 00059 */ 00060 PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath); 00061 00062 /*! \brief This function copy one file from source folder to destination folder 00063 * 00064 * @param[in] pathNameSrc - Pointer to a null-terminated string that specifies the source dir. 00065 * @param[in] pathNameDest - Pointer to a null-terminated string that specifies the destination dir 00066 * @param[in] fileName - pointer the the file name 00067 * 00068 * \return PAL_SUCCESS upon successful operation.\n 00069 * PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t 00070 * 00071 * \note File should not be open.\n 00072 * If the Destination file exist then it shall be truncated 00073 * 00074 */ 00075 PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc, char *pathNameDest, char * fileName); 00076 00077 palStatus_t pal_plat_fsMkdir(const char *pathName) 00078 { 00079 palStatus_t ret = PAL_SUCCESS; 00080 FRESULT status = FR_OK; 00081 status = f_mkdir(pathName); 00082 if (status != FR_OK) 00083 { 00084 ret = pal_plat_errorTranslation(status); 00085 } 00086 return ret; 00087 } 00088 00089 00090 palStatus_t pal_plat_fsRmdir(const char *pathName) 00091 { 00092 palStatus_t ret = PAL_SUCCESS; 00093 FRESULT status = FR_OK; 00094 00095 status = f_unlink(pathName); 00096 if (status != FR_OK) 00097 { 00098 if ( status == FR_DENIED) 00099 { 00100 ret = PAL_ERR_FS_DIR_NOT_EMPTY; 00101 } 00102 else if (status == FR_NO_FILE) 00103 { 00104 ret = PAL_ERR_FS_NO_PATH; 00105 } 00106 else 00107 { 00108 ret = pal_plat_errorTranslation(status); 00109 } 00110 } 00111 00112 return ret; 00113 } 00114 00115 00116 palStatus_t pal_plat_fsFopen(const char *pathName, pal_fsFileMode_t mode, palFileDescriptor_t *fd) 00117 { 00118 palStatus_t ret = PAL_SUCCESS; 00119 FRESULT status = FR_OK; 00120 FIL * descriptor = NULL; 00121 00122 descriptor = (FIL *)pal_plat_malloc (sizeof(FIL)); 00123 if (descriptor) 00124 { 00125 *fd = (palFileDescriptor_t)descriptor; 00126 status = f_open((FIL*)*fd, pathName, g_platOpenModeConvert[mode]); 00127 if (FR_OK != status) 00128 { 00129 pal_plat_free (descriptor); 00130 if(FR_NO_PATH == status) 00131 { 00132 ret = PAL_ERR_FS_NO_FILE; 00133 } 00134 else 00135 { 00136 ret = pal_plat_errorTranslation(status); 00137 } 00138 } 00139 } 00140 00141 return ret; 00142 } 00143 00144 00145 palStatus_t pal_plat_fsFclose(palFileDescriptor_t *fd) 00146 { 00147 FRESULT status = FR_OK; 00148 palStatus_t ret = PAL_SUCCESS; 00149 00150 00151 if (CHK_FD_VALIDITY(*fd)) 00152 {//Bad File Descriptor 00153 ret = PAL_ERR_FS_BAD_FD; 00154 return ret; 00155 } 00156 00157 status = f_close((FIL *)*fd); 00158 if (FR_OK != status) 00159 { 00160 ret = pal_plat_errorTranslation(status); 00161 } 00162 else 00163 { 00164 pal_plat_free ((void*)*fd); 00165 } 00166 return ret; 00167 } 00168 00169 00170 palStatus_t pal_plat_fsFread(palFileDescriptor_t *fd, void * buffer, size_t numOfBytes, size_t *numberOfBytesRead) 00171 { 00172 palStatus_t ret = PAL_SUCCESS; 00173 FRESULT status = FR_OK; 00174 uint8_t readaligment[PAL_FS_ALIGNMENT_TO_SIZE] = { 0 }; 00175 uint32_t index = 0; 00176 size_t byteRead = 0; 00177 uint8_t leftover = 0; 00178 00179 if (CHK_FD_VALIDITY(*fd)) 00180 {//Bad File Descriptor 00181 ret = PAL_ERR_FS_BAD_FD; 00182 return ret; 00183 } 00184 00185 leftover = numOfBytes % PAL_FS_ALIGNMENT_TO_SIZE; 00186 for(index = 0; index < (numOfBytes / PAL_FS_ALIGNMENT_TO_SIZE); index++) 00187 { 00188 status = f_read((FIL *)*fd, readaligment, PAL_FS_ALIGNMENT_TO_SIZE, &byteRead); 00189 if (FR_OK != status) 00190 { 00191 ret = pal_plat_errorTranslation(status); 00192 break; 00193 } 00194 else 00195 { 00196 memcpy(&((uint8_t *)buffer)[*numberOfBytesRead], readaligment, PAL_FS_ALIGNMENT_TO_SIZE); 00197 *numberOfBytesRead += byteRead; 00198 } 00199 } 00200 00201 if ((ret == PAL_SUCCESS) && (leftover > 0)) 00202 { 00203 status = f_read((FIL *)*fd, readaligment, PAL_FS_ALIGNMENT_TO_SIZE, &byteRead); 00204 if (FR_OK != status) 00205 { 00206 ret = pal_plat_errorTranslation(status); 00207 } 00208 else 00209 { 00210 memcpy(&((uint8_t *)buffer)[*numberOfBytesRead], readaligment, leftover); 00211 *numberOfBytesRead += leftover; 00212 ret = pal_fsFseek(fd, leftover - PAL_FS_ALIGNMENT_TO_SIZE ,PAL_FS_OFFSET_SEEKCUR); 00213 } 00214 } 00215 00216 return ret; 00217 } 00218 00219 00220 palStatus_t pal_plat_fsFwrite(palFileDescriptor_t *fd, const void *buffer, size_t numOfBytes, size_t *numberOfBytesWritten) 00221 { 00222 palStatus_t ret = PAL_SUCCESS; 00223 FRESULT status = FR_OK; 00224 uint32_t index = 0; 00225 size_t bytesWritten = 0; 00226 uint8_t leftover = 0; 00227 00228 if (CHK_FD_VALIDITY(*fd)) 00229 {//Bad File Descriptor 00230 ret = PAL_ERR_FS_BAD_FD; 00231 return ret; 00232 } 00233 00234 leftover = numOfBytes % PAL_FS_ALIGNMENT_TO_SIZE; 00235 for (index = 0; index < (numOfBytes / PAL_FS_ALIGNMENT_TO_SIZE); index++) 00236 { 00237 status = f_write((FIL *)*fd, ((uint8_t *)buffer + *numberOfBytesWritten), PAL_FS_ALIGNMENT_TO_SIZE, &bytesWritten); 00238 if (FR_OK != status) 00239 { 00240 ret = pal_plat_errorTranslation(status); 00241 break; 00242 } 00243 else if (PAL_FS_ALIGNMENT_TO_SIZE != bytesWritten) 00244 { 00245 ret = PAL_ERR_FS_INSUFFICIENT_SPACE; 00246 } 00247 else 00248 { 00249 *numberOfBytesWritten += bytesWritten; 00250 } 00251 } 00252 00253 if ((ret == PAL_SUCCESS) && (leftover > 0)) 00254 { 00255 status = f_write((FIL *)*fd, ((uint8_t *)buffer + *numberOfBytesWritten), leftover, &bytesWritten); 00256 if (FR_OK != status) 00257 { 00258 ret = pal_plat_errorTranslation(status); 00259 } 00260 else if (leftover != bytesWritten) 00261 { 00262 ret = PAL_ERR_FS_INSUFFICIENT_SPACE; 00263 } 00264 else 00265 { 00266 *numberOfBytesWritten += bytesWritten; 00267 } 00268 } 00269 00270 return ret; 00271 } 00272 00273 00274 palStatus_t pal_plat_fsFseek(palFileDescriptor_t *fd, int32_t offset, pal_fsOffset_t whence) 00275 { 00276 palStatus_t ret = PAL_SUCCESS; 00277 FRESULT status = FR_OK; 00278 uint32_t fatFSOffset = 0; 00279 00280 if (CHK_FD_VALIDITY(*fd)) 00281 {//Bad File Descriptor 00282 ret = PAL_ERR_FS_BAD_FD; 00283 return ret; 00284 } 00285 00286 00287 switch(whence) 00288 { 00289 case PAL_FS_OFFSET_SEEKCUR: 00290 if (((-1)*offset > f_tell((FIL*)*fd) && (offset < 0)) || (offset > f_tell((FIL*)*fd) && (offset > 0))) 00291 { 00292 ret = PAL_ERR_FS_ERROR; 00293 } 00294 else 00295 { 00296 fatFSOffset = f_tell((FIL*)*fd) + offset; 00297 } 00298 break; 00299 00300 case PAL_FS_OFFSET_SEEKEND: 00301 if ((-1)*offset > f_size((FIL*)*fd) || (offset > 0)) 00302 { 00303 ret = PAL_ERR_FS_ERROR; 00304 } 00305 else 00306 { 00307 fatFSOffset = f_size((FIL*)*fd) + offset; 00308 } 00309 break; 00310 00311 case PAL_FS_OFFSET_SEEKSET: 00312 if (offset > f_size((FIL*)*fd)) 00313 { 00314 ret = PAL_ERR_FS_ERROR; 00315 } 00316 else 00317 { 00318 fatFSOffset = offset; 00319 } 00320 break; 00321 00322 default: 00323 fatFSOffset = 0; 00324 break; 00325 } 00326 00327 if (ret == PAL_SUCCESS) 00328 { 00329 status = f_lseek ((FIL *)*fd, fatFSOffset); 00330 if (FR_OK != status) 00331 { 00332 ret = pal_plat_errorTranslation(status); 00333 } 00334 } 00335 return ret; 00336 } 00337 00338 00339 palStatus_t pal_plat_fsFtell(palFileDescriptor_t *fd, int32_t * pos) 00340 { 00341 palStatus_t ret = PAL_SUCCESS; 00342 00343 if (CHK_FD_VALIDITY(*fd)) 00344 {//Bad File Descriptor 00345 ret = PAL_ERR_FS_BAD_FD; 00346 } 00347 else 00348 { 00349 *pos = f_tell((FIL*)*fd); 00350 } 00351 return ret; 00352 } 00353 00354 00355 palStatus_t pal_plat_fsUnlink(const char *pathName) 00356 { 00357 palStatus_t ret = PAL_SUCCESS; 00358 FRESULT status = FR_OK; 00359 00360 status = f_unlink(pathName); 00361 if (status != FR_OK) 00362 { 00363 if (status == FR_DENIED) 00364 { 00365 ret = PAL_ERR_FS_DIR_NOT_EMPTY; 00366 } 00367 else 00368 { 00369 ret = pal_plat_errorTranslation(status); 00370 } 00371 } 00372 return ret; 00373 } 00374 00375 00376 palStatus_t pal_plat_fsRmFiles(const char *pathName) 00377 { 00378 DIR dh; //Directory handler 00379 palStatus_t ret = PAL_SUCCESS; 00380 FRESULT status = FR_OK; 00381 char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder 00382 FILINFO currentEntry = { 0 }; //file Entry 00383 00384 status = f_opendir(&dh, pathName); 00385 if (status != FR_OK) 00386 { 00387 ret = pal_plat_errorTranslation(status); 00388 } 00389 00390 if (ret == PAL_SUCCESS) 00391 { 00392 while(true) 00393 { 00394 if (!pal_plat_findNextFile(&dh, ¤tEntry)) 00395 { 00396 ret = PAL_ERR_FS_ERROR_IN_SEARCHING; 00397 break; 00398 } 00399 pal_plat_addFileNameToPath(pathName, currentEntry.fname, buffer); 00400 if (currentEntry.fname[0] != '\0') 00401 { 00402 if (currentEntry.fattrib & AM_DIR) 00403 { 00404 ret = pal_fsRmFiles(buffer); 00405 if (ret != PAL_SUCCESS) 00406 { 00407 break; 00408 } 00409 ret = pal_fsRmDir(buffer); 00410 if (PAL_SUCCESS != ret) 00411 { 00412 break; 00413 } 00414 } 00415 else 00416 { 00417 status = f_unlink (buffer); 00418 if (status != FR_OK) 00419 { 00420 ret = pal_plat_errorTranslation(status); 00421 break; 00422 } 00423 } 00424 } 00425 else 00426 {//End of directory reached without errors break, close directory and exit 00427 break; 00428 } 00429 }//while() 00430 00431 status = f_closedir (&dh); //Close DIR handler 00432 if (status != FR_OK) 00433 { 00434 ret = pal_plat_errorTranslation(status); 00435 } 00436 } 00437 00438 return ret; 00439 } 00440 00441 00442 palStatus_t pal_plat_fsCpFolder(const char *pathNameSrc, char *pathNameDest) 00443 { 00444 DIR src_dh; //Directory for the source Directory handler 00445 palStatus_t ret = PAL_SUCCESS; 00446 FILINFO currentEntry = { 0 }; //file Entry 00447 FRESULT status = FR_OK; 00448 00449 00450 status = f_opendir(&src_dh, pathNameSrc); 00451 if (status != FR_OK) 00452 { 00453 ret = pal_plat_errorTranslation(status); 00454 } 00455 00456 00457 if (ret == PAL_SUCCESS) 00458 { 00459 while(true) 00460 { 00461 if (!pal_plat_findNextFile(&src_dh, ¤tEntry)) 00462 { 00463 ret = PAL_ERR_FS_ERROR_IN_SEARCHING; 00464 break; 00465 } 00466 if (currentEntry.fname[0] != 0) 00467 { 00468 if (currentEntry.fattrib & AM_DIR) // skip all folder as this is flat copy only 00469 { 00470 continue; 00471 } 00472 //copy the file to the destination 00473 ret = pal_plat_fsCpFile(pathNameSrc, pathNameDest, currentEntry.fname); 00474 if (ret != PAL_SUCCESS) 00475 { 00476 break; 00477 } 00478 } 00479 else 00480 {//End of directory reached without errors break and close directory and exit 00481 break; 00482 } 00483 }//while() 00484 f_closedir(&src_dh); 00485 } 00486 00487 return ret; 00488 } 00489 00490 00491 PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc, char *pathNameDest, char * fileName) 00492 { 00493 palStatus_t ret = PAL_SUCCESS; 00494 FIL src_fd, dst_fd; 00495 char * buffer = NULL; 00496 char buffer_name[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder 00497 size_t bytesCount = 0; 00498 FRESULT status = FR_OK; 00499 00500 //Add file name to path 00501 pal_plat_addFileNameToPath(pathNameSrc, fileName, buffer_name); 00502 status = f_open(&src_fd, buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READONLY]); 00503 if (status != FR_OK) 00504 { 00505 ret = pal_plat_errorTranslation(status); 00506 } 00507 else 00508 { 00509 //Add file name to path 00510 pal_plat_addFileNameToPath(pathNameDest, fileName, buffer_name); 00511 status = f_open(&dst_fd, buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READWRITETRUNC]); 00512 if (status != FR_OK) 00513 { 00514 ret = pal_plat_errorTranslation(status); 00515 } 00516 else 00517 { 00518 buffer = (char*)pal_plat_malloc (PAL_FS_COPY_BUFFER_SIZE); 00519 if (!buffer) 00520 { 00521 ret = PAL_ERR_RTOS_RESOURCE ; 00522 } 00523 } 00524 } 00525 00526 if (ret == PAL_SUCCESS) 00527 { 00528 while (1) 00529 { 00530 status = f_read(&src_fd, buffer, PAL_FS_COPY_BUFFER_SIZE, &bytesCount); 00531 00532 if (status != FR_OK) 00533 { 00534 break; 00535 } 00536 00537 //Check if end of file reached 00538 if (bytesCount == 0) 00539 { 00540 break; 00541 } 00542 00543 status = f_write(&dst_fd, buffer, bytesCount, &bytesCount); 00544 if (status != FR_OK) 00545 { 00546 break; 00547 } 00548 } 00549 if (status != FR_OK) 00550 { 00551 ret = pal_plat_errorTranslation(status); 00552 } 00553 } 00554 00555 00556 00557 f_close(&src_fd); 00558 f_close(&dst_fd); 00559 if (buffer) 00560 { 00561 pal_plat_free (buffer); 00562 } 00563 return ret; 00564 } 00565 00566 const char* pal_plat_fsGetDefaultRootFolder(pal_fsStorageID_t dataID) 00567 { 00568 const char* returnedRoot = NULL; 00569 if (PAL_FS_PARTITION_PRIMARY == dataID) 00570 { 00571 returnedRoot = PAL_FS_MOUNT_POINT_PRIMARY; 00572 } 00573 else if (PAL_FS_PARTITION_SECONDARY == dataID) 00574 { 00575 returnedRoot = PAL_FS_MOUNT_POINT_SECONDARY; 00576 } 00577 return returnedRoot; 00578 } 00579 00580 00581 PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, FILINFO *CurrentEntry) 00582 { 00583 bool ret = true; 00584 bool skip = false; 00585 bool foundFile = false; 00586 FRESULT status; 00587 00588 do 00589 { 00590 status = f_readdir(dh, CurrentEntry); 00591 if (status == FR_OK) 00592 { 00593 if ((CurrentEntry)->fname[0] == 0) 00594 {//End Of Directory 00595 ret = true; 00596 break; 00597 } 00598 00599 /* Skip the names "." and ".." as we don't want to remove them. also make sure that the current entry point to REGULER file*/ 00600 skip = (!strcmp((CurrentEntry)->fname, ".")) || (!strcmp((CurrentEntry)->fname, "..")); 00601 if (skip) 00602 { 00603 continue; 00604 } 00605 else 00606 { 00607 foundFile = true; 00608 } 00609 } 00610 else 00611 {//NOT!!! EOF other error 00612 ret = false; 00613 break; //Break from while 00614 } 00615 } 00616 while((!foundFile) && (ret)); //While file has been found or ret is set to false 00617 return ret; 00618 } 00619 00620 PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath) 00621 { 00622 palStatus_t ret = PAL_SUCCESS; 00623 00624 if ((strlen(pathName) >= PAL_MAX_FOLDER_DEPTH_CHAR) || (strlen(fileName) >= PAL_MAX_FULL_FILE_NAME)) 00625 { 00626 ret = PAL_ERR_FS_FILENAME_LENGTH; 00627 } 00628 else if (fullPath) 00629 { 00630 strcpy(fullPath, pathName); 00631 strcat(fullPath, "/"); 00632 strcat(fullPath, fileName); 00633 } 00634 else 00635 { 00636 ret = PAL_ERR_RTOS_RESOURCE ; 00637 } 00638 return ret; 00639 } 00640 00641 00642 PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode) 00643 { 00644 palStatus_t ret = PAL_SUCCESS; 00645 00646 switch(errorOpCode) 00647 { 00648 case 0: 00649 break; 00650 case FR_DENIED: 00651 case FR_WRITE_PROTECTED: 00652 case FR_LOCKED: 00653 ret = PAL_ERR_FS_ACCESS_DENIED; 00654 break; 00655 00656 case FR_NOT_READY : 00657 ret = PAL_ERR_FS_BUSY; 00658 break; 00659 00660 case FR_EXIST: 00661 ret = PAL_ERR_FS_NAME_ALREADY_EXIST; 00662 break; 00663 00664 case FR_INVALID_NAME: 00665 case FR_INVALID_OBJECT: 00666 case FR_INVALID_DRIVE: 00667 ret = PAL_ERR_FS_INVALID_ARGUMENT; 00668 break; 00669 00670 case FR_NO_FILE: 00671 ret = PAL_ERR_FS_NO_FILE; 00672 break; 00673 00674 case FR_NO_PATH: 00675 ret = PAL_ERR_FS_NO_PATH; 00676 break; 00677 00678 default: 00679 ret = PAL_ERR_FS_ERROR; 00680 break; 00681 } 00682 return ret; 00683 } 00684 00685 00686 size_t pal_plat_fsSizeCheck(const char *stringToChk) 00687 { 00688 size_t length = 0; 00689 length = strlen(stringToChk); 00690 return length; 00691 } 00692 00693 00694 00695 palStatus_t pal_plat_fsFormat(pal_fsStorageID_t dataID) 00696 { 00697 const char* partitionNames[] ={ 00698 PAL_FS_MOUNT_POINT_PRIMARY, 00699 PAL_FS_MOUNT_POINT_SECONDARY 00700 }; 00701 palStatus_t result = PAL_SUCCESS; 00702 const char* partName = partitionNames[dataID]; 00703 FRESULT res = f_mkfs(partName, 0, 0); 00704 if (FR_OK != res) 00705 { 00706 result = PAL_ERR_FS_ERROR; 00707 } 00708 return result; 00709 }
Generated on Tue Jul 12 2022 16:22:09 by 1.7.2