diff --git a/libfat.pnproj b/libfat.pnproj index b505475..ad7ad17 100644 --- a/libfat.pnproj +++ b/libfat.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/source/fatdir.c b/source/fatdir.c index c179e43..52a6fb5 100644 --- a/source/fatdir.c +++ b/source/fatdir.c @@ -1,11 +1,11 @@ /* fatdir.c - - Functions used by the newlib disc stubs to interface with + + Functions used by the newlib disc stubs to interface with this library Copyright (c) 2006 Michael "Chishm" Chisholm - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -48,7 +48,7 @@ int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) { PARTITION* partition = NULL; DIR_ENTRY dirEntry; - + // Get the partition this file is on partition = _FAT_partition_getPartitionFromPath (path); if (partition == NULL) { @@ -73,10 +73,10 @@ int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) { r->_errno = ENOENT; return -1; } - + // Fill in the stat struct _FAT_directory_entryStat (partition, &dirEntry, st); - + _FAT_unlock(&partition->lock); return 0; } @@ -93,7 +93,7 @@ int _FAT_unlink_r (struct _reent *r, const char *path) { uint32_t cluster; bool nextEntry; bool errorOccured = false; - + // Get the partition this directory is on partition = _FAT_partition_getPartitionFromPath (path); if (partition == NULL) { @@ -105,7 +105,7 @@ int _FAT_unlink_r (struct _reent *r, const char *path) { if (partition->readOnly) { r->_errno = EROFS; return -1; - } + } // Move the path pointer to the start of the actual path if (strchr (path, ':') != NULL) { @@ -115,23 +115,23 @@ int _FAT_unlink_r (struct _reent *r, const char *path) { r->_errno = EINVAL; return -1; } - + _FAT_lock(&partition->lock); - + // Search for the file on the disc if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) { _FAT_unlock(&partition->lock); r->_errno = ENOENT; return -1; } - + cluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); - + // If this is a directory, make sure it is empty if (_FAT_directory_isDirectory (&dirEntry)) { nextEntry = _FAT_directory_getFirstEntry (partition, &dirContents, cluster); - + while (nextEntry) { if (!_FAT_directory_isDot (&dirContents)) { // The directory had something in it that isn't a reference to itself or it's parent @@ -156,13 +156,13 @@ int _FAT_unlink_r (struct _reent *r, const char *path) { r->_errno = EIO; errorOccured = true; } - + // Flush any sectors in the disc cache if (!_FAT_cache_flush(partition->cache)) { r->_errno = EIO; errorOccured = true; } - + _FAT_unlock(&partition->lock); if (errorOccured) { return -1; @@ -173,7 +173,7 @@ int _FAT_unlink_r (struct _reent *r, const char *path) { int _FAT_chdir_r (struct _reent *r, const char *path) { PARTITION* partition = NULL; - + // Get the partition this directory is on partition = _FAT_partition_getPartitionFromPath (path); if (partition == NULL) { @@ -189,7 +189,7 @@ int _FAT_chdir_r (struct _reent *r, const char *path) { r->_errno = EINVAL; return -1; } - + _FAT_lock(&partition->lock); // Try changing directory @@ -211,16 +211,16 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { DIR_ENTRY newDirEntry; const char *pathEnd; uint32_t dirCluster; - + // Get the partition this directory is on partition = _FAT_partition_getPartitionFromPath (oldName); if (partition == NULL) { r->_errno = ENODEV; return -1; } - + _FAT_lock(&partition->lock); - + // Make sure the same partition is used for the old and new names if (partition != _FAT_partition_getPartitionFromPath (newName)) { _FAT_unlock(&partition->lock); @@ -233,7 +233,7 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { _FAT_unlock(&partition->lock); r->_errno = EROFS; return -1; - } + } // Move the path pointer to the start of the actual path if (strchr (oldName, ':') != NULL) { @@ -259,7 +259,7 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { r->_errno = ENOENT; return -1; } - + // Make sure there is no existing file / directory with the new name if (_FAT_directory_entryFromPath (partition, &newDirEntry, newName, NULL)) { _FAT_unlock(&partition->lock); @@ -268,7 +268,7 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { } // Create the new file entry - // Get the directory it has to go in + // Get the directory it has to go in pathEnd = strrchr (newName, DIR_SEPARATOR); if (pathEnd == NULL) { // No path was specified @@ -290,24 +290,24 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { // Copy the entry data memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY)); - + // Set the new name strncpy (newDirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); - + // Write the new entry if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) { _FAT_unlock(&partition->lock); r->_errno = ENOSPC; return -1; } - + // Remove the old entry if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) { _FAT_unlock(&partition->lock); r->_errno = EIO; return -1; } - + // Flush any sectors in the disc cache if (!_FAT_cache_flush (partition->cache)) { _FAT_unlock(&partition->lock); @@ -341,27 +341,27 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { r->_errno = EINVAL; return -1; } - + _FAT_lock(&partition->lock); // Search for the file/directory on the disc fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); - + // Make sure it doesn't exist if (fileExists) { _FAT_unlock(&partition->lock); r->_errno = EEXIST; return -1; } - + if (partition->readOnly) { // We can't write to a read-only partition _FAT_unlock(&partition->lock); r->_errno = EROFS; return -1; - } - - // Get the directory it has to go in + } + + // Get the directory it has to go in pathEnd = strrchr (path, DIR_SEPARATOR); if (pathEnd == NULL) { // No path was specified @@ -383,7 +383,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { // Create the entry data strncpy (dirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); - + // Set the creation time and date dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0; u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC()); @@ -391,10 +391,10 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { u16_to_u8array (dirEntry.entryData, DIR_ENTRY_mTime, _FAT_filetime_getTimeFromRTC()); u16_to_u8array (dirEntry.entryData, DIR_ENTRY_mDate, _FAT_filetime_getDateFromRTC()); u16_to_u8array (dirEntry.entryData, DIR_ENTRY_aDate, _FAT_filetime_getDateFromRTC()); - + // Set the directory attribute dirEntry.entryData[DIR_ENTRY_attributes] = ATTRIB_DIR; - + // Get a cluster for the new directory dirCluster = _FAT_fat_linkFreeClusterCleared (partition, CLUSTER_FREE); if (!_FAT_fat_isValidCluster(partition, dirCluster)) { @@ -412,7 +412,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { r->_errno = ENOSPC; return -1; } - + // Create the dot entry within the directory memset (newEntryData, 0, DIR_ENTRY_DATA_SIZE); memset (newEntryData, ' ', 11); @@ -420,12 +420,12 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { newEntryData[DIR_ENTRY_attributes] = ATTRIB_DIR; u16_to_u8array (newEntryData, DIR_ENTRY_cluster, dirCluster); u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, dirCluster >> 16); - + // Write it to the directory, erasing that sector in the process - _FAT_cache_eraseWritePartialSector ( partition->cache, newEntryData, + _FAT_cache_eraseWritePartialSector ( partition->cache, newEntryData, _FAT_fat_clusterToSector (partition, dirCluster), 0, DIR_ENTRY_DATA_SIZE); - - + + // Create the double dot entry within the directory // if ParentDir == Rootdir then ".."" always link to Cluster 0 @@ -437,7 +437,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, parentCluster >> 16); // Write it to the directory - _FAT_cache_writePartialSector ( partition->cache, newEntryData, + _FAT_cache_writePartialSector ( partition->cache, newEntryData, _FAT_fat_clusterToSector (partition, dirCluster), DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); // Flush any sectors in the disc cache @@ -451,7 +451,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { return 0; } -int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) +int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) { PARTITION* partition = NULL; unsigned int freeClusterCount; @@ -465,29 +465,38 @@ int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) _FAT_lock(&partition->lock); - freeClusterCount = _FAT_fat_freeClusterCount (partition); - + if(memcmp(&buf->f_flag, "SCAN", 4) == 0) + { + //Special command was given to sync the numberFreeCluster + _FAT_partition_createFSinfo(partition); + } + + if(partition->filesysType == FS_FAT32) + freeClusterCount = partition->fat.numberFreeCluster; + else + freeClusterCount = _FAT_fat_freeClusterCount (partition); + // FAT clusters = POSIX blocks - buf->f_bsize = partition->bytesPerCluster; // File system block size. - buf->f_frsize = partition->bytesPerCluster; // Fundamental file system block size. - - buf->f_blocks = partition->fat.lastCluster - CLUSTER_FIRST + 1; // Total number of blocks on file system in units of f_frsize. - buf->f_bfree = freeClusterCount; // Total number of free blocks. - buf->f_bavail = freeClusterCount; // Number of free blocks available to non-privileged process. + buf->f_bsize = partition->bytesPerCluster; // File system block size. + buf->f_frsize = partition->bytesPerCluster; // Fundamental file system block size. + + buf->f_blocks = partition->fat.lastCluster - CLUSTER_FIRST + 1; // Total number of blocks on file system in units of f_frsize. + buf->f_bfree = freeClusterCount; // Total number of free blocks. + buf->f_bavail = freeClusterCount; // Number of free blocks available to non-privileged process. // Treat requests for info on inodes as clusters - buf->f_files = partition->fat.lastCluster - CLUSTER_FIRST + 1; // Total number of file serial numbers. - buf->f_ffree = freeClusterCount; // Total number of free file serial numbers. - buf->f_favail = freeClusterCount; // Number of file serial numbers available to non-privileged process. - + buf->f_files = partition->fat.lastCluster - CLUSTER_FIRST + 1; // Total number of file serial numbers. + buf->f_ffree = freeClusterCount; // Total number of free file serial numbers. + buf->f_favail = freeClusterCount; // Number of file serial numbers available to non-privileged process. + // File system ID. 32bit ioType value - buf->f_fsid = _FAT_disc_hostType(partition->disc); - + buf->f_fsid = _FAT_disc_hostType(partition->disc); + // Bit mask of f_flag values. buf->f_flag = ST_NOSUID /* No support for ST_ISUID and ST_ISGID file mode bits */ | (partition->readOnly ? ST_RDONLY /* Read only file system */ : 0 ) ; // Maximum filename length. - buf->f_namemax = MAX_FILENAME_LENGTH; + buf->f_namemax = MAX_FILENAME_LENGTH; _FAT_unlock(&partition->lock); return 0; @@ -497,7 +506,7 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) DIR_ENTRY dirEntry; DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); bool fileExists; - + state->partition = _FAT_partition_getPartitionFromPath (path); if (state->partition == NULL) { r->_errno = ENODEV; @@ -512,18 +521,18 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) r->_errno = EINVAL; return NULL; } - + _FAT_lock(&state->partition->lock); - + // Get the start cluster of the directory fileExists = _FAT_directory_entryFromPath (state->partition, &dirEntry, path, NULL); - + if (!fileExists) { _FAT_unlock(&state->partition->lock); r->_errno = ENOENT; return NULL; } - + // Make sure it is a directory if (! _FAT_directory_isDirectory (&dirEntry)) { _FAT_unlock(&state->partition->lock); @@ -533,11 +542,11 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) // Save the start cluster for use when resetting the directory data state->startCluster = _FAT_directory_entryGetCluster (state->partition, dirEntry.entryData); - + // Get the first entry for use with a call to dirnext - state->validEntry = + state->validEntry = _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); - + // We are now using this entry state->inUse = true; _FAT_unlock(&state->partition->lock); @@ -548,7 +557,7 @@ int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState) { DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); _FAT_lock(&state->partition->lock); - + // Make sure we are still using this entry if (!state->inUse) { _FAT_unlock(&state->partition->lock); @@ -557,7 +566,7 @@ int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState) { } // Get the first entry for use with a call to dirnext - state->validEntry = + state->validEntry = _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); _FAT_unlock(&state->partition->lock); @@ -568,14 +577,14 @@ int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); _FAT_lock(&state->partition->lock); - + // Make sure we are still using this entry if (!state->inUse) { _FAT_unlock(&state->partition->lock); r->_errno = EBADF; return -1; } - + // Make sure there is another file to report on if (! state->validEntry) { _FAT_unlock(&state->partition->lock); @@ -589,9 +598,9 @@ int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct if (filestat != NULL) { _FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat); } - + // Look for the next entry for use next time - state->validEntry = + state->validEntry = _FAT_directory_getNextEntry (state->partition, &(state->currentEntry)); _FAT_unlock(&state->partition->lock); @@ -600,7 +609,7 @@ int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct int _FAT_dirclose_r (struct _reent *r, DIR_ITER *dirState) { DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); - + // We are no longer using this entry _FAT_lock(&state->partition->lock); state->inUse = false; diff --git a/source/file_allocation_table.c b/source/file_allocation_table.c index 7edd7cb..7690209 100644 --- a/source/file_allocation_table.c +++ b/source/file_allocation_table.c @@ -245,6 +245,9 @@ uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster) { } } partition->fat.firstFree = firstFree; + if(partition->fat.numberFreeCluster) + partition->fat.numberFreeCluster--; + partition->fat.numberLastAllocCluster = firstFree; if ((cluster >= CLUSTER_FIRST) && (cluster <= lastCluster)) { @@ -309,6 +312,8 @@ bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster) { // Erase the link _FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE); + if(partition->fat.numberFreeCluster < (partition->numberOfSectors/partition->sectorsPerCluster)) + partition->fat.numberFreeCluster++; // Move onto next cluster cluster = nextCluster; } diff --git a/source/partition.c b/source/partition.c index 8d107c5..d4072cc 100644 --- a/source/partition.c +++ b/source/partition.c @@ -93,7 +93,20 @@ enum BPB { BPB_bootSig_AA = 0x1FF }; +// File system information block offsets +enum FSIB +{ + FSIB_SIG1 = 0x00, + FSIB_SIG2 = 0x1e4, + FSIB_numberOfFreeCluster = 0x1e8, + FSIB_numberLastAllocCluster = 0x1ec, + FSIB_bootSig_55 = 0x1FE, + FSIB_bootSig_AA = 0x1FF +}; + static const char FAT_SIG[3] = {'F', 'A', 'T'}; +static const char FS_INFO_SIG1[4] = {'R', 'R', 'a', 'A'}; +static const char FS_INFO_SIG2[4] = {'r', 'r', 'A', 'a'}; sec_t FindFirstValidPartition(const DISC_INTERFACE* disc) @@ -163,7 +176,7 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { return NULL; } - + // Make sure it is a valid MBR or boot sector if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) { return NULL; @@ -230,10 +243,15 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector; + //FS info sector + partition->fsInfoSector = startSector + (u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) ? u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) : 1); + // Store info about FAT uint32_t clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster; partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1; partition->fat.firstFree = CLUSTER_FIRST; + partition->fat.numberFreeCluster = 0; + partition->fat.numberLastAllocCluster = 0; if (clusterCount < CLUSTERS_PER_FAT12) { partition->filesysType = FS_FAT12; // FAT12 volume @@ -268,6 +286,8 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach partition->openFileCount = 0; partition->firstOpenFile = NULL; + _FAT_partition_readFSinfo(partition); + return partition; } @@ -283,6 +303,9 @@ void _FAT_partition_destructor (PARTITION* partition) { nextFile = nextFile->nextOpenFile; } + // Write out the fs info sector + _FAT_partition_writeFSinfo(partition); + // Free memory used by the cache, writing it to disc at the same time _FAT_cache_destructor (partition->cache); @@ -305,3 +328,77 @@ PARTITION* _FAT_partition_getPartitionFromPath (const char* path) { return (PARTITION*)devops->deviceData; } + +void _FAT_partition_createFSinfo(PARTITION * partition) +{ + if(partition->readOnly || partition->filesysType != FS_FAT32) + return; + + uint8_t sectorBuffer[BYTES_PER_READ]; + memset(sectorBuffer, 0, sizeof(sectorBuffer)); + + int i; + for(i = 0; i < 4; ++i) + { + sectorBuffer[FSIB_SIG1+i] = FS_INFO_SIG1[i]; + sectorBuffer[FSIB_SIG2+i] = FS_INFO_SIG2[i]; + } + + partition->fat.numberFreeCluster = _FAT_fat_freeClusterCount(partition); + u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster); + u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster); + + sectorBuffer[FSIB_bootSig_55] = 0x55; + sectorBuffer[FSIB_bootSig_AA] = 0xAA; + + _FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer); +} + +void _FAT_partition_readFSinfo(PARTITION * partition) +{ + if(partition->filesysType != FS_FAT32) + return; + + uint8_t sectorBuffer[BYTES_PER_READ] = {0}; + + // Read first sector of disc + if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) { + return; + } + + if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) != 0 || + memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4) != 0 || + u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster) == 0) + { + //sector does not yet exist, create one! + _FAT_partition_createFSinfo(partition); + return; + } + + partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster); + partition->fat.numberLastAllocCluster = u8array_to_u32(sectorBuffer, FSIB_numberLastAllocCluster); +} + +void _FAT_partition_writeFSinfo(PARTITION * partition) +{ + if(partition->filesysType != FS_FAT32) + return; + + uint8_t sectorBuffer[BYTES_PER_READ] = {0}; + + // Read first sector of disc + if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) { + return; + } + + if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) || memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4)) + return; + + u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster); + u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster); + + // Read first sector of disc + if (!_FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) { + return; + } +} diff --git a/source/partition.h b/source/partition.h index 52e6648..b8ad0b1 100644 --- a/source/partition.h +++ b/source/partition.h @@ -4,7 +4,7 @@ on various block devices. Copyright (c) 2006 Michael "Chishm" Chisholm - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -45,6 +45,8 @@ typedef struct { uint32_t sectorsPerFat; uint32_t lastCluster; uint32_t firstFree; + uint32_t numberFreeCluster; + uint32_t numberLastAllocCluster; } FAT; typedef struct { @@ -60,6 +62,7 @@ typedef struct { uint32_t bytesPerSector; uint32_t sectorsPerCluster; uint32_t bytesPerCluster; + uint32_t fsInfoSector; FAT fat; // Values that may change after construction uint32_t cwdCluster; // Current working directory cluster @@ -76,7 +79,7 @@ Mount the supplied device and return a pointer to the struct necessary to use it PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t SectorsPerPage, sec_t startSector); /* -Dismount the device and free all structures used. +Dismount the device and free all structures used. Will also attempt to synchronise all open files to disc. */ void _FAT_partition_destructor (PARTITION* partition); @@ -86,4 +89,19 @@ Return the partition specified in a path, as taken from the devoptab. */ PARTITION* _FAT_partition_getPartitionFromPath (const char* path); +/* +Create the fs info sector. +*/ +void _FAT_partition_createFSinfo(PARTITION * partition); + +/* +Read the fs info sector data. +*/ +void _FAT_partition_readFSinfo(PARTITION * partition); + +/* +Write the fs info sector data. +*/ +void _FAT_partition_writeFSinfo(PARTITION * partition); + #endif // _PARTITION_H