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.c Source File

pal_plat_fileSystem.c

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