Creating a File | Kickoff

Creating a File

25 Mar

Creating a File
The CreateFileEntry function creates a new entry for a file in a directory. The function accepts pointers to a FILE structure (fo) and a variable that will hold the number of the file’s entry in its directory (fHandle). The function also allocates a cluster for the file. The function returns a status code.

The function calls the FindEmptyEntries, PopulateEntries, and CreateFirst- Cluster functions from this chapter. The FILE structure’s name member holds the name of the file to create.

CETYPE CreateFileEntry(FILEOBJ fo, word *fHandle)
{
CETYPE error = CE_GOOD;
byte index;
char name[11];
byte size;
// Save the file’s name from the FILE structure.
for (index = 0; index < FILE_NAME_SIZE; index ++)
{
name[index] = fo -> name[index];
}
if (error == CE_GOOD)
{
*fHandle = 0;
// Find an empty entry in the directory.
if (FindEmptyEntries(fo, fHandle))
{
// Store the file’s data in the entry.
if ((error = PopulateEntries(fo, name ,fHandle)) == CE_GOOD)
{
// Allocate a cluster to the file.
error = CreateFirstCluster(fo);
}
}
else
{
error = CE_DIR_FULL;
}
}
return(error);
}

Deleting a File
To delete an existing file in the FAT16 file system, the storage media’s host must do the following:

1. Search the file’s directory for the entry containing the name of the file to delete.
2. Save the cluster number from the file’s directory entry.
3. Mark the directory entry as deleted by storing E5h in the entry’s first byte.
4. Examine the FAT entry for the saved cluster number. If the entry isn’t an EOC marker, save the cluster number and store 0000h in the entry to mark it as available.
5. Repeat step 4 until finding an EOC marker. Replace the EOC marker with 0000h.

The FAT_erase_cluster_chain function accepts a cluster number (cluster) and a pointer to a DISK structure (dsk) and stores 0000h in all FAT entries in the chain beginning with the passed cluster number. The function calls the FATread and FATwrite functions from Chapter 8.

byte FAT_erase_cluster_chain (word cluster, DISK *dsk)
{
word c;
word c2;
enum _status {
Good,
Fail,
Exit
} status;
status = Good;
// Valid cluster numbers start at 2.
if (cluster == 0 || cluster == 1)
{
status = Exit;
}
else
{
while (status == Good)
{
// Get the FAT entry for the passed cluster number.
if (c = FATread(dsk, cluster)) == FAIL)
status = Fail;
else
{
// Valid cluster numbers start at 2.
if (c == 0 || c == 1)
{
status = Exit;
}
else
{
c2 = LAST_CLUSTER;
if ( c >= c2)
// The cluster is the last one in the chain.
status = Exit;
// Erase the fat entry by storing an empty-cluster code in the entry.
if (FATwrite(dsk, cluster, CLUSTER_EMPTY) == FAIL)
status = Fail;
// Set the current cluster to the value read from the FAT entry.
cluster = c;
}
}
} // End: while not the end of the chain and no error.
}
if (status == Exit)
// All of the FAT entries in the chain have been erased.
return (TRUE);
else
return(FALSE);
}

The FILEerase function erases a file’s directory entry and if requested, the FAT entries for all of the file’s clusters. The function accepts a FILEOBJ

pointer to a file structure (fo), a pointer to a directory entry (fHandle), and a value (EraseClusters) that indicates whether the function should erase the FAT entries for all of the file’s clusters.

In the passed file structure, the dirclus member must contain the number of the first cluster in the directory with the file entry. The function calls the Cache_File_Entry from Chapter 9 and the FAT_erase_cluster_chain function above. The function returns a status code.

CETYPE FILEerase(FILEOBJ fo, word *fHandle, byte EraseClusters)
{
byte a;
word clus;
DIRENTRY dir;
DISK *disk;
CETYPE status = CE_GOOD;
// Save the DISK structure.
disk = fo -> dsk;
// Set the directory’s current cluster number to the directory’s first cluster.
clus = fo -> dirclus;
fo -> dirccls = clus;
// Read the sector containing the entry to erase.
dir = Cache_File_Entry(fo, fHandle, TRUE);
// Was a non-empty, non-deleted entry returned?
a = dir->DIR_Name[0];
if (dir == (DIRENTRY)NULL || a == DIR_EMPTY)
{
status = CE_FILE_NOT_FOUND;
}
else
{
if ( a == DIR_DEL)
status = CE_FILE_NOT_FOUND;

else
{
a = dir->DIR_Attr;
// Mark the entry as deleted.
dir->DIR_Name[0] = DIR_DEL;
// Save the number of the entry’s first cluster.
clus = dir->DIR_FstClusLO;
// Write the revised directory entry to delete the file.
if (status != CE_GOOD || !(Write_File_Entry( fo, fHandle)))
status = CE_ERASE_FAIL;
else
{
if (EraseClusters)
{
// Erase the FAT entries for the file’s clusters.
status =
((FAT_erase_cluster_chain(clus, disk)) ? CE_GOOD : CE_ERASE_FAIL);
}
}
} // End: a not empty, not deleted entry was returned
} // End: a not empty entry was returned
return (status);
}

Opening a File
The FILEopen function performs several actions to prepare a file for reading or writing. The function retrieves a file’s directory entry, copies information from the entry into a FILE structure, initializes other members of the FILE structure, reads the file’s first sector into the file structure’s dsk -> buffer member, and sets the file structure’s FLAGS.write member to indicate whether the file is open for reading or writing.

The function accepts a pointer to a file structure (fo), a pointer to the number of the file’s entry in its directory (fHandle), and a character that specifies whether to open the file for append (a), read (r), or write (w). In the passed file structure, the dirclus member must contain the number of the first cluster in the file’s directory.

The function calls the SectorRead function from Chapter 5, the Cluster2Sector function from Chapter 8, the Cache_File_Entry function from Chapter 9, and the Fill_File_Object function from this chapter. After calling the function, firmware can use the information in the FILE structure to perform operations on the file’s contents.

CETYPE FILEopen (FILEOBJ fo, word *fHandle, char type)
{
DISK *dsk;
CETYPE error = CE_GOOD;
dword l;
byte r;
// Save the FILE structure’s dsk member.
dsk = (DISK *)(fo -> dsk);
if (dsk -> mount == FALSE)
error = CE_NOT_INIT; // The media isn’t available.
else
{
// Get the file’s directory entry and store the directory’s sector
// in the dsk -> buffer member of the file structure (fo).
Cache_File_Entry(fo, fHandle, TRUE);
// Fill the file structure with information from the directory entry.
r = Fill_File_Object(fo, fHandle);
if (r != FOUND)
error = CE_FILE_NOT_FOUND;

else
{
// A file was found.
// Initialize FILE structure members.
fo -> seek = 0; // Byte offset in the file.
fo -> ccls = fo -> cluster; // The current cluster = the file’s first cluster.
fo -> sec = 0; // The sector in the cluster.
fo -> pos = 0; // The byte in the sector.
// Determine the LBA of the file’s current cluster.
l = Cluster2Sector(dsk, fo -> ccls);
// Read the cluster’s first sector into the DISK structure’s buffer member.
if ( SectorRead( l, dsk -> buffer) != sdcValid)
error = CE_BAD_SECTOR_READ;
// Set the FILE structure’s flags.
fo -> Flags.FileWriteEOF = FALSE;
if (type == ‘w’ || type == ‘a’)
{
// Open the file for writing or appending.
fo -> Flags.write = 1;
}
else
{
// Open the file for reading.
fo -> Flags.write = 0;
}
} // End: a file was found.
} // End: the media is available.
return (error);
}

Figure 10-1: A mass-storage master performs these actions to read the contents of a file.

Reading from a File
The FILEopen function above can prepare to read from a file. Because storage media typically requires reading complete sectors, each read from the media reads a sector’s worth of data even if the firmware requires just one or a few bytes.

Tasks
To read a file’s contents, firmware must perform the following actions (shown in Figure 10-1):

1. Get the file’s size and the number of the file’s first cluster from the directory entry and convert the cluster number to an LBA sector number.
2. Read data from the cluster’s sector(s).

3. To read more data, get the next cluster number from the current cluster’s FAT entry, convert the cluster number to an LBA sector number, and read the data in the cluster’s sector(s).

4. Repeat step 3 as needed until a FAT entry indicates that the entry’s cluster is the last cluster in the file.

Random Posts

No comments yet

Leave a Reply

You must be logged in to post a comment.