Esempio n. 1
0
//*************************************************************************************
//  Function:		CETYPE FS_CreateFile (	const char * 	FileName, 
//											FILE_MODE 		mode,
//											FSFILE* 		filePtr )
//  Summary:		Creates/Opens a file with ascii name provided in FileName
//  Input:
//					FileName 	- The name of the file to open
//  		  		mode 		- File open mode (FILE_MODE enum)
//        			- FS_CREATE_NEW		- Create a new file or replace an existing file.
//        			- FS_OPEN_EXISTING	- Open existing file for read/write access or 
//										  creates a new file; file is positioned at the
//										  beginning.
//         			- FS_APPEND			- Open existing file for read/write access or 
//										  creates a new file; file is positioned just
//										  past the last byte.
//        			- FS_READ_ONLY		- Open existing file in read-only mode; file
//										  positioned at the beginning.
//					filePtr		- pointer to FSFILE data structure that will be confi-
//								  gured ro provide access to the file if function
//								  succeeds.
//  Return Values:
//    				CETYPE - Expected CE_GOOD, but may have other codes depending on
//							 various error conditions.
//  Description:
//    				This function will create and/or open specified file.
//    				The specified file name will be formatted to ensure that it's in 8.3
//					format. Next, the search for the specified file name will be
//					performed. If the name is found, the action will be taken based
//					upon the requested File Mode.  
//*************************************************************************************
CETYPE FS_CreateFile (	const char* FileName, FILE_MODE mode, FSFILE* filePtr )
	{
 	//----------------------------------------------------------------
	// Validate conditions and parameters
 	//----------------------------------------------------------------
 	if (!SDFS_InitStatus)
 		return CE_NOT_INIT;		// FS is not initialized!
 	if (NULL == FileName)
 		return CE_INVALID_ARGUMENT;		
 	if (NULL == filePtr)
 		return CE_INVALID_ARGUMENT;		
	//-----------------------------------------------------------------
	
	CETYPE 	RC			= CE_GOOD;
	char	fmtName[NAME_SIZE_8r3];
	
	//-----------------------------------------------------------------
	// Validate new name and convert it to 8.3 FAT format
	//-----------------------------------------------------------------
	if ( !SDFS_Format8dot3Name(FileName, fmtName, FALSE) )
		return CE_INVALID_FILENAME;

 	//================================================================
 	// Make sure that the name provided is unique...
 	//----------------------------------------------------------------
 	FS_SeekStart(&SDFS_CWD);		// Rewind Current Working Directory
 	RC = SDFS_DirFindNext(&SDFS_CWD, filePtr, ATTR_NONE,  ATTR_NONE, fmtName);
 	//----------------------------------------------------------------
 	if (CE_EOF == RC)
 		// There is no object with the same name
 		goto NotFound;
 	//----------------------------------------------------------------			
 	if (CE_GOOD != RC)
 		// Some other error (except for CE_EOF) had happened...
 		return RC;
 	//----------------------------------------------------------------			
 	if ( FS_IsDirectory(filePtr) )
 		// The object found is a Directory...
 		{
	 	SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE);	// Reset output FSFILE structure
	 	return CE_FILENAME_EXISTS;
 		}
 	//----------------------------------------------------------------			


 	//================================================================
 	// The file with the specified name present on the disk...
 	//----------------------------------------------------------------
	switch(mode)
       	{
		case FS_CREATE_NEW:
            // File exists, we want to create a new one, so remove it first
            if ( CE_GOOD != (RC = FS_Delete(filePtr)) )
            	// Delete failed...
            	{
		 		SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE);	// Reset output FSFILE structure
            	return RC;
            	}
            //-----------------------------------------
            // Nope, does not exist any more :)
            goto NotFound;

               	
		case FS_APPEND:
            // File exists, we want to position it at the end
            if ( CE_GOOD != (RC = FS_SeekEnd(filePtr)) )
            	// Seek failed...
            	{
		 		SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE);	// Reset output FSFILE structure
            	return RC;
            	}
            //-----------------------------------------
            // Everything is fine!
            return CE_GOOD;
            

		case FS_READ_ONLY:
			// Set READONLY attribute on the FO data structure to prevent WRITEs
			filePtr->dirFileEntry.DIR_Attr |= ATTR_READONLY;
			// Fall-through to OPEN_EXISTING
		case FS_OPEN_EXISTING:
			FS_SeekStart(filePtr);
			return CE_GOOD;
			
			
		default:
	 		SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE);	// Reset output FSFILE structure
           	return CE_INVALID_ARGUMENT;
       	}


 	//================================================================
 	// The file with the specified name does not exist on disk...
 	//----------------------------------------------------------------
 NotFound:
	switch(mode)
       	{
		case FS_CREATE_NEW:
		case FS_APPEND:
		case FS_OPEN_EXISTING:
			// For all of the cases above proceed to creating new file
			break;
			

		case FS_READ_ONLY:
			// Bad luck...
	 		SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE);	// Reset output FSFILE structure
           	return CE_NOT_FOUND;
			
			
		default:
	 		SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE);	// Reset output FSFILE structure
           	return CE_INVALID_ARGUMENT;
       	}


 	//================================================================
 	// Now it is time to create a new file
 	//----------------------------------------------------------------
 	// First, try to create Directory Entry
 	//----------------------------------------------------------------
 	if ( (RC = SDFS_DirFindEmpty(&SDFS_CWD, filePtr)) != CE_GOOD)
 		return RC;		// Could not create directory entry...
 	//----------------------------------------------------------------
 	// Second, allocate a cluster to the file
 	//----------------------------------------------------------------
 	if ( CE_GOOD != (RC = SDFS_ClusterAllocateNew(filePtr)) )
 		{
 		SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE);	// Reset output FSFILE structure
	 	return RC;	
 		}
 	//----------------------------------------------------------------
 	// Third, set the name and Attributes of the new entry
 	//----------------------------------------------------------------
 	memcpy(filePtr->dirFileEntry.DIR_Name, fmtName, NAME_SIZE_8r3);
 	filePtr->dirFileEntry.DIR_Attr = ATTR_ARCHIVE;	
 	//----------------------------------------------------------------
 	// That's basically it - just need to save changes to disk
 	//----------------------------------------------------------------
 	return FS_Flush(filePtr);
	}
Esempio n. 2
0
//*********************************************************************************
//  Function:		CETYPE FS_Write(FSFILE* filePtr, const void* origin, WORD length)
//  Summary:		Write data to a file
//  Conditions:		File opened in FS_CREATE_NEW, FS_APPEND, or FS_OPEN_EXISTING mode
//  Input:
//    				filePtr	-	Pointer to file structure
//    				origin 	-	Pointer to source buffer
//    				length 	-    Length of the source buffer (data to write)
//  Return:
//    				CETYPE 	- 	Error code (expected: CE_GOOD)
//  Description:
//    				The FS_Write function will write data to a file. First, the sector
//					that corresponds to the current position in the file will be loaded 
//					(if it hasn't already been cached in the global data buffer). Data 
//					will then be written to the device from the specified buffer until 
//					the specified amount has been written.    
//					If the end of a cluster is reached, the next cluster will be
// 					loaded, unless the end-of-file flag for the specified file has been 
//					set. If it has, a new cluster will be allocated to the file. Finally, 
//					the new position and filesize will be stored in the FSFILE object.
//*********************************************************************************
CETYPE  FS_Write(FSFILE* filePtr, const void* origin, WORD length )
	{
 	//----------------------------------------------------------------
	// Validate conditions and parameters
 	//----------------------------------------------------------------
 	if (!SDFS_InitStatus)
 		return CE_NOT_INIT;		// FS is not initialized!
 	if (NULL == filePtr)
 		return CE_INVALID_ARGUMENT;		
 	//----------------------------------------------------------------
    // Check if the file attributes allow write
    if( (filePtr->dirFileEntry.DIR_Attr & ATTR_READONLY) == ATTR_READONLY )
        return CE_READONLY;
    // Check if pointer is valid	
    if (origin == NULL)
        return CE_INVALID_ARGUMENT;
    // Check if length is valid	
    if (length == 0)
        return CE_INVALID_ARGUMENT;
	//-----------------------------------------------------------------
 
	DWORD   LBA;
 	BYTE*	ptrFrom	= (BYTE*)origin;
 	WORD	ChunkSize;
	CETYPE 	RC;
    	
    // Write data to the file
    //{
	//------------------------------------------------------------	
    // Loop while writing bytes, exit loop if:
    //	* All bytes are written
    //	* Error encountered
	//------------------------------------------------------------	
 	while (length > 0)
		{
        //----------------------------------------------------
        // Make sure we have defined a place to write to
        //----------------------------------------------------
		//{
        if (filePtr->fileCrntSecPos == SDFS_VolumeInfo.sectorSize)
        	{
	        //----------------------------------------------------
	        // Current sector is filled in...
	        //----------------------------------------------------
	        // NOTE: fileCrntSec is a 0-based counter (index)
	        //----------------------------------------------------
           	if (filePtr->fileCrntSec == SDFS_VolumeInfo.SecPerClus - 1)
            	{
	 			//----------------------------------------------------
	 			// Current cluster is exhausted - move to the next one
				//----------------------------------------------------
				RC = SDFS_ClusterGetNext(filePtr);
				if ( CE_EOF == RC )
					// Oops! Reached end-of-file - try to add another cluster
					RC = SDFS_ClusterAllocateNew(filePtr);
				//----------------------------------------------------
				if ( CE_GOOD != RC )
					// Bad luck - no cluster to advance to!
	                return RC;
            	}
            else
            	{
	            // It is safe to move to the next sector in the current cluster
	            filePtr->fileCrntSec++;		    // move to the next sector
	            filePtr->fileCrntSecPos = 0;	// reset position
	            }
	        //----------------------------------------------------
         	}   	
		//}
		//-----------------------------------------------------------------   
	    LBA	= SDFS_FATClusterToLBA( filePtr->fileCrntCls)
	    			  		+ filePtr->fileCrntSec;	// add the sector number to it
		ChunkSize = length <= SDFS_VolumeInfo.sectorSize - filePtr->fileCrntSecPos ? 
							  length 
							: SDFS_VolumeInfo.sectorSize - filePtr->fileCrntSecPos;
		//-----------------------------------------------------------------   
		if	(CE_GOOD != (RC = SDFS_DataCacheWrite (LBA, ptrFrom, filePtr->fileCrntSecPos, ChunkSize )))	
			return RC;					
		//-----------------------------------------------------------------   
		length 	-= ChunkSize;
		ptrFrom	+= ChunkSize;
		//----------------------
		filePtr->fileCrntSecPos	+= ChunkSize;
		filePtr->fileSeek		+= ChunkSize;
		if (filePtr->dirFileEntry.DIR_FileSize < filePtr->fileSeek)
			filePtr->dirFileEntry.DIR_FileSize = filePtr->fileSeek;
		} 

	//-----------------------------------
    return CE_GOOD;
	} // write
Esempio n. 3
0
//*********************************************************************************
//  Function:		CETYPE FS_WriteSector(FSFILE* filePtr, const void* origin)
//  Summary:		Write data to a file one sector at a time bypassing CACHE
//  Conditions:		File opened in FS_CREATE_NEW, FS_APPEND, or FS_OPEN_EXISTING mode
//  Input:
//    				filePtr	-	Pointer to file structure
//    				origin 	-	Pointer to source buffer
//  Return:
//    				CETYPE 	- 	Error code (expected: CE_GOOD)
//  Description:
//    				The FS_WriteSector function will write data to a file one sector 
//					at a time bypassing CACHE. The length of the data buffer pointed
//					to by "orogin" expected to be equal to the size of the sector.    
//					If the end of a cluster is reached, the next cluster will be
// 					loaded, unless the end-of-file flag for the specified file has been 
//					set. If it has, a new cluster will be allocated to the file. Finally, 
//					the new position and filesize will be stored in the FSFILE object.
//*********************************************************************************
CETYPE  FS_WriteSector(FSFILE* filePtr, const void* origin)
	{
 	//----------------------------------------------------------------
	// Validate conditions and parameters
 	//----------------------------------------------------------------
 	if (!SDFS_InitStatus)
 		return CE_NOT_INIT;		// FS is not initialized!
 	if (NULL == filePtr)
 		return CE_INVALID_ARGUMENT;		
 	//----------------------------------------------------------------
    // Check if the file attributes allow write
    if( (filePtr->dirFileEntry.DIR_Attr & ATTR_READONLY) == ATTR_READONLY )
        return CE_READONLY;
    // Check if pointer is valid	
    if (origin == NULL)
        return CE_INVALID_ARGUMENT;
	//-----------------------------------------------------------------
 
	DWORD   LBA;
 	BYTE*	ptrFrom	= (BYTE*)origin;
 	WORD	ChunkSize;
	CETYPE 	RC;
    	
	//----------------------------------------------------
	// Make sure we have defined a place to write to
	//----------------------------------------------------
	if (0 != filePtr->fileCrntSecPos)
		// For Sector writes we always start at the EMPTY
		// sector, so the rest of the current sector will
		// be skipped...
		{
		// NOTE: fileCrntSec is a 0-based counter (index)
		//----------------------------------------------------
	  	if (filePtr->fileCrntSec == SDFS_VolumeInfo.SecPerClus - 1)
		   	{
			//----------------------------------------------------
			// Current cluster is exhausted - move to the next one
			//----------------------------------------------------
			RC = SDFS_ClusterGetNext(filePtr);
			if ( CE_EOF == RC )
			// Oops! Reached end-of-file - try to add another cluster
			RC = SDFS_ClusterAllocateNew(filePtr);
			//----------------------------------------------------
			if ( CE_GOOD != RC )
			// Bad luck - no cluster to advance to!
			        return RC;
		   	}
		else
		   	{
		    // It is safe to move to the next sector in the current cluster
		    filePtr->fileCrntSec++;		    // move to the next sector
		    filePtr->fileCrntSecPos = 0;	// reset position
		    }
		}
	//-----------------------------------------------------------------   
    LBA	= SDFS_FATClusterToLBA( filePtr->fileCrntCls)
    			  		+ filePtr->fileCrntSec;	// add the sector number to it
	ChunkSize = SDFS_VolumeInfo.sectorSize;
	//-----------------------------------------------------------------   
	if ( !SD_SPI_SectorWrite(LBA, ptrFrom, FALSE) )
			return CE_WRITE_ERROR;
	//-----------------------------------------------------------------   
	filePtr->fileCrntSecPos	+= ChunkSize;
	filePtr->fileSeek		+= ChunkSize;
	if (filePtr->dirFileEntry.DIR_FileSize < filePtr->fileSeek)
		filePtr->dirFileEntry.DIR_FileSize = filePtr->fileSeek; 
	//-----------------------------------
    return CE_GOOD;
	} // write
Esempio n. 4
0
//*************************************************************************************
//  Function:		CETYPE FS_mkDir (char * Name, ATTR_TYPE Attr, FSFILE* newDir)
//-------------------------------------------------------------------------------------
//  Summary:		Creates directory with the specified name in the current working
//					directory.
//  Input:			
//					Name	- Name of the new directory
//					Attr	- Additional attributes of the new directory
//					newDir	- pointer to the File Object structure that on SUCCESS
//							  will be set to the newly created directory.
//  Return Values:
//					CETYPE enum member (expected CE_GOOD)
//					Other codes depending on encountered error conditions
//*************************************************************************************
CETYPE FS_mkDir (char * Name, ATTR_TYPE Attr, FSFILE* newDir)
	{
 	//----------------------------------------------------------------
	// Validate conditions and parameters
 	//----------------------------------------------------------------
 	if (!SDFS_InitStatus)
 		return CE_NOT_INIT;		// FS is not initialized!
 	if (NULL == Name)
 		return CE_INVALID_FILENAME;		
 	if (NULL == newDir)
 		return CE_INVALID_ARGUMENT;		
 	//----------------------------------------------------------------
 	char	fmtName[NAME_SIZE_8r3];
 	CETYPE	RC;
 	//----------------------------------------------------------------
 	// Verify/Format provided Directory name (for direct match)
 	//----------------------------------------------------------------
 	if ( !SDFS_Format8dot3Name (Name, fmtName, FALSE) )
 		return CE_INVALID_FILENAME;	// Invalid/missing name
 	//----------------------------------------------------------------
 	// Make sure that the name provided is unique...
 	//----------------------------------------------------------------
 	FS_SeekStart(&SDFS_CWD);		// Rewind Current Working Directory
 	RC = SDFS_DirFindNext(&SDFS_CWD, newDir, ATTR_NONE,  ATTR_NONE, fmtName);
 	//----------------------------------------------------------------
 	if (CE_GOOD == RC)
 		{
	 	if ( FS_IsDirectory(newDir) )
	 		// Directory with the same name is found...
	 		return CE_GOOD;
	 	else
	 		// There exists file with the same name...
	 		{
		 	SDFS_InitFSFILE(newDir, NULL, ATTR_NONE);	// Reset output FSFILE structure
		 	return CE_FILENAME_EXISTS;
	 		}
 		}
 	if (CE_EOF != RC)
 		return RC;		// Some other error happend on the way...
 	//----------------------------------------------------------------
 	// The name provided is unique; Try to create Directory Entry
 	//----------------------------------------------------------------
 	if ( (RC = SDFS_DirFindEmpty(&SDFS_CWD, newDir)) != CE_GOOD)
 		return RC;		// Could not create directory entry...
 	//----------------------------------------------------------------
 	// Success; Set the name and Attributes of the new entry
 	//----------------------------------------------------------------
 	memcpy(newDir->dirFileEntry.DIR_Name, fmtName, NAME_SIZE_8r3);
 	newDir->dirFileEntry.DIR_Attr = ATTR_DIRECTORY | ATTR_ARCHIVE;	
 	//----------------------------------------------------------------
 	// Allocate a cluster for the new Directory and create mandatory
 	// "." and ".." entries
 	//----------------------------------------------------------------
 	if ( (RC = SDFS_ClusterAllocateNew(newDir)) != CE_GOOD)
 		// Failure allocating cluster...
 		{
	 	SDFS_InitFSFILE(newDir, NULL, ATTR_NONE);	// Reset output FSFILE structure
	 	return RC;
 		}
 	//----------------------------------------------------------------
 	DIRENTRY	spcDir;
 	DWORD		dirCluster;
 	// Set template Directory record for "." and ".." entries
 	SDFS_DirResetEntry(	&spcDir, NULL, ATTR_DIRECTORY);
 	//----------------------------------------------------------------
 	// Create and store "." entry
 	//----------------------------------------------------------------
 	spcDir.DIR_Name[0] = '.';
 	dirCluster = SDFS_DirGetFirstCluster(&newDir->dirFileEntry);
 	SDFS_DirSetFirstCluster (&spcDir, dirCluster);
 	FS_Write(newDir, &spcDir, sizeof(DIRENTRY));
 	//----------------------------------------------------------------
 	// Create and store ".." entry
 	//----------------------------------------------------------------
 	spcDir.DIR_Name[1] = '.';
 	dirCluster = SDFS_DirGetFirstCluster(&SDFS_CWD.dirFileEntry);
 	if (dirCluster == SDFS_VolumeInfo.rootClsN)
 		// Parent is the Root directory of the volume
 		dirCluster = 0; // FAT32 rule for pointers to Root
 	SDFS_DirSetFirstCluster (&spcDir, dirCluster);
 	FS_Write(newDir, &spcDir, sizeof(DIRENTRY));
 	//----------------------------------------------------------------
 	return FS_Flush(newDir);
	}