Allocating Additional Clusters
If a write operation needs additional storage beyond the clusters allocated to a file, the host must find a new available cluster and allocate it to the file. Another situation where the host needs to allocate an additional cluster is when adding an entry to a subdirectory whose cluster(s) are full. The FILEallocate_new_cluster function can perform these tasks.
The function accepts a FILEOBJ pointer to a FILE structure, finds an available cluster, adds the cluster to the file’s cluster chain in the FAT, sets the FILE structure’s ccls member to the new cluster’s number, and returns a status code. The function calls the FATfindEmptyCluster and FATwrite functions from Chapter 8.
byte FILEallocate_new_cluster( FILEOBJ fo)
// Save the FILE structure’s dsk and ccls members.
dsk = fo -> dsk;
c = fo -> ccls;
// Find an empty cluster.
c = FATfindEmptyCluster(fo);
if (c == 0)
// Mark the cluster as used and as the last one in the chain.
FATwrite( dsk, c, LAST_CLUSTER_FAT16);
// Write the cluster’s number in the FAT entry for the FILE structure’s ccls member.
curcls = fo -> ccls;
FATwrite( dsk, curcls, c);
// Set the FILE structure’s ccls member to the new, empty cluster’s number.
fo -> ccls = c;
To prepare to read or write to a file, a host must obtain information about the file from the file’s directory entry. A host might also need to create or delete a file. The functions that follow show how to perform these operations.
Obtaining File Information
The Fill_File_Object function reads information from a file’s directory entry and stores the information in a FILE structure. The function accepts a pointer to a FILE structure (fo) and a pointer to the number of the file’s entry in its directory (fHandle). The function returns a status code. The FILEfind function later in this chapter shows how to find the number of a file’s directory entry.
The function calls the Cache_File_Entry function from Chapter 9. Cache_File_Entry is called with ForceRead false, so in the FILE structure passed to the function, the dsk -> buffer member must contain the sector with the file’s directory entry (unless it’s the first entry in a sector), the dirclus member must contain the number of the first cluster in the file’s directory, and the dirccls member must contain the dirclus value or another directory-cluster number where the code should begin looking for the entry.
#define DIR_DEL 0xe5 // deleted entry
#define DIR_EMPTY 0 // last entry in a directory
#define FOUND 0 // directory entry match
#define NOT_FOUND 1 // directory entry not found
#define NO_MORE 2 // no more files found
byte Fill_File_Object(FILEOBJ fo, word *fHandle)
byte test = 0;
// Get the file’s directory entry.
// Assumes that fo -> dsk -> buffer contains the sector containing the entry to read
// (unless it’s the first entry in a sector).
dir = Cache_File_Entry(fo, fHandle, FALSE);
// Read the first character of the file name from the entry.
a = dir -> DIR_Name;
if (dir == (DIRENTRY)NULL || a == DIR_EMPTY)
status = NO_MORE; // The entry doesn’t exist or is empty.
if ( a == DIR_DEL)
status = NOT_FOUND; // The entry is deleted.
status = FOUND;
// An entry exists. Store the entry’s name in the file structure’s name member.
for (index=0; index < DIR_NAMESIZE; index++)
character = dir -> DIR_Name[index];
fo -> name[test++] = character;
// If the entry has an extension, store it in the file’s structure’s name member.
character = dir -> DIR_Extension;
if (character != ‘ ‘)
for (index = 0; index < DIR_EXTENSION; index++)
character = dir->DIR_Extension[index];
fo -> name[test++] = character;
// Store the passed entry number.
fo -> entry = *fHandle;
// Store the entry’s file size.
fo -> size = (dir -> DIR_FileSize);
// Store the entry’s initial cluster number.
temp = (dir -> DIR_FstClusHI << 16);
temp |= dir -> DIR_FstClusLO;
fo -> cluster = temp;
// Store the entry’s date and time.
fo -> time = (dir -> DIR_WrtTime);
fo -> date = (dir -> DIR_WrtDate);
// Store the entry’s attributes.
a = dir->DIR_Attr;
fo -> attributes = a;
} // End: the entry isn’t deleted
} // End: an entry exists