fileio.c

来自「SD卡驱动」· C语言 代码 · 共 2,353 行 · 第 1/5 页

C
2,353
字号
    return(c);
}


/******************************************************************************
 * Function:        WORD FATReadQueued( DISK *dsk, WORD ccls)
 *
 * PreCondition:    Disk mounted
 *
 * Input:           dsk		- Disk structure
 *                  
 * Output:			c		- Cluster; 0 if failed
 *
 * Side Effects:    None
 *
 * Overview:        Queue based FAT read
 *
 * Note:            Should not be called by user
 *****************************************************************************/
WORD FATReadQueued( DISK *dsk, WORD ccls)
// dsk  disk structure
// ccls current cluster
{
    WORD p, c;
    DWORD l;

    if ( dsk->type != FAT16)
       return CLUSTER_FAIL;

	gBufferOwner = NULL;

    // get address of current cluster in fat
    p = ccls;
    // cluster = 0xabcd
    // packed as:     0   |   1    |   2   |  3    |
    // word p       0   1 |  2   3 | 4   5 | 6   7 |..
    //              cd  ab|  cd  ab| cd  ab| cd  ab|

    // load the fat sector containing the cluster
    if((ccls & 0xFF) == 0x00)
    {
        l = dsk->fat + (p >> 8 );   // 256 clusters per sector
        if( !SECTORread( l, dsk->buffer) )
            return CLUSTER_FAIL;
    }

    // get the next cluster value
    c = RAMreadW( dsk->buffer, ((p & 0xFF)<<1));

    if(c >= LAST_CLUSTER_FAT16)
        c = LAST_CLUSTER;

    return c;

} // FATReadQueued



/******************************************************************************
 * Function:        CETYPE __fclose(FILEOBJ fo)
 *
 * PreCondition:    File opened
 *
 * Input:           fo		- Pointer to file structure
 *                  
 * Output:			CE_GOOD				- File closed successfully
 *					CE_WRITE_ERROR		- Could not write to the sector
 *					CE_FILENOTOPENED	- File not opened for the write 
 *
 * Side Effects:    None
 *
 * Overview:        Close a file
 *
 * Note:
 *****************************************************************************/

CETYPE __fclose(FILEOBJ fo)
{
    WORD        fHandle, fIndex;
    CETYPE        error = 72;
    DIRENTRY    dir;

    fHandle = fo->entry;

    if(fo->Flags.write)
    {
        // Get the entry
        dir = LoadDirAttrib(fo, &fHandle);

        // update the time
        IncrementTimeStamp(dir);

        dir->DIR_FileSize = fo->size;

        // just write the last entry in
        if(Write_File_Entry(fo,&fHandle))
            error = CE_GOOD;
        else
            error = CE_WRITE_ERROR;

        // its now closed!
        fo->Flags.write = FALSE;
    }

#ifdef FAT16_DYNAMIC_MEM
	FAT16_free((unsigned char *)fo);
#else

	for( fIndex = 0; fIndex < FAT16_MAX_FILES_OPEN; fIndex++ )
	{
		if( fo == &gFileArray[fIndex] )
		{
			gFileSlotOpen[fIndex] = TRUE;
			break;
		}
	}


#endif

    if (error == 72)
		error = CE_GOOD;

    return(error);
} // my_fclose



/******************************************************************************
 * Function:        void IncrementTimeStamp(DIRENTRY dir)
 *
 * PreCondition:    File opened
 *
 * Input:           dir		- Pointer to directory structure
 *                  
 * Output:			void
 *
 * Side Effects:    None
 *
 * Overview:        Touch the time so we can keep track of the files
 *
 * Note:            None
 *****************************************************************************/

void IncrementTimeStamp(DIRENTRY dir)
{
    BYTE          seconds;
    BYTE          minutes;
    BYTE          hours;
    
    BYTE          day;
    BYTE          month;
    BYTE          year;
    
    seconds = (dir->DIR_WrtTime & 0x1f);
    minutes = ((dir->DIR_WrtTime & 0x07E0) >> 5);
    hours   = ((dir->DIR_WrtTime & 0xF800) >> 11);

    day     = (dir->DIR_WrtDate & 0x1f);
    month   = ((dir->DIR_WrtDate & 0x01E0) >> 5);
    year    = ((dir->DIR_WrtDate & 0xFE00) >> 9);
        
    if(seconds < 29)
        seconds++;
    else
    {
        seconds = 0x00;
        
        if(minutes < 59)
        {
           minutes++; 
        }
        else
        {
            minutes = 0;
            
            if(hours < 23)
            {
                hours++;
            }
            else
            {
                hours = 0;
                // new day!... only 28 in a month
                if(day < 28)
                {
                    day++;
                }
                else
                {
                    day = 1;
                    
                    if(month < 12)
                    {
                        month++;
                    }
                    else
                    {
                        month = 1;
                        // new year
                        year++;
                        // HOPEFULLY we never go past 2107
                    }
                }
            }
        }
    }
    
    dir->DIR_WrtTime = (WORD)(seconds);
    dir->DIR_WrtTime |= ((WORD)(minutes) << 5);
    dir->DIR_WrtTime |= ((WORD)(hours) << 11);  
    
    dir->DIR_WrtDate = (WORD)(day);
    dir->DIR_WrtDate |= ((WORD)(month) << 5);
    dir->DIR_WrtDate |= ((WORD)(year) << 9);
}


/******************************************************************************
 * Function:        BYTE Fill_File_Object(FILEOBJ fo, WORD *fHandle)
 *
 * PreCondition:    Disk mounted
 *
 * Input:           fo		- Pointer to file structure
 *					fHandle - Passed member's location
 *                  
 * Output:			FOUND		- Operation successful
 *					NOT_FOUND	- Operation failed
 *
 * Side Effects:    None
 *
 * Overview:        Fill the passed file object with the passed member's (fHandle) information
 *
 * Note:            Should not be called by user
 *****************************************************************************/

BYTE Fill_File_Object(FILEOBJ fo, WORD *fHandle)
{
    DIRENTRY    dir;
    BYTE 			index, a;         
    BYTE     character;
    BYTE          status;   
    DWORD         temp;
	BYTE	test = 0;
    
    // Get the entry
    dir = Cache_File_Entry( fo, fHandle, FALSE);
    
    // Read the first char of the file name 
    a = dir->DIR_Name[0]; 
	    
    // Make sure there is a directory left
    if(dir == (DIRENTRY)NULL || a == DIR_EMPTY)
    {                  
        status = NO_MORE;
    }
    else
    {
        // Check for empty or deleted directory
        if ( a == DIR_DEL)
            status = NOT_FOUND;
        else
        {
            // Get the attributes
            a = dir->DIR_Attr; 
            

			/* Short File Name */
        
			// 2.1.1  print the file name and extension         					
			for (index=0; index < DIR_NAMESIZE; index++)
			{
				character = dir->DIR_Name[index];
				character = (BYTE)toupper(character); 

				fo->name[test++] = character;
			}
			
			// Get the attributes
			a = dir->DIR_Attr; 

			// its possible to have an extension in a directory
			character = dir->DIR_Extension[0];

			// Get the file extension if its there
			for (index=0; index < DIR_EXTENSION; index++)
			{
				character = dir->DIR_Extension[index];
				character = (BYTE)toupper(character);

				fo->name[test++] = character;
			}

			// done and done with the name
//			fo->name[++test] = (BYTE)'\0';

			// Now store the identifier
			fo->entry = *fHandle;
					

            // see if we are still a good file (long file names can erase just the main entry)
            a = dir->DIR_Name[0];
            
            if(a == DIR_DEL)
                status = NOT_FOUND;
            else
                status = FOUND;

			// Now store the size
            fo->size = (dir->DIR_FileSize);
            	
	        // Now store the cluster
	        temp = (dir->DIR_FstClusHI);
			temp = temp << 16;
	        temp |= dir->DIR_FstClusLO;
	        fo->cluster = temp;
	                  
	        // get the date and time      
	        fo->time = (dir->DIR_WrtTime);
            fo->date = (dir->DIR_WrtDate);
	
	        /// -Get and store the attributes
            a = dir->DIR_Attr;           
            fo->attributes = a;
 
        }// deleted directory  
    }// Ensure we are still good
        
    return(status);
} // Fill_File_Object


/******************************************************************************
 * Function:        DIRENTRY LoadDirAttrib(FILEOBJ fo, WORD *fHandle)
 *
 * PreCondition:    Disk mounted
 *
 * Input:           fo		- Pointer to file structure
 *					fHandle	- Information location
 *                  
 * Output:			DIRENTRY	- The directory entry
 *
 * Side Effects:    None
 *
 * Overview:        Load the current sector for the filename base and return the direntry
 *
 * Note:            Should not be called by user
 *****************************************************************************/

DIRENTRY LoadDirAttrib(FILEOBJ fo, WORD *fHandle)
{
    DIRENTRY    dir;
    BYTE		a;         
    
    // Get the entry
    dir = Cache_File_Entry( fo, fHandle, TRUE);
    
    // Read the first char of the file name 
    a = dir->DIR_Name[0]; 
	    
    // Make sure there is a directory left
    if(a == DIR_EMPTY)
        dir = (DIRENTRY)NULL;
    
    if(dir != (DIRENTRY)NULL)
    {
        // Check for empty or deleted directory
        if ( a == DIR_DEL)
            dir = (DIRENTRY)NULL;
        else
        {
            // Get the attributes
            a = dir->DIR_Attr; 
            
             // scan through all the long dir entries
            while(a == ATTR_LONG_NAME)
            {   
                (*fHandle)++;
                dir = Cache_File_Entry( fo, fHandle, FALSE);
                a = dir->DIR_Attr;      
            } // long file name while loop
            
        } // deleted dir
        
    }// Ensure we are still good
        
    return(dir);
} // LoadDirAttrib


/******************************************************************************
 * Function:        CETYPE FILEerase( FILEOBJ fo, WORD *fHandle, BYTE EraseClusters)
 *
 * PreCondition:    File not opened, File exists
 *
 * Input:           fo				- Pointer to file structure
 *					fHandle 		- Location of file information
 *					EraseClusters 	- Remove cluster allocation from FAT?
 *                  
 * Output:			CE_GOOD				- File erased successfully
 *					CE_FILE_NOT_FOUND	- Could not find the file on the card
 *					CE_ERASE_FAIL		- Internal Card erase failed
 *
 * Side Effects:    None
 *
 * Overview:        Erase file
 *
 * Note:            Should not be called by user
 *****************************************************************************/

CETYPE FILEerase( FILEOBJ fo, WORD *fHandle, BYTE EraseClusters)
{
    DIRENTRY    dir;
    BYTE		a;           
    CETYPE      status = CE_GOOD;   
    WORD        clus;  
    DISK *      disk;
    
    disk = fo->dsk;    

    // reset the cluster
    clus = fo->dirclus;
    fo->dirccls = clus;
    
    // load the sector
    dir = Cache_File_Entry(fo, fHandle, TRUE);
    
    // Fill up the File Object with the information pointed to by fHandle
    a = dir->DIR_Name[0]; 
	    
    // see if there is something in the dir
    if(dir == (DIRENTRY)NULL || a == DIR_EMPTY)
    {                  
        status = CE_FILE_NOT_FOUND;
    }
    else
    {
        // Check for empty or deleted directory
        if ( a == DIR_DEL)
            status = CE_FILE_NOT_FOUND;
        else
        {        
            // Get the attributes
            a = dir->DIR_Attr; 
              
		    /* Short File Name - entry*/
		    dir->DIR_Name[0] = DIR_DEL; // mark as deleted
	
	        // Get the starting cluster
	        clus = dir->DIR_FstClusLO;
	        
            // Now write it 
            if(status != CE_GOOD || !(Write_File_Entry( fo, fHandle)))
                status = CE_ERASE_FAIL;
            else
            {
                if(EraseClusters)
                {
                    /* Now my_remove the cluster allocation from the FAT */
                    status = ((FAT_erase_cluster_chain(clus, disk)) ? CE_GOOD : CE_ERASE_FAIL);    
                }
            }
        
        } // Not already deleted
        
    }// Not existant
            
    return (status);
}

/******************************************************************************

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?