in FreeRTOS-Plus/Source/Reliance-Edge/core/driver/inodedata.c [420:518]
static REDSTATUS Shrink(
CINODE *pInode,
uint64_t ullSize)
{
REDSTATUS ret = 0;
/* pInode->fDirty is checked explicitly here, instead of using the
CINODE_IS_DIRTY() macro, to avoid a duplicate mount check.
*/
if(!CINODE_IS_MOUNTED(pInode) || ((ullSize > 0U) && !pInode->fDirty))
{
REDERROR();
ret = -RED_EINVAL;
}
else
{
uint32_t ulTruncBlock = (uint32_t)((ullSize + REDCONF_BLOCK_SIZE - 1U) >> BLOCK_SIZE_P2);
RedInodePutData(pInode);
#if REDCONF_DIRECT_POINTERS > 0U
while(ulTruncBlock < REDCONF_DIRECT_POINTERS)
{
ret = TruncDataBlock(pInode, &pInode->pInodeBuf->aulEntries[ulTruncBlock], true);
if(ret != 0)
{
break;
}
ulTruncBlock++;
}
#endif
#if REDCONF_INDIRECT_POINTERS > 0U
while((ret == 0) && (ulTruncBlock < (REDCONF_DIRECT_POINTERS + INODE_INDIR_BLOCKS)))
{
ret = RedInodeDataSeek(pInode, ulTruncBlock);
if((ret == 0) || (ret == -RED_ENODATA))
{
bool fFreed;
ret = TruncIndir(pInode, &fFreed);
if(ret == 0)
{
if(fFreed)
{
pInode->pInodeBuf->aulEntries[pInode->uInodeEntry] = BLOCK_SPARSE;
}
/* The next seek will go to the beginning of the next
indirect.
*/
ulTruncBlock += (INDIR_ENTRIES - pInode->uIndirEntry);
}
}
}
#endif
#if DINDIR_POINTERS > 0U
while((ret == 0) && (ulTruncBlock < INODE_DATA_BLOCKS))
{
ret = RedInodeDataSeek(pInode, ulTruncBlock);
if((ret == 0) || (ret == -RED_ENODATA))
{
bool fFreed;
/* TruncDindir() invokes seek as it goes along, which will
update the entry values (possibly all three of these);
make a copy so we can compute things correctly after.
*/
uint16_t uOrigInodeEntry = pInode->uInodeEntry;
uint16_t uOrigDindirEntry = pInode->uDindirEntry;
uint16_t uOrigIndirEntry = pInode->uIndirEntry;
ret = TruncDindir(pInode, &fFreed);
if(ret == 0)
{
if(fFreed)
{
pInode->pInodeBuf->aulEntries[uOrigInodeEntry] = BLOCK_SPARSE;
}
/* The next seek will go to the beginning of the next
double indirect.
*/
ulTruncBlock += (DINDIR_DATA_BLOCKS - (uOrigDindirEntry * INDIR_ENTRIES)) - uOrigIndirEntry;
}
}
}
#endif
}
return ret;
}