//***************************************************************************** // //! Maps a path string containing mount point names to a path suitable for //! use in calls to the FatFs APIs. //! //! \param pcPath points to a string containing a path in the namespace //! defined by the mount information passed to fs_init(). //! \param pcMapped points to a buffer into which the mapped path string will //! be written. //! \param iLen is the size, in bytes, of the buffer pointed to by pcMapped. //! //! This function may be used by applications which want to make use of FatFs //! functions which are not directly mapped by the fswrapper layer. A path //! in the namespace defined by the mount points passed to function fs_init() //! is translated to an equivalent path in the FatFs namespace and this may //! then be used in a direct call to functions such as f_opendir() or //! f_getfree(). //! //! \return Returns \b true on success or \b false if fs_init() has not //! been called, if the path provided maps to an internal file system image //! rather than a FatFs logical drive or if the buffer pointed to by //! \e pcMapped is too small to fit the output string. // //***************************************************************************** bool fs_map_path(const char *pcPath, char *pcMapped, int iLen) { char *pcFSFilename; uint32_t ui32MountIndex; int iCount; // // If no mount points have been defined, return an error. // if(!g_psMountPoints) { return(false); } // // Find which mount point we need to use to satisfy this file open request. // ui32MountIndex = fs_find_mount_index(pcPath, &pcFSFilename); // // If we got a bad mount index or the index returned represents a mount // point that is not in the FAT file system, return an error. // if((ui32MountIndex == BAD_MOUNT_INDEX) || (g_psMountPoints[ui32MountIndex].pui8FSImage)) { // // We can't map the mount index so return an error. // return(false); } // // Now we can generate the FatFs namespace path string. // iCount = usnprintf(pcMapped, iLen, "%d:%s", g_psMountPoints[ui32MountIndex].ui32DriveNum, pcFSFilename); // // Tell the user how we got on. The count returned by usnprintf is the // number of characters that should have been written, excluding the // terminating NULL so we use this to check for overflow of the output // buffer. // return((iLen >= (iCount + 1)) ? true : false); }
//***************************************************************************** // //! Opens a file. //! //! \param pcName points to a NULL terminated string containing the path and //! file name to open. //! //! This function opens a file and returns a handle allowing it to be read. //! //! \return Returns a valid file handle on success or NULL on failure. // //***************************************************************************** struct fs_file * fs_open(char *pcName) { const struct fsdata_file *ptTree; const struct fsdata_file *ptEnd; struct fs_file *ptFile = NULL; fs_wrapper_data *pWrapper; FRESULT fresult = FR_OK; tBoolean bPosInd = false; char *pcFSFilename; char *pcFilename; unsigned long ulLength; // // Allocate memory for the file system structure. // ptFile = mem_malloc(sizeof(struct fs_file)); if(NULL == ptFile) { return(NULL); } // // Allocate memory for our internal control structure. // ptFile->pextension = mem_malloc(sizeof(fs_wrapper_data)); pWrapper = (fs_wrapper_data *)ptFile->pextension; if(NULL == pWrapper) { return(NULL); } // // Find which mount point we need to use to satisfy this file open request. // pWrapper->ulMountIndex = fs_find_mount_index(pcName, &pcFSFilename); if(pWrapper->ulMountIndex == BAD_MOUNT_INDEX) { // // We can't map the mount index so return an error. // mem_free(pWrapper); mem_free(ptFile); return(NULL); } // // Enable access to the physical medium if we have been provided with // a callback for this. // if(g_psMountPoints[pWrapper->ulMountIndex].pfnEnable) { g_psMountPoints[pWrapper->ulMountIndex].pfnEnable( pWrapper->ulMountIndex); } // // Are we opening a file on an internal file system image? // if(g_psMountPoints[pWrapper->ulMountIndex].pcFSImage) { // // Initialize the file system tree pointer to the root of the linked // list for this mount point's file system image. // ptTree = (const struct fsdata_file *) g_psMountPoints[pWrapper->ulMountIndex].pcFSImage; // // Which type of file system are we dealing with? // if(ptTree->next == FILE_SYSTEM_MARKER) { // // If we found the marker, this is a position independent file // system image. Remember this and fix up the pointer to the // first descriptor by skipping over the 4 byte marker and the // 4 byte image size entry. We also keep track of where the file // system image ends since this allows us to do a bit more error // checking later. // bPosInd = true; ulLength = *(unsigned long *)((unsigned char *)ptTree + 4); ptTree = (struct fsdata_file *)((char *)ptTree + 8); ptEnd = (struct fsdata_file *)((char *)ptTree + ulLength); } // // Begin processing the linked list, looking for the requested file // name. // while(NULL != ptTree) { // // Compare the requested file "name" to the file name in the // current node. // if(strncmp(pcFSFilename, FS_POINTER(ptTree, ptTree->name, bPosInd), ptTree->len) == 0) { // // Fill in the data pointer and length values from the // linked list node. // ptFile->data = FS_POINTER(ptTree, ptTree->data, bPosInd); ptFile->len = ptTree->len; // // For now, we setup the read index to the end of the file, // indicating that all data has been read. This indicates that // all the data is currently available in a contiguous block // of memory (which is always the case with an internal file // system image). // ptFile->index = ptTree->len; // // We are not using a FAT file system file and don't need to // remap the filename so set these pointers to NULL. // pWrapper->pFATFile = NULL; // // Exit the loop and return the file system pointer. // break; } // // If we get here, we did not find the file at this node of the // linked list. Get the next element in the list. We can't just // assign ptTree from ptTree->next since this will give us the // wrong pointer for a position independent image (where the values // in the structure are offsets from the start of the file // descriptor, not absolute pointers) but we do know that a 0 in // the "next" field does indicate that this is the last file so we // can use that info to force the loop to exit at the end. // if(ptTree->next == 0) { ptTree = NULL; } else { ptTree = (struct fsdata_file *)FS_POINTER(ptTree, ptTree->next, bPosInd); // // If this is a position independent file system image, we can // also check that the new node is within the image. If it // isn't, the image is corrupted to stop the search. // if(bPosInd && (ptTree >= ptEnd)) { ptTree = NULL; } } } // // If we didn't find the file, ptTee will be NULL. Make sure we // return a NULL pointer if this happens. // if(NULL == ptTree) { mem_free(ptFile->pextension); mem_free(ptFile); ptFile = NULL; } } else { // // This file is on the FAT file system. // // // Allocate memory for the Fat File system handle. // pWrapper->pFATFile = mem_malloc(sizeof(FIL)); if(NULL == pWrapper->pFATFile) { mem_free(ptFile->pextension); mem_free(ptFile); ptFile = NULL; } else { // // Reformat the filename to start with the FAT logical drive number. // pcFilename = mem_malloc(strlen(pcFSFilename) + 16); if(!pcFilename) { // // Can't allocate temporary storage for the reformatted // filename! // mem_free(pWrapper->pFATFile); mem_free(ptFile->pextension); mem_free(ptFile); ptFile = NULL; } else { usprintf(pcFilename, "%d:%s", g_psMountPoints[pWrapper->ulMountIndex].ulDriveNum, pcFSFilename); // // Attempt to open the file on the Fat File System. // fresult = f_open(pWrapper->pFATFile, pcFilename, FA_READ); // // Free the filename storage // mem_free(pcFilename); // // Did we open the file correctly? // if(FR_OK == fresult) { // // Yes - fill in the file structure to indicate that a // FAT file is in use. // ptFile->data = NULL; ptFile->len = NULL; ptFile->index = NULL; } else { // // If we get here, we failed to find the file on the FAT // file system so free up the FAT handle/object. // mem_free(pWrapper->pFATFile); mem_free(pWrapper); mem_free(ptFile); ptFile = NULL; } } } } // // Disable access to the physical medium if we have been provided with // a callback for this. // if(g_psMountPoints[pWrapper->ulMountIndex].pfnDisable) { g_psMountPoints[pWrapper->ulMountIndex].pfnDisable( pWrapper->ulMountIndex); } return(ptFile); }