Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

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