Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_plat_fileSystem.cpp Source File

pal_plat_fileSystem.cpp

00001 /*******************************************************************************
00002  * Copyright 2016, 2017 ARM Ltd.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *******************************************************************************/
00016 #include "mbed.h"
00017 
00018 #include <errno.h>
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <stdlib.h>
00022 
00023 #include "FileSystemLike.h"
00024 #include "FilePath.h"
00025 
00026 
00027 //PAL Includes
00028 #include "pal.h"
00029 #include "pal_plat_fileSystem.h"
00030 
00031 
00032 #ifndef EEXIST
00033 #define EEXIST 17
00034 #endif
00035 #ifndef EACCES
00036 #define EACCES 13
00037 #endif
00038 #ifndef EFAULT
00039 #define EFAULT 14
00040 #endif
00041 #ifndef EROFS
00042 #define EROFS 30
00043 #endif
00044 #ifndef EBUSY
00045 #define EBUSY 16
00046 #endif
00047 #ifndef ENAMETOOLONG
00048 #define ENAMETOOLONG 36
00049 #endif
00050 #ifndef EBADF
00051 #define EBADF 9
00052 #endif
00053 #ifndef EISDIR
00054 #define EISDIR 21
00055 #endif
00056 #ifndef ENOTEMPTY
00057 #define ENOTEMPTY 39
00058 #endif
00059 #ifndef ENOENT
00060 #define ENOENT 2
00061 #endif
00062 
00063 
00064 
00065 #define PAL_FS_COPY_BUFFER_SIZE 256                                                            //!< Size of the chunk to copy files
00066 PAL_PRIVATE const char *g_platOpenModeConvert[] = {"0", "r", "r+", "w+x", "w+"};                    //!< platform convert table for \b fopen() modes
00067 PAL_PRIVATE const int g_platSeekWhenceConvert[] = {0, SEEK_SET, SEEK_CUR, SEEK_END};                //!< platform convert table for \b fseek() relative position modes
00068 
00069 
00070 
00071 
00072 
00073 /*! \brief This function find the next file in a directory
00074  *
00075  * @param[in]    *dh - Directory handler to an open DIR
00076  * @param[out]    CurrentEntry - entry for the file found in Directory (pre allocated)
00077  *
00078  * \return true - upon successful operation.\n
00079  *
00080  */
00081 PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, struct dirent ** CurrentEntry);
00082 
00083 /*! \brief This function translate the platform errors opcode to pal error codes
00084  *
00085  * @param[in]    errorOpCode - platform opcode to be translated
00086  *
00087  * \return PAL_SUCCESS upon successful operation.\n
00088  */
00089 PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode);
00090 
00091 
00092 /*! \brief This function build the full path name by adding the filename to the working path given in pathName arg
00093  *
00094  * @param[in]    *pathName - pointer to the null-terminated string that specifies the directory name.
00095  * @param[in]   *fileName - pointer to the file name
00096  * @param[out]    *fullPath - pointer to the full path including the filename (pre allocated)
00097  *
00098  * \return PAL_SUCCESS upon successful operation.\n
00099  *         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t
00100  *
00101  */
00102 PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath);
00103 
00104 /*! \brief This function copy one file from source folder to destination folder
00105 *
00106 * @param[in]  pathNameSrc - Pointer to a null-terminated string that specifies the source dir.
00107 * @param[in]  pathNameDest - Pointer to a null-terminated string that specifies the destination dir
00108 * @param[in] fileName - pointer the the file name
00109 *
00110 * \return PAL_SUCCESS upon successful operation.\n
00111 *         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t
00112 *
00113 * \note File should not be open.\n
00114 *         If the Destination file exist then it shall be truncated
00115 *
00116 */
00117 PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc,  char *pathNameDest, char * fileName);
00118 
00119 palStatus_t pal_plat_fsMkdir(const char *pathName)
00120 {
00121     palStatus_t ret = PAL_SUCCESS;
00122     if(mkdir(pathName, 0600))
00123     {
00124         ret = pal_plat_errorTranslation(errno);
00125     }
00126     return ret;
00127 }
00128 
00129 
00130 palStatus_t pal_plat_fsRmdir(const char *pathName)
00131 {
00132     palStatus_t ret = PAL_SUCCESS;
00133 
00134     if (remove(pathName))
00135     {
00136         if((EINVAL == errno) || (EACCES == errno) || (ENOTEMPTY == errno)) // EINVAL LittleFS error code, EACCES FatFS error code
00137         {
00138             ret = PAL_ERR_FS_DIR_NOT_EMPTY;
00139         }
00140         else if(errno == ENOENT)
00141         {
00142             ret    = PAL_ERR_FS_NO_PATH;
00143         }
00144         else
00145         {
00146             ret = pal_plat_errorTranslation(errno);
00147         }
00148     }
00149     return ret;
00150 }
00151 
00152 
00153 palStatus_t pal_plat_fsFopen(const char *pathName, pal_fsFileMode_t mode, palFileDescriptor_t *fd)
00154 {
00155     palStatus_t ret = PAL_SUCCESS;
00156 
00157     if (mode == PAL_FS_FLAG_READWRITEEXCLUSIVE)
00158     {
00159         *fd = (palFileDescriptor_t)fopen(pathName, "r");
00160         if (*fd)
00161         {
00162             ret = PAL_ERR_FS_NAME_ALREADY_EXIST;
00163             fclose((FILE *)*fd);
00164         }
00165     }
00166 
00167     if(ret == PAL_SUCCESS)
00168     {
00169         *fd = (palFileDescriptor_t)fopen(pathName, g_platOpenModeConvert[mode]);
00170         if (!(*fd))
00171         {
00172             ret = pal_plat_errorTranslation(errno);
00173         }
00174     }
00175     return ret;
00176 }
00177 
00178 
00179 palStatus_t pal_plat_fsFclose(palFileDescriptor_t *fd)
00180 {
00181     palStatus_t ret = PAL_SUCCESS;
00182     if (fclose((FILE *)*fd))
00183     {
00184         ret = pal_plat_errorTranslation(errno);
00185     }
00186     return ret;
00187 }
00188 
00189 
00190 palStatus_t pal_plat_fsFread(palFileDescriptor_t *fd, void * buffer, size_t numOfBytes, size_t *numberOfBytesRead)
00191 {
00192     palStatus_t ret = PAL_SUCCESS;
00193     clearerr((FILE *)*fd);
00194     *numberOfBytesRead = fread(buffer, 1, numOfBytes, (FILE *)*fd);
00195     if (*numberOfBytesRead != numOfBytes)
00196     {
00197         if (ferror((FILE *)*fd))
00198         {
00199             ret = PAL_ERR_FS_ERROR;
00200         }
00201         clearerr((FILE *)*fd);
00202     }
00203     return ret;
00204 }
00205 
00206 
00207 palStatus_t pal_plat_fsFwrite(palFileDescriptor_t *fd, const void *buffer, size_t numOfBytes, size_t *numberOfBytesWritten)
00208 {
00209     palStatus_t ret = PAL_SUCCESS;
00210     errno = 0;
00211     *numberOfBytesWritten = fwrite(buffer, 1, numOfBytes, (FILE *)*fd);
00212     if (*numberOfBytesWritten != numOfBytes)
00213     {
00214         if(errno == EBADF)
00215         {
00216             ret = PAL_ERR_FS_ACCESS_DENIED;
00217         }
00218         else
00219         {
00220             ret = pal_plat_errorTranslation(errno);
00221         }
00222     }
00223     return ret;
00224 }
00225 
00226 
00227 palStatus_t pal_plat_fsFseek(palFileDescriptor_t *fd, int32_t offset, pal_fsOffset_t whence)
00228 {
00229     palStatus_t ret = PAL_SUCCESS;
00230     if (fseek((FILE *)*fd, offset, g_platSeekWhenceConvert[whence]))
00231     {
00232         ret = pal_plat_errorTranslation(errno);
00233     }
00234     return ret;
00235 }
00236 
00237 
00238 palStatus_t pal_plat_fsFtell(palFileDescriptor_t *fd, int32_t * pos)
00239 {
00240     palStatus_t ret = PAL_SUCCESS;
00241     long retPos = 0;
00242     *pos = 0;
00243     retPos = ftell((FILE *)*fd);
00244     if (retPos < 0)
00245     {
00246         ret = pal_plat_errorTranslation(errno);
00247     }
00248     else
00249     {
00250         *pos = retPos;
00251     }
00252     return ret;
00253 }
00254 
00255 
00256 palStatus_t pal_plat_fsUnlink(const char *pathName)
00257 {
00258     palStatus_t ret = PAL_SUCCESS;
00259     if (remove(pathName))
00260     {
00261         ret = pal_plat_errorTranslation(errno);
00262     }
00263     return ret;
00264 }
00265 
00266 
00267 palStatus_t pal_plat_fsRmFiles(const char *pathName)
00268 {
00269     DIR *dh = NULL; //Directory handler
00270     palStatus_t ret = PAL_SUCCESS;
00271     char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder
00272     struct dirent * currentEntry = NULL; //file Entry
00273 
00274     dh = opendir(pathName);
00275     if (dh)
00276     {
00277         while(true)
00278         {
00279             if (!pal_plat_findNextFile(dh, &currentEntry))
00280             {
00281                 ret = PAL_ERR_FS_ERROR_IN_SEARCHING;
00282                 break;
00283             }
00284 
00285             if (currentEntry)
00286             {
00287                 pal_plat_addFileNameToPath(pathName, currentEntry->d_name, buffer);
00288                 if (currentEntry->d_type == DT_DIR)
00289                 {
00290                     pal_plat_fsRmFiles(buffer);
00291                 }
00292                 if (remove(buffer))
00293                 {
00294                     ret = pal_plat_errorTranslation(errno);
00295                     break;
00296                 }
00297             }
00298             else
00299             {//End of directory reached  without errors break, close directory and exit
00300                 break;
00301             }
00302         }//while()
00303     }
00304     else//if (dh)
00305     {
00306         ret = PAL_ERR_FS_NO_PATH;
00307     }
00308 
00309     if (dh)
00310     {
00311         closedir(dh); //Close DIR handler
00312     }
00313     return ret;
00314 }
00315 
00316 
00317 palStatus_t pal_plat_fsCpFolder(const char *pathNameSrc,  char *pathNameDest)
00318 {
00319     DIR *src_dh = NULL; //Directory for the source Directory handler
00320     palStatus_t ret = PAL_SUCCESS;
00321     struct dirent * currentEntry = NULL; //file Entry
00322 
00323     src_dh = opendir(pathNameSrc);
00324     if (src_dh == NULL)
00325     {
00326         ret = PAL_ERR_FS_NO_PATH;
00327     }
00328 
00329     if (ret == PAL_SUCCESS)
00330     {
00331         while(true)
00332         {
00333             if (!pal_plat_findNextFile(src_dh, &currentEntry))
00334             {
00335                 ret = PAL_ERR_FS_ERROR_IN_SEARCHING;
00336                 break;
00337             }
00338 
00339             if (currentEntry)
00340             {
00341                 if (currentEntry->d_type == DT_DIR)
00342                 {
00343                     continue;
00344                 }
00345                 //copy the file to the destination
00346                 ret = pal_plat_fsCpFile(pathNameSrc, pathNameDest, currentEntry->d_name);
00347                 if (ret != PAL_SUCCESS)
00348                 {
00349                     break;
00350                 }
00351             }
00352             else
00353             {//End of directory reached  without errors break and close directory and exit
00354                 break;
00355             }
00356         }//while()
00357     }
00358 
00359     if (src_dh)
00360     {
00361         closedir(src_dh);
00362     }
00363     return ret;
00364 }
00365 
00366 
00367 PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc,  char *pathNameDest, char * fileName)
00368 {
00369     palStatus_t ret = PAL_SUCCESS;
00370     palFileDescriptor_t src_fd = 0;
00371     palFileDescriptor_t dst_fd = 0;
00372     char buffer_name[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder
00373     char * buffer = NULL;
00374     size_t bytesCount = 0;
00375 
00376     //Add file name to path
00377     pal_plat_addFileNameToPath(pathNameSrc, fileName, buffer_name);
00378     src_fd = (palFileDescriptor_t)fopen(buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READONLY]);
00379     if (src_fd == 0)
00380     {
00381         ret = pal_plat_errorTranslation(errno);
00382     }
00383     else
00384     {
00385         //Add file name to path
00386         pal_plat_addFileNameToPath(pathNameDest, fileName, buffer_name);
00387         dst_fd = (palFileDescriptor_t)fopen(buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READWRITETRUNC]);
00388         if (dst_fd == 0)
00389         {
00390             ret = pal_plat_errorTranslation(errno);
00391         }
00392         else
00393         {
00394             buffer = (char*)malloc(PAL_FS_COPY_BUFFER_SIZE);
00395             if (!buffer)
00396             {
00397                 ret = PAL_ERR_RTOS_RESOURCE ;
00398             }
00399         }
00400     }
00401 
00402     if (ret == PAL_SUCCESS)
00403     {
00404         while (1)
00405         {
00406             ret = pal_fsFread(&src_fd, buffer, PAL_FS_COPY_BUFFER_SIZE, &bytesCount);
00407             if (ret != PAL_SUCCESS)
00408             {
00409                 break;
00410             }
00411 
00412             //Check if end of file reached
00413             if (bytesCount == 0)
00414             {
00415                 break;
00416             }
00417 
00418             ret = pal_fsFwrite(&dst_fd, buffer, bytesCount, &bytesCount);
00419             if (ret != PAL_SUCCESS)
00420             {
00421                 break;
00422             }
00423         }
00424     }
00425 
00426     if (src_fd != 0)
00427     {
00428         pal_fsFclose(&src_fd);
00429     }
00430     if (dst_fd != 0)
00431     {
00432         pal_fsFclose(&dst_fd);
00433     }
00434     if (buffer)
00435     {
00436         free(buffer);
00437     }
00438     return ret;
00439 }
00440 
00441 
00442 const char* pal_plat_fsGetDefaultRootFolder(pal_fsStorageID_t dataID)
00443 {
00444     const char* returnedRoot = NULL;
00445     if (PAL_FS_PARTITION_PRIMARY == dataID)
00446     {
00447         returnedRoot = PAL_FS_MOUNT_POINT_PRIMARY;
00448     }
00449     else if (PAL_FS_PARTITION_SECONDARY == dataID)
00450     {
00451         returnedRoot = PAL_FS_MOUNT_POINT_SECONDARY;
00452     }
00453 
00454     return returnedRoot;
00455 }
00456 
00457 
00458 PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, struct dirent ** CurrentEntry)
00459 {
00460     bool ret = true;
00461     bool skip = false;
00462     bool foundFile = false;
00463 
00464     do
00465     {
00466         errno = 0;
00467         *CurrentEntry = readdir(dh);
00468         if (*CurrentEntry)
00469         {
00470             /* Skip the names "." and ".." as we don't want to remove them. also make sure that the current entry point to REGULER file*/
00471             skip = (!strcmp((*CurrentEntry)->d_name, ".")) || (!strcmp((*CurrentEntry)->d_name, ".."));
00472             if (skip)
00473             {
00474                 continue;
00475             }
00476             else
00477             {
00478                 foundFile = true;
00479             }
00480         }
00481         else
00482         {//Check if EOF reached
00483             if (errno)
00484             {//NOT!!! EOF  other error
00485                 ret = false;
00486             }
00487             break; //Break from while
00488         }
00489     }
00490     while((!foundFile) && (ret)); //While file has been found or ret is set to false
00491 
00492     return ret;
00493 }
00494 
00495 PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath)
00496 {
00497     palStatus_t ret = PAL_SUCCESS;
00498 
00499     if ((strlen(pathName) >= PAL_MAX_FOLDER_DEPTH_CHAR)  || (strlen(fileName) >= PAL_MAX_FULL_FILE_NAME))
00500     {
00501         ret = PAL_ERR_FS_FILENAME_LENGTH;
00502     }
00503     else if (fullPath)
00504     {
00505         strcpy(fullPath, pathName);
00506         strcat(fullPath, "/");
00507         strcat(fullPath, fileName);
00508     }
00509     else
00510     {
00511         ret = PAL_ERR_RTOS_RESOURCE ;
00512     }
00513     return ret;
00514 }
00515 
00516 
00517 
00518 
00519 PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode)
00520 {
00521     palStatus_t ret = PAL_SUCCESS;
00522 
00523     switch(errorOpCode)
00524     {
00525     case 0:
00526         break;
00527     case EACCES:
00528     case EFAULT:
00529     case EROFS:
00530         ret = PAL_ERR_FS_ACCESS_DENIED;
00531         break;
00532 
00533     case EBUSY :
00534         ret = PAL_ERR_FS_BUSY;
00535         break;
00536 
00537     case EEXIST:
00538         ret = PAL_ERR_FS_NAME_ALREADY_EXIST;
00539         break;
00540 
00541     case ENAMETOOLONG:
00542         ret = PAL_ERR_FS_FILENAME_LENGTH;
00543         break;
00544 
00545     case EBADF:
00546         ret = PAL_ERR_FS_BAD_FD;
00547         break;
00548 
00549     case EINVAL:
00550         ret = PAL_ERR_FS_INVALID_ARGUMENT;
00551         break;
00552 
00553     case EISDIR:
00554         ret = PAL_ERR_FS_FILE_IS_DIR;
00555         break;
00556 
00557     case ENOTEMPTY:
00558         ret = PAL_ERR_FS_DIR_NOT_EMPTY;
00559         break;
00560 
00561     case ENOENT:
00562         ret = PAL_ERR_FS_NO_FILE;
00563         break;
00564 
00565     default:
00566         ret = PAL_ERR_FS_ERROR;
00567         break;
00568     }
00569     return ret;
00570 }
00571 
00572 
00573 size_t pal_plat_fsSizeCheck(const char *stringToChk)
00574 {
00575     size_t length = 0;
00576     length = strlen(stringToChk);
00577     return length;
00578 }
00579 
00580 
00581 
00582 
00583 
00584 palStatus_t pal_plat_fsFormat(pal_fsStorageID_t dataID)
00585 {
00586     const char* partitionTranslationArray[] =
00587                                   {
00588                                           PAL_FS_MOUNT_POINT_PRIMARY,
00589                                           PAL_FS_MOUNT_POINT_SECONDARY
00590                                   };//  "/sd\0"
00591     FileSystem *myFs;
00592     int err = 0;
00593     palStatus_t status = PAL_SUCCESS;
00594     FilePath myPath(partitionTranslationArray[dataID]);
00595     myFs = (FileSystem*)myPath.fileSystem();
00596     if (NULL != myFs) 
00597     {
00598         err = myFs->reformat(NULL);
00599         if (err < 0)
00600         {
00601             status = PAL_ERR_FS_ERROR;
00602         }
00603     }
00604     else //This should not happen
00605     {
00606         status = PAL_ERR_FS_ERROR;
00607     }
00608     return status;
00609 }
00610