@@ -47,11 +47,13 @@ typedef struct _FAT_VOLUME_INFO
4747 ULONG RootDirSectors ; /* Number of sectors of the root directory (non-fat32) */
4848 ULONG RootDirStartCluster ; /* Starting cluster number of the root directory (fat32 only) */
4949 ULONG DataSectorStart ; /* Starting sector of the data area */
50+ // ULONG NumberOfClusters; /* Number of clusters of the data area */
5051 ULONG DeviceId ;
52+ ULONG TotalSectors ; /* Total number of sectors on the volume */
5153 UINT16 BytesPerSector ; /* Number of bytes per sector */
52- UINT8 FatType ; /* FAT12, FAT16, FAT32, FATX16 or FATX32 */
53- UINT8 NumberOfFats ; /* Number of FAT tables */
5454 UINT8 SectorsPerCluster ; /* Number of sectors per cluster */
55+ UINT8 NumberOfFats ; /* Number of FAT tables */
56+ UINT8 FatType ; /* FAT12, FAT16, FAT32, FATX16 or FATX32 */
5557} FAT_VOLUME_INFO ;
5658
5759PFAT_VOLUME_INFO FatVolumes [MAX_FDS ];
@@ -134,6 +136,27 @@ VOID FatSwapFatXDirEntry(PFATX_DIRENTRY Obj)
134136 SW (Obj , LastAccessDate );
135137}
136138
139+ /**
140+ * @brief
141+ * Returns the number of clusters of the data area of the FAT volume.
142+ * This value is computed by taking the total sectors on the disk, subtracting
143+ * up to the first file area sector, then dividing by the sectors per cluster count.
144+ *
145+ * @note
146+ * Relies on the FAT_VOLUME_INFO fields already computed by FatOpenVolume().
147+ *
148+ * @see
149+ * https://github.com/reactos/reactos/blob/435482912c6dc0aaa4371e37b7336b2b1291e65f/drivers/filesystems/fastfat/fat.h#L460
150+ * https://github.com/reactos/reactos/blob/435482912c6dc0aaa4371e37b7336b2b1291e65f/drivers/filesystems/vfatfs/fsctl.c#L24
151+ **/
152+ FORCEINLINE
153+ ULONG
154+ FatNumberOfClusters (
155+ _In_ PFAT_VOLUME_INFO Volume )
156+ {
157+ return ((Volume -> TotalSectors - Volume -> DataSectorStart ) / Volume -> SectorsPerCluster );
158+ }
159+
137160BOOLEAN FatOpenVolume (PFAT_VOLUME_INFO Volume , PFAT_BOOTSECTOR BootSector , ULONGLONG PartitionSectorCount )
138161{
139162 char ErrMsg [80 ];
@@ -254,21 +277,38 @@ BOOLEAN FatOpenVolume(PFAT_VOLUME_INFO Volume, PFAT_BOOTSECTOR BootSector, ULONG
254277 return FALSE;
255278 }
256279
257- //
258- // Get the sectors per FAT,
259- // root directory starting sector,
260- // and data sector start
261- //
262280 if (ISFATX (Volume -> FatType ))
263281 {
264- Volume -> BytesPerSector = 512 ;
282+ Volume -> TotalSectors = PartitionSectorCount ;
283+ }
284+ else
285+ {
286+ /*
287+ * After DOS 4.0, at least one of TotalSectors or TotalSectorsBig will be zero.
288+ * In DOS version 3.2 or before, both of these might contain some value,
289+ * because, before 3.2, there was no TotalSectorsBig entry. Thus some disks
290+ * might have an unexpected value in the field, and we will use TotalSectorsBig
291+ * only if TotalSectors equals zero.
292+ */
293+ C_ASSERT (FIELD_OFFSET (FAT_BOOTSECTOR , TotalSectors ) ==
294+ FIELD_OFFSET (FAT32_BOOTSECTOR , TotalSectors ));
295+ C_ASSERT (FIELD_OFFSET (FAT_BOOTSECTOR , TotalSectorsBig ) ==
296+ FIELD_OFFSET (FAT32_BOOTSECTOR , TotalSectorsBig ));
297+ Volume -> TotalSectors = (FatVolumeBootSector -> TotalSectors ? FatVolumeBootSector -> TotalSectors
298+ : FatVolumeBootSector -> TotalSectorsBig );
299+ }
300+
301+ /* Get the sectors per FAT, root directory sector start, and data sector start */
302+ if (ISFATX (Volume -> FatType ))
303+ {
304+ Volume -> BytesPerSector = SECTOR_SIZE ;
265305 Volume -> SectorsPerCluster = SWAPD (FatXVolumeBootSector -> SectorsPerCluster );
266- Volume -> FatSectorStart = ( 0x1000 / Volume -> BytesPerSector ) ;
306+ Volume -> FatSectorStart = 4096 / Volume -> BytesPerSector ;
267307 Volume -> ActiveFatSectorStart = Volume -> FatSectorStart ;
268- Volume -> NumberOfFats = 1 ;
308+ Volume -> NumberOfFats = 1 ; // FatXVolumeBootSector->NumberOfFats;
269309 FatSize = (ULONG )(PartitionSectorCount / Volume -> SectorsPerCluster *
270310 (Volume -> FatType == FATX16 ? 2 : 4 ));
271- Volume -> SectorsPerFat = ROUND_UP (FatSize , 0x1000 ) / Volume -> BytesPerSector ;
311+ Volume -> SectorsPerFat = ROUND_UP (FatSize , 4096 ) / Volume -> BytesPerSector ;
272312
273313 Volume -> RootDirSectorStart = Volume -> FatSectorStart + Volume -> NumberOfFats * Volume -> SectorsPerFat ;
274314 Volume -> RootDirSectors = FatXVolumeBootSector -> SectorsPerCluster ;
@@ -286,6 +326,7 @@ BOOLEAN FatOpenVolume(PFAT_VOLUME_INFO Volume, PFAT_BOOTSECTOR BootSector, ULONG
286326
287327 Volume -> RootDirSectorStart = Volume -> FatSectorStart + Volume -> NumberOfFats * Volume -> SectorsPerFat ;
288328 Volume -> RootDirSectors = ((FatVolumeBootSector -> RootDirEntries * 32 ) + (Volume -> BytesPerSector - 1 )) / Volume -> BytesPerSector ;
329+ // Volume->RootDirSectors = (FatVolumeBootSector->RootDirEntries * sizeof(DIRENT) / Volume->BytesPerSector);
289330
290331 Volume -> DataSectorStart = Volume -> RootDirSectorStart + Volume -> RootDirSectors ;
291332 }
@@ -294,10 +335,12 @@ BOOLEAN FatOpenVolume(PFAT_VOLUME_INFO Volume, PFAT_BOOTSECTOR BootSector, ULONG
294335 Volume -> BytesPerSector = Fat32VolumeBootSector -> BytesPerSector ;
295336 Volume -> SectorsPerCluster = Fat32VolumeBootSector -> SectorsPerCluster ;
296337 Volume -> FatSectorStart = Fat32VolumeBootSector -> ReservedSectors ;
297- Volume -> ActiveFatSectorStart = Volume -> FatSectorStart +
298- ((Fat32VolumeBootSector -> ExtendedFlags & 0x80 ) ? ((Fat32VolumeBootSector -> ExtendedFlags & 0x0f ) * Fat32VolumeBootSector -> SectorsPerFatBig ) : 0 );
338+ Volume -> ActiveFatSectorStart =
339+ Volume -> FatSectorStart + ((Fat32VolumeBootSector -> ExtendedFlags & 0x80 ) ?
340+ ((Fat32VolumeBootSector -> ExtendedFlags & 0x0f ) * Fat32VolumeBootSector -> SectorsPerFatBig ) : 0 );
299341 Volume -> NumberOfFats = Fat32VolumeBootSector -> NumberOfFats ;
300342 Volume -> SectorsPerFat = Fat32VolumeBootSector -> SectorsPerFatBig ;
343+ // Volume->SectorsPerFat = (Fat32VolumeBootSector->SectorsPerFat ? Fat32VolumeBootSector->SectorsPerFat : Fat32VolumeBootSector->SectorsPerFatBig);
301344
302345 Volume -> RootDirStartCluster = Fat32VolumeBootSector -> RootDirStartCluster ;
303346 Volume -> DataSectorStart = Volume -> FatSectorStart + Volume -> NumberOfFats * Volume -> SectorsPerFat ;
@@ -312,6 +355,7 @@ BOOLEAN FatOpenVolume(PFAT_VOLUME_INFO Volume, PFAT_BOOTSECTOR BootSector, ULONG
312355 return FALSE;
313356 }
314357 }
358+ // Volume->NumberOfClusters = FatNumberOfClusters(Volume);
315359
316360 Volume -> FatCacheSize = min (Volume -> SectorsPerFat , FAT_MAX_CACHE_SIZE / Volume -> BytesPerSector );
317361 TRACE ("FAT cache is %d sectors, %d bytes\n" , Volume -> FatCacheSize , Volume -> FatCacheSize * Volume -> BytesPerSector );
@@ -1562,6 +1606,22 @@ ARC_STATUS FatSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
15621606 return ESUCCESS ;
15631607}
15641608
1609+
1610+ /**
1611+ * @brief
1612+ * Returns the size of the FAT volume laid on the storage media device
1613+ * opened via @p DeviceId.
1614+ **/
1615+ ULONGLONG
1616+ FatGetVolumeSize (
1617+ _In_ ULONG DeviceId )
1618+ {
1619+ PFAT_VOLUME_INFO Volume = FatVolumes [DeviceId ];
1620+ ASSERT (Volume );
1621+ return (ULONGLONG )Volume -> TotalSectors * Volume -> BytesPerSector ;
1622+ }
1623+
1624+
15651625const DEVVTBL FatFuncTable =
15661626{
15671627 FatClose ,
@@ -1585,7 +1645,7 @@ const DEVVTBL FatXFuncTable =
15851645const DEVVTBL * FatMount (ULONG DeviceId )
15861646{
15871647 PFAT_VOLUME_INFO Volume ;
1588- UCHAR Buffer [512 ];
1648+ UCHAR Buffer [SECTOR_SIZE ];
15891649 PFAT_BOOTSECTOR BootSector = (PFAT_BOOTSECTOR )Buffer ;
15901650 PFAT32_BOOTSECTOR BootSector32 = (PFAT32_BOOTSECTOR )Buffer ;
15911651 PFATX_BOOTSECTOR BootSectorX = (PFATX_BOOTSECTOR )Buffer ;
0 commit comments