Esempio n. 1
0
/**
 *	@public
 *	@brief	Equivalent to fclose()
 *
 *	@param	pFile		FF_FILE object that was created by FF_Open().
 *
 *	@return 0 on sucess.
 *	@return -1 if a null pointer was provided.
 *
 **/
FF_ERROR FF_Close(FF_FILE *pFile) {

	FF_FILE		*pFileChain;
	FF_DIRENT	OriginalEntry;
	FF_ERROR	Error;

	if(!pFile) {
		return FF_ERR_NULL_POINTER;	
	}
	// UpDate Dirent if File-size has changed?

	// Update the Dirent!
	Error = FF_GetEntry(pFile->pIoman, pFile->DirEntry, pFile->DirCluster, &OriginalEntry);
	if(Error) {
		return Error;
	}
	
	if(!pFile->FileDeleted) {
		if(pFile->Filesize != OriginalEntry.Filesize) {
			OriginalEntry.Filesize = pFile->Filesize;
			Error = FF_PutEntry(pFile->pIoman, pFile->DirEntry, pFile->DirCluster, &OriginalEntry);
			if(Error) {
				return Error;
			}
		}
	}

	Error = FF_FlushCache(pFile->pIoman);		// Ensure all modfied blocks are flushed to disk!

	// Handle Linked list!
	FF_PendSemaphore(pFile->pIoman->pSemaphore);
	{	// Semaphore is required, or linked list could become corrupted.
		if(pFile->pIoman->FirstFile == pFile) {
			pFile->pIoman->FirstFile = pFile->Next;
		} else {
			pFileChain = (FF_FILE *) pFile->pIoman->FirstFile;
			while(pFileChain->Next != pFile) {
				pFileChain = pFileChain->Next;
			}
			pFileChain->Next = pFile->Next;
		}
	}	// Semaphore released, linked list was shortened!
	FF_ReleaseSemaphore(pFile->pIoman->pSemaphore);

	// If file written, flush to disk
	FF_FREE(pFile);

	if(Error) {
		return Error;
	}

	// Simply free the pointer!
	return FF_ERR_NONE;
}
Esempio n. 2
0
static FF_ERROR FF_ExtendFile(FF_FILE *pFile, FF_T_UINT32 Size) {
	FF_IOMAN	*pIoman = pFile->pIoman;
	FF_T_UINT32 nBytesPerCluster = pIoman->pPartition->BlkSize * pIoman->pPartition->SectorsPerCluster;
	FF_T_UINT32 nTotalClustersNeeded = Size / nBytesPerCluster;
	FF_T_UINT32 nClusterToExtend; 
	FF_T_UINT32 CurrentCluster, NextCluster;
	FF_T_UINT32	i;
	FF_DIRENT	OriginalEntry;

	if((pFile->Mode & FF_MODE_WRITE) != FF_MODE_WRITE) {
		return FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE;
	}

	if(pFile->Filesize == 0 && pFile->ObjectCluster == 0) {	// No Allocated clusters.
		// Create a Cluster chain!
		pFile->AddrCurrentCluster = FF_CreateClusterChain(pFile->pIoman);
		if(!FF_GetEntry(pIoman, pFile->DirEntry, pFile->DirCluster, &OriginalEntry)) {
			OriginalEntry.ObjectCluster = pFile->AddrCurrentCluster;
			FF_PutEntry(pIoman, pFile->DirEntry, pFile->DirCluster, &OriginalEntry);
		} else {
			return FF_ERR_FILE_EXTEND_FAILED;
		}
		pFile->ObjectCluster = pFile->AddrCurrentCluster;
		pFile->iChainLength = 1;
		pFile->CurrentCluster = 0;
		pFile->iEndOfChain = pFile->AddrCurrentCluster;
	}
	
	if(Size % nBytesPerCluster) {
		nTotalClustersNeeded += 1;
	}

	if(pFile->iChainLength == 0) {	// First extension requiring the chain length, 
		pFile->iChainLength = FF_GetChainLength(pIoman, pFile->ObjectCluster, &pFile->iEndOfChain);
	}

	nClusterToExtend = (nTotalClustersNeeded - pFile->iChainLength);

	if(nTotalClustersNeeded > pFile->iChainLength) {

		NextCluster = pFile->AddrCurrentCluster;
		FF_lockFAT(pIoman);
		{
			for(i = 0; i <= nClusterToExtend; i++) {
				CurrentCluster = FF_FindEndOfChain(pIoman, NextCluster);
				NextCluster = FF_FindFreeCluster(pIoman);
				if(!NextCluster) {
					FF_unlockFAT(pIoman);
					return FF_ERR_FAT_NO_FREE_CLUSTERS;
				}
				FF_putFatEntry(pIoman, CurrentCluster, NextCluster);
				FF_putFatEntry(pIoman, NextCluster, 0xFFFFFFFF);
			}
			
			pFile->iEndOfChain = FF_FindEndOfChain(pIoman, NextCluster);
		}
		FF_unlockFAT(pIoman);
		
		pFile->iChainLength += i;
		FF_DecreaseFreeClusters(pIoman, i);	// Keep Tab of Numbers for fast FreeSize()
	}

	return FF_ERR_NONE;
}