#ifndef _FAT32_H #define _FAT32_H #define FAT32EOF 0x0FFFFFF8 // The little endian of 0x0ffffff8 #define SHA1EMPTY "da39a3ee5e6b4b0d3255bfef95601890afd80709" // SHA1 hash of an empty file #pragma pack(push, 1) typedef struct BootEntry { // The structure for a FAT32 boot entry unsigned char BS_jmpBoot[3]; // Assembly instruction to jump to boot code unsigned char BS_OEMName[8]; // OEM Name in ASCII unsigned short BPB_BytsPerSec; // Bytes per sector, allowed values include 512, 1024, 2048, and 4096 unsigned char BPB_SecPerClus; // Sectors per cluster (data unit), allowed values are powers of 2, but the cluster size must be 32KB or smaller unsigned short BPB_RsvdSecCnt; // Size in sectors of the reserved area unsigned char BPB_NumFATs; // Number of FATs unsigned short BPB_RootEntCnt; // Maximum number of files in the root directory for FAT12 and FAT16. This is 0 for FAT32 unsigned short BPB_TotSec16; // 16-bit value of number of sectors in file system unsigned char BPB_Media; // Media type unsigned short BPB_FATSz16; // 16-bit size in sectors of each FAT for FAT12 and FAT16. For FAT32, this field is 0 unsigned short BPB_SecPerTrk; // Sectors per track of storage device unsigned short BPB_NumHeads; // Number of heads in storage device unsigned int BPB_HiddSec; // Number of sectors before the start of partition unsigned int BPB_TotSec32; // 32-bit value of number of sectors in file system, either this value or the 16-bit value above must be 0 unsigned int BPB_FATSz32; // 32-bit size in sectors of one FAT unsigned short BPB_ExtFlags; // A flag for FAT unsigned short BPB_FSVer; // The major and minor version number unsigned int BPB_RootClus; // Cluster where the root directory can be found unsigned short BPB_FSInfo; // Sector where FSINFO structure can be found unsigned short BPB_BkBootSec; // Sector where backup copy of boot sector is located unsigned char BPB_Reserved[12]; // Reserved unsigned char BS_DrvNum; // BIOS INT13h drive number unsigned char BS_Reserved1; // Not used unsigned char BS_BootSig; // Extended boot signature to identify if the next three values are valid unsigned int BS_VolID; // Volume serial number unsigned char BS_VolLab[11]; // Volume label in ASCII, user defines when creating the file system unsigned char BS_FilSysType[8]; // File system type label in ASCII } BootEntry; #pragma pack(pop) #pragma pack(push, 1) typedef struct DirEntry { // The structure for a FAT32 directory entry unsigned char DIR_Name[11]; // File name unsigned char DIR_Attr; // File attributes unsigned char DIR_NTRes; // Reserved unsigned char DIR_CrtTimeTenth; // Created time (tenths of second) unsigned short DIR_CrtTime; // Created time (hours, minutes, seconds) unsigned short DIR_CrtDate; // Created day unsigned short DIR_LstAccDate; // Accessed day unsigned short DIR_FstClusHI; // High 2 bytes of the first cluster address unsigned short DIR_WrtTime; // Written time (hours, minutes, seconds) unsigned short DIR_WrtDate; // Written day unsigned short DIR_FstClusLO; // Low 2 bytes of the first cluster address unsigned int DIR_FileSize; // File size in bytes (0 for directories) } DirEntry; #pragma pack(pop) /** * This function prints the information of the file system based on the given boot entry. * The information includes the number of FATs, the number of bytes per sector, * the number of sectors per cluster, and the number of reserved sectors. * * Input: * bootEntry The pointer to the boot entry to extract information. * * Return: * None. * **/ void printFsInfo(BootEntry *bootEntry); /** * This function returns a readable format of the file/directory name. * If the directory entry specifies a file, then the format will be "<name>.<extension>" or "<name>". * Note that a file name cannot have the main part, though this function supports that in the format ".<extension>". * If the directory entry specifies a file container (i.e., another directory), then the format will be "<dirname>/". * **THE RETURNED POINTER IS LOCATED ON THE HEAP AND NEEDS TO BE FREED!** * * Input: * dirEntry The pointer to the directory entry to extract information. * * Return: * None. * **/ char *formattedDirName(DirEntry *dirEntry); /** * This function prints the information of the a directory entry based on the given structure. * The information includes the name (and extension) of the file/directory, the size, and the starting cluster. * * Input: * dirEntry The pointer to the directory entry to extract information. * * Return: * 0 on success, -1 on failure, meaning that the directory entry has a long file name or is freed * **/ int printDirInfo(DirEntry *dirEntry); /** * This function finds the directory entry index of the specified contiguously allocated deleted file. * If SHA1 hash of the file content is specified, then it also checked if the content hash matches. * If such a deleted file is not found, then it returns -1. * If multiple targets are found (only when sCode is NULL), then it returns -2. * * Input: * dirEntry The pointer to the directory entry to extract information. * sCode The pointer to the SHA1 hash of the contiguously allocated file contents. * disk The pointer to the memory map of the FAT32 disk file. * bootEntry The pointer to the boot entry of the disk. * rootDirEntries The pointer to the array of the root directory entries. * dirEntryCount The number of the root directory entries * * Return: * The directory entry index of the specified deleted file, which is non-negative. * -1 stands for not found, and -2 stands for multiple targets (only when sCode is NULL). * **/ int delContEntryIndex(char *fileName, char *sCode, char *disk, BootEntry *bootEntry, DirEntry **rootDirEntries, int dirEntryCount); /** * This function finds the clusters in order of the specified possibly non-contiguously allocated deleted file. * It applies a brute force search among all permutations of a certain number of clusters (determined by the file size), * assuming that the file appears only in the first 20 clusters in the data area (i.e., Cluster 2~21). * If no such combination matches the specified SHA1 hash, then it returns -1. * Otherwise, it updates the target cluster array, with each cluster in the [2, 22) range, * and returns the number of clusters that are occupied. * The first element in the target cluster array represents the number of clusters that the directory entry occupies. * * Input: * dirEntry The pointer to the directory entry to extract information. * sCode The pointer to the SHA1 hash of the possibly non-contiguously allocated file contents. * disk The pointer to the memory map of the FAT32 disk file. * bootEntry The pointer to the boot entry of the disk. * rootDirEntries The pointer to the array of the root directory entries. * dirEntryCount The number of the root directory entries. * targetClusters The array for storing the target clusters in order and their count. * It must be initialized with size 6 (the count and at most 5 clusters). * * Return: * The directory entry index of the specified deleted file, which is non-negative. * -1 stands for not found. * **/ int delNonContClusters(char *fileName, char *sCode, char *disk, BootEntry *bootEntry, DirEntry **rootDirEntries, int dirEntryCount, unsigned int *targetClusters); /** * This function follows the FAT and returns the corresponding position in the data area. * It can also update the cluster pointer to the next cluster address specified by the first FAT in the disk, * if the mode is specified as 1. Mode 1 is **NOT** recommended if the pointer is directly from the FAT structure. * Any value >= 0x0ffffff8 can be considered as EOF. * * Input: * bootEntry The pointer to the boot entry of the disk. * cluster The pointer to the cluster to follow the FAT. * disk The pointer to the memory map of the FAT32 disk file. * mode The mode whether to update the cluster pointer to the next cluster address. * 0 stands for do-not-update, and 1 stands for update. * * Return: * The corresponding position of the cluster pointer in the data area. * **/ unsigned long followFAT(BootEntry *bootEntry, unsigned int *cluster, char *disk, int mode); /** * This function updates all FATs with the specified directory entry and next cluster address to update. * It directly updates the memory map of the FAT32 disk file. * * Input: * bootEntry The pointer to the boot entry of the disk. * cluster The cluster to update the FATs. * disk The pointer to the memory map of the FAT32 disk file. * DIR_NextClus The address of the next cluster used for updating. * * Return: * None. * **/ void updateFATs(BootEntry *bootEntry, unsigned int cluster, char *disk, unsigned int DIR_NextClus); #endif