REDSTATUS RedInodeDataWrite()

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;
}