fileio.c
来自「SD卡驱动」· C语言 代码 · 共 2,353 行 · 第 1/5 页
C
2,353 行
CETYPE __fwrite( MYFILE* fo, void * src, WORD count, WORD* pBytesWritten )
{
DISK * dsk; // pointer to disk structure
CETYPE error = CE_GOOD;
BYTE sectorloaded = FALSE;
WORD pos;
DWORD l; // absolute lba of sector to load
DWORD seek,size;
// see if the file was openned in a write mode
if(!(fo->Flags.write))
return CE_WRITE_ERROR;
if (WriteProtectState())
return CE_WRITE_PROTECTED;
dsk = fo->dsk;
// get the stated position
pos = fo->pos;
seek = fo->seek;
l = Cluster2Sector(dsk,fo->ccls);
l += (WORD)fo->sec; // add the sector number to it
gBufferOwner = fo;
if(!SECTORread( l, dsk->buffer) )
error = CE_BAD_SECTOR_READ;
sectorloaded = TRUE;
// exit loop if EOF reached
size = fo->size;
// 2. loop reading count bytes
while (error == CE_GOOD && count > 0)
{
if( seek == size )
fo->Flags.FileWriteEOF = TRUE;
// load a new sector if necessary, multiples of sector
if (pos == MEDIA_SECTOR_SIZE)
{
// close the currently loaded sector if we need to
if(sectorloaded)
{
if(SECTORwrite( l, dsk->buffer) != TRUE)
error = CE_WRITE_ERROR;
}
// reset position
pos = 0;
// point to the next sector
fo->sec++;
// get a new cluster if necessary
if (fo->sec == dsk->SecPerClus)
{
fo->sec = 0;
if(fo->Flags.FileWriteEOF)
error = FILEallocate_new_cluster(fo); // add new cluster to the file
else
error = FILEget_next_cluster( fo, 1);
}
if (error == CE_DISK_FULL)
return error;
if(error == CE_GOOD)
{
l = Cluster2Sector(dsk,fo->ccls);
l += (WORD)fo->sec; // add the sector number to it
gBufferOwner = fo;
if( !SECTORread( l, dsk->buffer) )
error = CE_BAD_SECTOR_READ;
sectorloaded = TRUE;
}
} // load new sector
if(error == CE_GOOD)
{
// Write one byte at a time
RAMwrite( dsk->buffer, pos++, *(char *)src);
src = src + 1; // compiler bug
seek++;
count--;
(*pBytesWritten)++;
}
// now increment the size of the part
if(fo->Flags.FileWriteEOF)
size++;
} // while count
if(error == CE_GOOD)
{
// figure out the lba
l = Cluster2Sector(dsk,fo->ccls);
l += (WORD)fo->sec; // add the sector number to it
if(!SECTORwrite( l, dsk->buffer))
error = CE_WRITE_ERROR;
}
// save off the positon
fo->pos = pos;
// save off the seek
fo->seek = seek;
// now the new size
fo->size = size;
return(error);
} // __fwrite
/******************************************************************************
* Function: CETYPE CreateFileEntry(FILEOBJ fo, WORD *fHandle)
*
* PreCondition: File opened in WRITE mode
*
* Input: fo - Pointer to file structure
* fHandle - Location to create file
*
* Output: CE_GOOD - File creation successful
* CE_DIR_FULL - All root dir entry are taken
*
* Side Effects: None
*
* Overview: With the data passed within fo, create a new file entry in the current directory
*
* Note: None
*****************************************************************************/
CETYPE CreateFileEntry(FILEOBJ fo, WORD *fHandle)
{
BYTE index;
CETYPE error = CE_GOOD;
char name[11];
for (index = 0; index < FILE_NAME_SIZE; index ++)
{
name[index] = fo->name[index];
}
// make sure we are good
if(error == CE_GOOD)
{
*fHandle = 0;
// figure out where to put this file in the directory stucture
if(FindEmptyEntries(fo, fHandle))
{
// found the entry now populate it
if((error = PopulateEntries(fo, name ,fHandle)) == CE_GOOD)
{
// if everything is a go, create a first cluster
error = CreateFirstCluster(fo);
}
}
else
{
error = CE_DIR_FULL;
}
}
return(error);
}
/******************************************************************************
* Function: CETYPE CreateFirstCluster(FILEOBJ fo)
*
* PreCondition: Called from CreateFileEntry
*
* Input: fo - The file that contains the first cluster
*
* Output: CE_GOOD - First cluster created
* CE_WRITE_ERROR - Cluster creation failed
*
* Side Effects: None
*
* Overview: Finds an open cluster and links it in
*
* Note: Should not be called by user
*****************************************************************************/
CETYPE CreateFirstCluster(FILEOBJ fo)
{
CETYPE error;
WORD cluster;
WORD fHandle;
DIRENTRY dir;
fHandle = fo->entry;
// Now create the first cluster (head cluster)
if((error = FILECreateHeadCluster(fo,&cluster)) == CE_GOOD)
{
// load it so I can link in the new cluster
dir = LoadDirAttrib(fo, &fHandle);
// Now update the new cluster
dir->DIR_FstClusLO = cluster;
// now write it
if(Write_File_Entry(fo, &fHandle) != TRUE)
error = CE_WRITE_ERROR;
} // Create Cluster
return(error);
}// End of CreateFirstCluster
/******************************************************************************
* Function: BYTE FindEmptyEntries(FILEOBJ fo, WORD *fHandle)
*
* PreCondition: Disk mounted, CreateFileEntry called
*
* Input: fo - Pointer to file structure
* fHandle - Start of entries
*
* Output: TRUE - One found
* FALSE - None found
*
* Side Effects: None
*
* Overview: Find the passed number of contingiant empty entries
*
* Note: Should not be called by user
*****************************************************************************/
BYTE FindEmptyEntries(FILEOBJ fo, WORD *fHandle)
{
BYTE status = NOT_FOUND;
BYTE amountfound;
BYTE a;
WORD bHandle;
DIRENTRY dir;
if((dir = Cache_File_Entry( fo, fHandle, TRUE)) == NULL)
{
status = CE_BADCACHEREAD;
}
else
{
// while its still not found
while(status == NOT_FOUND)
{
amountfound = 0;
bHandle = *fHandle;
// find (number) continuous entries
do
{
// Get the entry
dir = Cache_File_Entry( fo, fHandle, FALSE);
// Read the first char of the file name
a = dir->DIR_Name[0];
// increase number
(*fHandle)++;
}while((a == DIR_DEL || a == DIR_EMPTY) && (dir != (DIRENTRY)NULL) && (++amountfound < 1));
// --- now why did we exit?
if(dir == NULL) // Last entry of the cluster
{
//setup the current cluster
a = fo->dirccls; // write it back
// make sure we are not the root directory
if(a == 0)
status = NO_MORE;
else
{
fo->ccls = a;
if(FILEallocate_new_cluster(fo) == CE_DISK_FULL)
status = NO_MORE;
else
{
*fHandle = bHandle;
status = FOUND; // a new cluster will surely hold a new file name
}
}
}
else
{
if(amountfound == 1)
{
status = FOUND;
*fHandle = bHandle;
}
}
}// while
// copy the base handle over
*fHandle = bHandle;
}
if(status == FOUND)
return(TRUE);
else
return(FALSE);
}
/******************************************************************************
* Function: BYTE PopulateEntries(FILEOBJ fo, char *name , WORD *fHandle)
*
* PreCondition: Disk mounted, CreateFileEntry called
*
* Input: fo - Pointer to file structure
* name - Name of the file
* fHandle - Location of the file
*
* Output: CE_GOOD - Population successful
*
* Side Effects: None
*
* Overview: Actually fill up the directory entry with the data at hand and write it
*
* Note: Should not be called by user
*****************************************************************************/
BYTE PopulateEntries(FILEOBJ fo, char *name , WORD *fHandle)
{
BYTE error = CE_GOOD;
DIRENTRY dir;
dir = Cache_File_Entry( fo, fHandle, TRUE);
// copy the contents over
strncpy(dir->DIR_Name,name,DIR_NAMECOMP);
// setup no attributes
dir->DIR_Attr = ATTR_ARCHIVE;
dir->DIR_NTRes = 0x00; // nt reserved
// we don't have a real time clock
dir->DIR_CrtTimeTenth = 0xB2; // millisecond stamp
dir->DIR_CrtTime = 0x7278; // time created //
dir->DIR_CrtDate = 0x32B0; // date created (1/1/2004)
dir->DIR_LstAccDate = 0x32B0; // Last Access date
dir->DIR_FstClusHI = 0x00; // high word of this enty's first cluster number
dir->DIR_WrtTime = 0x7279; // last update time
dir->DIR_WrtDate = 0x32B0; // last update date
dir->DIR_FstClusLO = 0x0000; // low word of this entry's first cluster number
dir->DIR_FileSize = 0x0; // file size in DWORD
fo->size = dir->DIR_FileSize;
fo->time = dir->DIR_CrtTime;
fo->date = dir->DIR_CrtDate;
fo->attributes = dir->DIR_Attr;
fo->entry = *fHandle;
// just write the last entry in
Write_File_Entry(fo,fHandle);
return(error);
}
/******************************************************************************
* Function: BYTE FILEallocate_new_cluster( FILEOBJ fo)
*
* PreCondition: Disk mounted
*
* Input: fo - Pointer to file structure
*
* Output: OK - Cluster allocated
*
* Side Effects: None
*
* Overview: Allocate new cluster
*
* Note: Should not be called by user
*****************************************************************************/
BYTE FILEallocate_new_cluster( FILEOBJ fo)
// fo file structure
{
DISK * dsk;
WORD c,curcls;
dsk = fo->dsk;
c = fo->ccls;
// find the next empty cluster
c = FATfindEmptyCluster(fo);
if (c == 0)
return CE_DISK_FULL;
// mark the cluster as taken, and last in chain
if(dsk->type == FAT12)
FATwrite( dsk, c, LAST_CLUSTER_FAT12);
else
FATwrite( dsk, c, LAST_CLUSTER_FAT16);
// link current cluster to the new one
curcls = fo->ccls;
FATwrite( dsk, curcls, c);
// update the MYFILE structure
fo->ccls = c;
return CE_GOOD;
} // allocate new cluster
/******************************************************************************
* Function: WORD FATfindEmptyCluster(FILEOBJ fo)
*
* PreCondition: Disk mounted
*
* Input: fo - Pointer to file structure
*
* Output: c - Cluster; 0 if failed
*
* Side Effects: None
*
* Overview: Find the next available cluster
*
* Note: Should not be called by user
*****************************************************************************/
WORD FATfindEmptyCluster(FILEOBJ fo)
{
DISK * disk;
WORD value=0x0,c,curcls;
disk = fo->dsk;
c = fo->ccls;
// just incase
if(c < 2)
c = 2;
curcls = c;
FATread(disk, c);
// sequentially scan through the FAT looking for an empty cluster
while(c)
{
c++; // check next cluster in FAT
// check if reached last cluster in FAT, re-start from top
if (value == END_CLUSTER || c >= disk->maxcls)
c = 2;
// check if full circle done, disk full
if ( c == curcls)
{
c = 0;
break;
}
// look at its value
if ( (value = FATReadQueued(disk, c)) == CLUSTER_FAIL)
{
c = 0;
break;
}
// check if empty cluster found
if (value == CLUSTER_EMPTY)
break;
} // scanning for an empty cluster
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?