in FreeRTOS-Plus/Source/Reliance-Edge/core/driver/dir.c [305:454]
REDSTATUS RedDirEntryLookup(
CINODE *pPInode,
const char *pszName,
uint32_t *pulEntryIdx,
uint32_t *pulInode)
{
REDSTATUS ret = 0;
if(!CINODE_IS_MOUNTED(pPInode) || (pszName == NULL))
{
ret = -RED_EINVAL;
}
else if(!pPInode->fDirectory)
{
ret = -RED_ENOTDIR;
}
else
{
uint32_t ulNameLen = RedNameLen(pszName);
if(ulNameLen == 0U)
{
ret = -RED_EINVAL;
}
else if(ulNameLen > REDCONF_NAME_MAX)
{
ret = -RED_ENAMETOOLONG;
}
else
{
uint32_t ulIdx = 0U;
uint32_t ulDirentCount = DirOffsetToEntryIndex(pPInode->pInodeBuf->ullSize);
uint32_t ulFreeIdx = DIR_INDEX_INVALID; /* Index of first free dirent. */
/* Loop over the directory blocks, searching each block for a
dirent that matches the given name.
*/
while((ret == 0) && (ulIdx < ulDirentCount))
{
ret = RedInodeDataSeekAndRead(pPInode, ulIdx / DIRENTS_PER_BLOCK);
if(ret == 0)
{
const DIRENT *pDirents = CAST_CONST_DIRENT_PTR(pPInode->pbData);
uint32_t ulBlockLastIdx = REDMIN(DIRENTS_PER_BLOCK, ulDirentCount - ulIdx);
uint32_t ulBlockIdx;
for(ulBlockIdx = 0U; ulBlockIdx < ulBlockLastIdx; ulBlockIdx++)
{
const DIRENT *pDirent = &pDirents[ulBlockIdx];
if(pDirent->ulInode != INODE_INVALID)
{
/* The name in the dirent will not be null
terminated if it is of the maximum length, so
use a bounded string compare and then make sure
there is nothing more to the name.
*/
if( (RedStrNCmp(pDirent->acName, pszName, ulNameLen) == 0)
&& ((ulNameLen == REDCONF_NAME_MAX) || (pDirent->acName[ulNameLen] == '\0')))
{
/* Found a matching dirent, stop and return its
information.
*/
if(pulInode != NULL)
{
*pulInode = pDirent->ulInode;
#ifdef REDCONF_ENDIAN_SWAP
*pulInode = RedRev32(*pulInode);
#endif
}
ulIdx += ulBlockIdx;
break;
}
}
else if(ulFreeIdx == DIR_INDEX_INVALID)
{
ulFreeIdx = ulIdx + ulBlockIdx;
}
else
{
/* The directory entry is free, but we already found a free one, so there's
nothing to do here.
*/
}
}
if(ulBlockIdx < ulBlockLastIdx)
{
/* If we broke out of the for loop, we found a matching
dirent and can stop the search.
*/
break;
}
ulIdx += ulBlockLastIdx;
}
else if(ret == -RED_ENODATA)
{
if(ulFreeIdx == DIR_INDEX_INVALID)
{
ulFreeIdx = ulIdx;
}
ret = 0;
ulIdx += DIRENTS_PER_BLOCK;
}
else
{
/* Unexpected error, let the loop terminate, no action
here.
*/
}
}
if(ret == 0)
{
/* If we made it all the way to the end of the directory
without stopping, then the given name does not exist in the
directory.
*/
if(ulIdx == ulDirentCount)
{
/* If the directory had no sparse dirents, then the first
free dirent is beyond the end of the directory. If the
directory is already the maximum size, then there is no
free dirent.
*/
if((ulFreeIdx == DIR_INDEX_INVALID) && (ulDirentCount < DIRENTS_MAX))
{
ulFreeIdx = ulDirentCount;
}
ulIdx = ulFreeIdx;
ret = -RED_ENOENT;
}
if(pulEntryIdx != NULL)
{
*pulEntryIdx = ulIdx;
}
}
}
}
return ret;
}