in FreeRTOS-Plus/Source/Reliance-Edge/posix/posix.c [2372:2556]
static REDSTATUS FildesOpen(
const char *pszPath,
uint32_t ulOpenMode,
FTYPE type,
int32_t *piFildes)
{
uint8_t bVolNum;
const char *pszLocalPath;
REDSTATUS ret;
ret = RedPathSplit(pszPath, &bVolNum, &pszLocalPath);
if(ret == 0)
{
if(piFildes == NULL)
{
ret = -RED_EINVAL;
}
#if REDCONF_READ_ONLY == 0
else if(gaRedVolume[bVolNum].fReadOnly && (ulOpenMode != RED_O_RDONLY))
{
ret = -RED_EROFS;
}
#endif
else
{
uint16_t uHandleIdx;
REDHANDLE *pHandle = NULL;
/* Search for an unused handle.
*/
for(uHandleIdx = 0U; uHandleIdx < REDCONF_HANDLE_COUNT; uHandleIdx++)
{
if(gaHandle[uHandleIdx].ulInode == INODE_INVALID)
{
pHandle = &gaHandle[uHandleIdx];
break;
}
}
/* Error if all the handles are in use.
*/
if(pHandle == NULL)
{
ret = -RED_EMFILE;
}
else
{
bool fCreated = false;
uint16_t uMode = 0U;
uint32_t ulInode = 0U; /* Init'd to quiet warnings. */
#if REDCONF_VOLUME_COUNT > 1U
ret = RedCoreVolSetCurrent(bVolNum);
if(ret == 0)
#endif
{
#if REDCONF_READ_ONLY == 0
if((ulOpenMode & RED_O_CREAT) != 0U)
{
uint32_t ulPInode;
const char *pszName;
ret = RedPathToName(pszLocalPath, &ulPInode, &pszName);
if(ret == 0)
{
ret = RedCoreCreate(ulPInode, pszName, false, &ulInode);
if(ret == 0)
{
fCreated = true;
}
else if((ret == -RED_EEXIST) && ((ulOpenMode & RED_O_EXCL) == 0U))
{
/* If the path already exists and that's OK,
lookup its inode number.
*/
ret = RedCoreLookup(ulPInode, pszName, &ulInode);
}
else
{
/* No action, just propagate the error.
*/
}
}
}
else
#endif
{
ret = RedPathLookup(pszLocalPath, &ulInode);
}
}
/* If we created the inode, none of the below stuff is
necessary. This is important from an error handling
perspective -- we do not need code to delete the created
inode on error.
*/
if(!fCreated)
{
if(ret == 0)
{
REDSTAT s;
ret = RedCoreStat(ulInode, &s);
if(ret == 0)
{
uMode = s.st_mode;
}
}
/* Error if the inode is not of the expected type.
*/
if(ret == 0)
{
ret = ModeTypeCheck(uMode, type);
}
/* Directories must always be opened with O_RDONLY.
*/
if((ret == 0) && RED_S_ISDIR(uMode) && ((ulOpenMode & RED_O_RDONLY) == 0U))
{
ret = -RED_EISDIR;
}
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_FTRUNCATE == 1)
if((ret == 0) && ((ulOpenMode & RED_O_TRUNC) != 0U))
{
ret = RedCoreFileTruncate(ulInode, UINT64_SUFFIX(0));
}
#endif
}
if(ret == 0)
{
int32_t iFildes;
RedMemSet(pHandle, 0U, sizeof(*pHandle));
/* Populate this handle, marking it as in use.
*/
pHandle->ulInode = ulInode;
pHandle->bVolNum = bVolNum;
if(RED_S_ISDIR(uMode))
{
pHandle->bFlags |= HFLAG_DIRECTORY;
}
if(((ulOpenMode & RED_O_RDONLY) != 0U) || ((ulOpenMode & RED_O_RDWR) != 0U))
{
pHandle->bFlags |= HFLAG_READABLE;
}
#if REDCONF_READ_ONLY == 0
if(((ulOpenMode & RED_O_WRONLY) != 0U) || ((ulOpenMode & RED_O_RDWR) != 0U))
{
pHandle->bFlags |= HFLAG_WRITEABLE;
}
if((ulOpenMode & RED_O_APPEND) != 0U)
{
pHandle->bFlags |= HFLAG_APPENDING;
}
#endif
iFildes = FildesPack(uHandleIdx, bVolNum);
if(iFildes == -1)
{
/* It should be impossible to get here, unless there
is memory corruption.
*/
REDERROR();
ret = -RED_EFUBAR;
}
else
{
*piFildes = iFildes;
}
}
}
}
}
return ret;
}