Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_plat_fileSystem.c Source File

pal_plat_fileSystem.c

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