Skip to content

Commit d7bace7

Browse files
committed
Fix for write failures and incorrect free space on FAT32 volume with missing info sector
1 parent ee51afc commit d7bace7

File tree

1 file changed

+85
-13
lines changed

1 file changed

+85
-13
lines changed

source/rtl/ultibo/core/fatfs.pas

Lines changed: 85 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ TFATFileSystem = class(TFileSystem)
548548
function SetVolumeFlags(AFlags:LongWord):Boolean;
549549

550550
{Sector Methods}
551+
function CheckInfoSector(ALock:Boolean;var ABuffer):Boolean;
551552
function UpdateInfoSector:Boolean;
552553

553554
{Cluster Methods}
@@ -2772,6 +2773,70 @@ function TFATFileSystem.SetVolumeFlags(AFlags:LongWord):Boolean;
27722773

27732774
{==============================================================================}
27742775

2776+
function TFATFileSystem.CheckInfoSector(ALock:Boolean;var ABuffer):Boolean;
2777+
{Check the FAT32 Info Sector for valid values}
2778+
{Note: Caller must hold any required lock on buffer}
2779+
var
2780+
Buffer:Pointer;
2781+
begin
2782+
{}
2783+
Result:=False;
2784+
2785+
{Check Type}
2786+
case FFATType of
2787+
ftFAT12,ftFAT16:begin
2788+
Result:=True;
2789+
end;
2790+
ftFAT32:begin
2791+
{Get Buffer}
2792+
Buffer:=@ABuffer;
2793+
2794+
{Check Buffer}
2795+
if (PFATInfoSector(Buffer).LeadSignature <> fat32LeadSignature) or
2796+
(PFATInfoSector(Buffer).StructureSignature <> fat32StructSignature) or
2797+
(PFATInfoSector(Buffer).TrailSignature <> fat32TrailSignature) then
2798+
begin
2799+
if ALock and not(InfoLock) then Exit;
2800+
try
2801+
{$IFDEF FAT_DEBUG}
2802+
if FILESYS_LOG_ENABLED then FileSysLogDebug('TFATFileSystem.CheckInfoSector - Initializing Info Sector');
2803+
{$ENDIF}
2804+
2805+
{Initialize Info Sector}
2806+
PFATInfoSector(Buffer).LeadSignature:=fat32LeadSignature;
2807+
{PFATInfoSector(Buffer).Reserved1}
2808+
PFATInfoSector(Buffer).StructureSignature:=fat32StructSignature;
2809+
PFATInfoSector(Buffer).FreeClusterCount:=fatUnknownCluster;
2810+
PFATInfoSector(Buffer).LastFreeCluster:=fatUnknownCluster;
2811+
{PFATInfoSector(Buffer).Reserved2}
2812+
PFATInfoSector(Buffer).TrailSignature:=fat32TrailSignature;
2813+
2814+
{Check ReadOnly}
2815+
if not FReadOnly then
2816+
begin
2817+
{$IFDEF FAT_DEBUG}
2818+
if FILESYS_LOG_ENABLED then FileSysLogDebug('TFATFileSystem.CheckInfoSector - Writing Info Sector');
2819+
{$ENDIF}
2820+
2821+
{Write Info Sector}
2822+
if not WriteSectors(FInfoSector,1,Buffer^) then Exit;
2823+
end;
2824+
2825+
{$IFDEF FAT_DEBUG}
2826+
if FILESYS_LOG_ENABLED then FileSysLogDebug('TFATFileSystem.CheckInfoSector - Info Sector Initialized');
2827+
{$ENDIF}
2828+
finally
2829+
if ALock then InfoUnlock;
2830+
end;
2831+
end;
2832+
2833+
Result:=True;
2834+
end;
2835+
end;
2836+
end;
2837+
2838+
{==============================================================================}
2839+
27752840
function TFATFileSystem.UpdateInfoSector:Boolean;
27762841
{Update the FAT32 Info Sector with current values}
27772842
begin
@@ -2803,6 +2868,9 @@ function TFATFileSystem.UpdateInfoSector:Boolean;
28032868

28042869
{Read Info Sector}
28052870
if not ReadSectors(FInfoSector,1,FInfoBuffer^) then Exit;
2871+
2872+
{Check Info Sector}
2873+
if not CheckInfoSector(False,FInfoBuffer^) then Exit;
28062874
end;
28072875

28082876
{Check Enable}
@@ -2973,9 +3041,11 @@ function TFATFileSystem.GetNextFreeCluster:LongWord;
29733041

29743042
{Get Info Sector}
29753043
if not ReadSectors(FInfoSector,1,FSectorBuffer^) then Exit;
2976-
if PFATInfoSector(FSectorBuffer).LeadSignature <> fat32LeadSignature then Exit;
2977-
if PFATInfoSector(FSectorBuffer).StructureSignature <> fat32StructSignature then Exit;
2978-
if PFATInfoSector(FSectorBuffer).TrailSignature <> fat32TrailSignature then Exit;
3044+
3045+
{Check Info Sector}
3046+
if not CheckInfoSector(True,FSectorBuffer^) then Exit;
3047+
3048+
{Check Last Free Cluster}
29793049
if PFATInfoSector(FSectorBuffer).LastFreeCluster <> fatUnknownCluster then
29803050
begin
29813051
{Get Last Free Cluster}
@@ -3105,7 +3175,7 @@ function TFATFileSystem.GetFreeClusterCount:LongWord;
31053175
DiskBlock:TFATDiskBlock;
31063176
begin
31073177
{}
3108-
Result:=0;
3178+
Result:=fatUnknownCluster;
31093179

31103180
if FDriver = nil then Exit;
31113181
if FTotalClusterCount = 0 then Exit;
@@ -3129,9 +3199,11 @@ function TFATFileSystem.GetFreeClusterCount:LongWord;
31293199

31303200
{Get Info Sector}
31313201
if not ReadSectors(FInfoSector,1,FSectorBuffer^) then Exit;
3132-
if PFATInfoSector(FSectorBuffer).LeadSignature <> fat32LeadSignature then Exit;
3133-
if PFATInfoSector(FSectorBuffer).StructureSignature <> fat32StructSignature then Exit;
3134-
if PFATInfoSector(FSectorBuffer).TrailSignature <> fat32TrailSignature then Exit;
3202+
3203+
{Check Info Sector}
3204+
if not CheckInfoSector(True,FSectorBuffer^) then Exit;
3205+
3206+
{Check Free Cluster Count}
31353207
if PFATInfoSector(FSectorBuffer).FreeClusterCount <> fatUnknownCluster then
31363208
begin
31373209
{Get Free Cluster Count}
@@ -3260,9 +3332,9 @@ function TFATFileSystem.SetNextFreeCluster(ACluster:LongWord):Boolean;
32603332

32613333
{Get Info Sector}
32623334
if not ReadSectors(FInfoSector,1,FSectorBuffer^) then Exit;
3263-
if PFATInfoSector(FSectorBuffer).LeadSignature <> fat32LeadSignature then Exit;
3264-
if PFATInfoSector(FSectorBuffer).StructureSignature <> fat32StructSignature then Exit;
3265-
if PFATInfoSector(FSectorBuffer).TrailSignature <> fat32TrailSignature then Exit;
3335+
3336+
{Check Info Sector}
3337+
if not CheckInfoSector(True,FSectorBuffer^) then Exit;
32663338

32673339
{Set Last Free Cluster}
32683340
PFATInfoSector(FSectorBuffer).LastFreeCluster:=ACluster;
@@ -3301,9 +3373,9 @@ function TFATFileSystem.SetFreeClusterCount(ACount:LongWord):Boolean;
33013373

33023374
{Get Info Sector}
33033375
if not ReadSectors(FInfoSector,1,FSectorBuffer^) then Exit;
3304-
if PFATInfoSector(FSectorBuffer).LeadSignature <> fat32LeadSignature then Exit;
3305-
if PFATInfoSector(FSectorBuffer).StructureSignature <> fat32StructSignature then Exit;
3306-
if PFATInfoSector(FSectorBuffer).TrailSignature <> fat32TrailSignature then Exit;
3376+
3377+
{Check Info Sector}
3378+
if not CheckInfoSector(True,FSectorBuffer^) then Exit;
33073379

33083380
{Set Free Cluster Count}
33093381
PFATInfoSector(FSectorBuffer).FreeClusterCount:=ACount;

0 commit comments

Comments
 (0)