File Operations

25 Mar

File Operations
After the storage media has been formatted with a file system, firmware can create, read, modify, and delete files. This chapter presents firmware that performs these operations.

The code in this chapter uses the FILE and DISK structures introduced in Chapter 8 and the DIRENTRY structure introduced in Chapter 9.

The functions that access files use return values of type CETYPE:

typedef byte CETYPE;
#define CE_GOOD 0 // No error
#define CE_NOT_INIT 6 // Card isn’t initialized due to an error
#define CE_BAD_SECTOR_READ 7 // Error in reading a sector
#define CE_WRITE_ERROR 8 // Couldn’t write to the sector
#define CE_FILE_NOT_FOUND 10 // Couldn’t find the file
#define CE_DIR_FULL 17 // All of the entries are in use
#define CE_DISK_FULL 18 // All of the clusters are full
#define CE_WRITE_PROTECTED 22 // The card is write protected
#define CE_BADCACHEREAD 28 // Sector read failed
#define CE_EOF 61 // End of file reached

Cluster Operations
In creating and writing to files, a mass-storage host must be able to allocate clusters to files. A host might also want to erase the contents of a cluster. The following functions show how to perform these operations.

Erasing a Cluster
Deleting a file typically just removes the directory entry and marks the file’s cluster(s) as available. The clusters may still contain data from the deleted file. When allocating an available cluster to a new file, the host may want to erase the cluster’s contents by writing zero to each of the cluster’s bytes.

The EraseCluster function accepts pointer to a DISK structure (disk) and a cluster number to erase (cluster) and returns a status code. The function calls the SectorWrite function from Chapter 5 and the Cluster2Sector function from Chapter 8.

byte EraseCluster(DISK *disk, word cluster)
{
byte index;
byte NumofSectors;
dword SectorAddress;
// Get the LBA of the passed cluster number.
SectorAddress = Cluster2Sector(disk, cluster);
// Set the buffer’s data to zeroes.
memset(disk -> buffer, 0×00, SDC_SECTOR_SIZE);
// Write the buffer’s contents to the sector in the storage media.
for (index = 0; index < disk -> SecPerClus && error == CE_GOOD; index++)
{
if (SectorWrite(SectorAddress++, disk -> buffer) != sdcValid)
error = CE_WRITE_ERROR;
}
return(error);
}

Reserving an Available Cluster
The FILECreateHeadCluster function reserves an available cluster, which the host can then allocate to a file. The function accepts a pointer to a FILE structure (fo) and a pointer to a variable that will contain the number of a reserved, empty cluster (cluster). The function returns a status code.

The function calls the FATfindEmptyCluster and FATwrite functions from Chapter 8, the LoadDirAttrib function from Chapter 9, and the EraseCluster function above.

CETYPE FILECreateHeadCluster(FILEOBJ fo, word *cluster)
{
word curcls;
DISK *disk;
// Save the FILE structure’s dsk member.
disk = fo -> dsk;
// Use the FAT to find an available cluster.
*cluster = FATfindEmptyCluster(fo);
if (*cluster == 0)
error = CE_DISK_FULL;
else
{
// Mark the cluster as in use and the last one in the chain.
if (FATwrite(disk, *cluster, LAST_CLUSTER_FAT16) == FAIL)
error = CE_WRITE_ERROR;
// Erase the cluster’s contents.
if (error == CE_GOOD)
{
error = EraseCluster(disk,*cluster);
}
}
return(error);
}

Allocating a File’s First Cluster
The CreateFirstCluster function stores a cluster number in a file’s directory entry. The function accepts a pointer to a FILE structure (fo) and returns a status code. The function calls the LoadDirAttrib and Write_File_Entry functions from Chapter 9 and the FILECreateHeadCluster function above.

CETYPE CreateFirstCluster(FILEOBJ fo)
{
word cluster;
DIRENTRY dir;
CETYPE error;
word fHandle;
// Save the number of the file’s entry in the directory.
fHandle = fo -> entry;
// Allocate a cluster for the file.
if ((error = FILECreateHeadCluster(fo, &cluster)) == CE_GOOD)
{
// Get the file’s directory entry.
dir = LoadDirAttrib(fo, &fHandle);
// Store the file’s cluster number in the directory entry.
dir -> DIR_FstClusLO = cluster;
// Write the entry to the directory.
if (Write_File_Entry(fo, &fHandle) != TRUE)
error = CE_WRITE_ERROR;
}
return(error);
}


Random Posts

No comments yet

Leave a Reply

You must be logged in to post a comment.