in FreeRTOS-Plus/Source/Reliance-Edge/core/driver/inodedata.c [218:347]
REDSTATUS RedInodeDataWrite(
CINODE *pInode,
uint64_t ullStart,
uint32_t *pulLen,
const void *pBuffer)
{
REDSTATUS ret = 0;
if(!CINODE_IS_DIRTY(pInode) || (pulLen == NULL) || (pBuffer == NULL))
{
ret = -RED_EINVAL;
}
else if((ullStart > INODE_SIZE_MAX) || ((ullStart == INODE_SIZE_MAX) && (*pulLen > 0U)))
{
ret = -RED_EFBIG;
}
else if(*pulLen == 0U)
{
/* Do nothing, just return success.
*/
}
else
{
const uint8_t *pbBuffer = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pBuffer);
uint32_t ulWriteIndex = 0U;
uint32_t ulLen = *pulLen;
uint32_t ulRemaining;
if((INODE_SIZE_MAX - ullStart) < ulLen)
{
ulLen = (uint32_t)(INODE_SIZE_MAX - ullStart);
}
ulRemaining = ulLen;
/* If the write is beyond the current end of the file, and the current
end of the file is not block-aligned, then there may be some data
that needs to be zeroed in the last block.
*/
if(ullStart > pInode->pInodeBuf->ullSize)
{
ret = ExpandPrepare(pInode);
}
/* Partial block at start.
*/
if((ret == 0) && (((ullStart & (REDCONF_BLOCK_SIZE - 1U)) != 0U) || (ulRemaining < REDCONF_BLOCK_SIZE)))
{
uint32_t ulBytesInFirstBlock = REDCONF_BLOCK_SIZE - (uint32_t)(ullStart & (REDCONF_BLOCK_SIZE - 1U));
uint32_t ulThisWrite = REDMIN(ulRemaining, ulBytesInFirstBlock);
ret = WriteUnaligned(pInode, ullStart, ulThisWrite, pbBuffer);
if(ret == 0)
{
ulWriteIndex += ulThisWrite;
ulRemaining -= ulThisWrite;
}
}
/* Whole blocks.
*/
if((ret == 0) && (ulRemaining >= REDCONF_BLOCK_SIZE))
{
uint32_t ulBlockOffset = (uint32_t)((ullStart + ulWriteIndex) >> BLOCK_SIZE_P2);
uint32_t ulBlockCount = ulRemaining >> BLOCK_SIZE_P2;
uint32_t ulBlocksWritten = ulBlockCount;
REDASSERT(((ullStart + ulWriteIndex) & (REDCONF_BLOCK_SIZE - 1U)) == 0U);
ret = WriteAligned(pInode, ulBlockOffset, &ulBlocksWritten, &pbBuffer[ulWriteIndex]);
if((ret == -RED_ENOSPC) && (ulWriteIndex > 0U))
{
ulBlocksWritten = 0U;
ret = 0;
}
if(ret == 0)
{
ulWriteIndex += ulBlocksWritten << BLOCK_SIZE_P2;
ulRemaining -= ulBlocksWritten << BLOCK_SIZE_P2;
if(ulBlocksWritten < ulBlockCount)
{
ulRemaining = 0U;
}
}
}
/* Partial block at end.
*/
if((ret == 0) && (ulRemaining > 0U))
{
REDASSERT(ulRemaining < REDCONF_BLOCK_SIZE);
REDASSERT(((ullStart + ulWriteIndex) & (REDCONF_BLOCK_SIZE - 1U)) == 0U);
REDASSERT(ulWriteIndex > 0U);
ret = WriteUnaligned(pInode, ullStart + ulWriteIndex, ulRemaining, &pbBuffer[ulWriteIndex]);
if(ret == -RED_ENOSPC)
{
ret = 0;
}
else if(ret == 0)
{
ulWriteIndex += ulRemaining;
REDASSERT(ulWriteIndex == ulLen);
}
else
{
/* Unexpected error, return it.
*/
}
}
if(ret == 0)
{
*pulLen = ulWriteIndex;
if((ullStart + ulWriteIndex) > pInode->pInodeBuf->ullSize)
{
pInode->pInodeBuf->ullSize = ullStart + ulWriteIndex;
}
}
}
return ret;
}