📄 diskfs.pas
字号:
item.cluster:=0;
item.sector:=0;
item.name:='Searched';
item.expanded:=false;
item.flags:=0;
item.drive:=self;
item.children:=TList.create;
RootDirSearched:=item;
end;
{ Calculate Logical Drive Information from Boot Sector }
function TFATdrive.CalcDriveInfo(pbs: PBootSec; quiet: boolean): boolean;
var
res: boolean;
i: longword;
maxclus: longword;
value: longword;
quick_formatted: boolean;
begin
res:=true;
try
with pbootsec32(pbs)^ do
begin
{ Determine count of sectors occupied by the root directory... }
RootDirSectors:=((BPB_RootEntCnt * 32) + (BPB_BytesPSec - 1)) div BPB_BytesPSec;
if (BPB_FATsz16 <> 0) then
FATsz:=BPB_FATsz16
else
FATsz:=BPB_FATsz32;
{ Determine count of sectors occupied by all FATs... }
FATSectors:=FATsz * BPB_NumFATs;
{ Compute start of data region, the first sector of cluster 2... }
FirstDataSector := BPB_RsvdSecCnt + (BPB_NumFATs * FATsz) + RootDirSectors;
if (BPB_TotSec16 <> 0) then
TotSec:=BPB_TotSec16
else
TotSec:=BPB_TotSec32;
{ Determine count of data sectors }
TotDataSec:=TotSec - FirstDataSector;
{ Determine count of clusters ... }
CountofClusters:=TotDataSec div BPB_SecPerClus;
{ FAT type detection... }
if CountofClusters < 4085 then
FATtype:=FAT12
else if CountofClusters < 65525 then
FATtype:=FAT16
else FATtype:=FAT32;
{ Calculate Bytes per Cluster... }
BytePerClus:=BPB_BytesPSec * BPB_SecPerClus;
if (NOT quiet) AND (BytePerClus > 32768) then
messagebox(0, pchar('bad parameter in boot sector: bytes per sector ('+Inttostr(BytePerClus)+') > 32768 !'),
'Information', mb_iconinformation + mb_ok);
if FATtype = FAT32 then
begin
if (NOT quiet) AND (BPB_RootClus > countofclusters) then
messagebox(0, pchar('bad parameter in boot sector: root directory cluster ('+Inttostr(BPB_RootClus)+') > count of clusters !'),
'Information', mb_iconinformation + mb_ok)
else if (NOT quiet) AND (BPB_RootClus < 2) then
messagebox(0, pchar('bad parameter in boot sector: root directory cluster ('+Inttostr(BPB_RootClus)+') < 2 !'),
'Information', mb_iconinformation + mb_ok);
FirstRootDirSecNum:=FirstDataSector + longword(BPB_RootClus-2) * longword(BPB_SecPerClus); // -> sometimes Integer Overflow!!
end
else
FirstRootDirSecNum:=BPB_RsvdSecCnt + (BPB_NumFATs * FATsz);
if FATType = FAT32 then RootClus:=BPB_RootClus
else RootClus:=0;
FFATsec:=0;
FWorkSec:=0;
FDataSec:=0;
useFAT:=1;
if FATtype = fat32 then name:=bs32_vollab
else name:=pbootsec(@BootSec)^.bs_vollab;
// determine the drive's condition (if it is quick-formatted, etc.) ...
quick_formatted:=TRUE;
maxclus:=16;
if maxclus > CountOfClusters+1 then maxclus:=CountOfClusters+1;
for i:=2 to maxclus do
begin
value:=GetFAT(i, 0);
if value <> RootClus then
begin
if (FfatAnalyser.ClusterType(FATtype, value) = clusUsed) then
begin
quick_formatted:=FALSE;
break;
end;
end;
end;
if quick_formatted then
begin
condition:=condition OR drv_cond_quickformatted;
useFAT:=0;
end;
end;
except
else
if NOT quiet then
messagebox(0, 'Bad parameters for calculating logical drive information from Boot Sector', 'Error', mb_iconinformation + mb_ok);
res:=false;
end;
result:=res;
end;
{-----------------------------------------------------------------------------}
{ ------ FAT manipulaton functions -------------------------------------------}
{-----------------------------------------------------------------------------}
{ Obtain next link number from FAT (12/16/32), FATno: 0=first FAT, 1=2nd FAT, ...}
{ Note: the CountofClusters value is exactly the count of data clusters starting at cluster 2.
The maximum valid cluster number for the volume is CountofClusters + 1, and the "count of clusters including the two reserved
clusters" is CountofClusters + 2. }
function TFATdrive.GetFAT(N: longword; FATno: byte): longword;
var
nextentry, sector, byteoffset: word;
i: word;
value: longword;
FATOffset: longword;
nFATSec: longword;
EntOffset: word;
begin
try
with bootsec do
begin
if (N < 2) OR (N > countofclusters+1) then
begin
Debug(format('GetFAT error, wrong parameter: N %d (valid range is 2-%d)',
[N, Countofclusters+1]), debugHigh);
result:=0;
exit;
end;
if Fattype = FAT16 then
FATOffset:=N*2
else if FATtype = FAT32 then
FATOffset:=N*4
else if FATtype = FAT12 then
FATOffset:=N+(N div 2);
nFATSec:=BPB_RsvdSecCnt + (FATno * FATsz) + (FATOffset div BPB_BytesPSec);
if FFATsec <> nFatSec then
begin
ReadSec(nFATsec, 1, @FFATSecBuf, true);
FFATsec:=nFATsec;
end;
EntOffset:=FATOffset MOD BPB_BytesPSec;
if (FATtype = FAT12) AND (EntOffset = BPB_BytesPSec - 1) then
begin
{ avoid sector boundary }
ReadSec(nFATsec+1, 1, @FFATSecBuf[512], true);
end;
{ FAT sector has been read now... }
if FATtype = FAT16 then
value:=word(addr(FFATSecBuf[EntOffset])^)
else if FATtype = FAT32 then
value:=longword(addr(FFATSecBuf[EntOffset])^) and $0fffffff
else if FATtype = FAT12 then
begin
value:=word(addr(FFatSecBuf[EntOffset])^);
if (N AND 1 <> 0) then
value:=value SHR 4
else value:=value and $0fff;
end;
GetFAT:=value;
end;
except
else GetFAT:=0;
end;
end;
{ Get cluster mask for special cluster type (bad, end of file or used) }
function TFATdrive.GetClusterMask(clustype: byte): longword;
var
mask: longword;
begin
if clustype = clusFree then mask:=0;
begin
case FATtype of
FAT12: begin
if clustype = clusEOF then mask:=$0fff
else if clustype = clusBad then mask:=$0ff7;
end;
FAT16: begin
if clustype = clusEOF then mask:=$ffff
else if clustype = clusBad then mask:=$fff7;
end;
FAT32: begin
if clustype = clusEOF then mask:=$0fffffff
else if clustype = clusBad then mask := $0ffffff7;
end;
end;
end;
GetClusterMask:=mask;
end;
{ checks a cluster value for EOC (End Of Clusterchain) }
function TFATdrive.IsEOF(value: longword): boolean;
var
res: boolean;
begin
res:=false;
if (FATtype=FAT12) AND (value >= $0ff8) then res:=true
else if (FATtype=FAT16) AND (value >=$fff8) then res:=true
else if (FATtype=FAT32) AND (value >= $0ffffff8) then res:=true;
IsEOF:=res;
end;
function TFATdrive.Sec2Cluster(sec: longword): longword;
begin
with BootSec do
Sec2Cluster:=(sec-FirstDataSector) div BPB_SecPerClus+2;
end;
{ sector paramter is only used if cluster=0 (for FAT12/16) }
function TFATdrive.ReadDataSec(var cluster: longword; var sector: longword; var clussec: word; xferbuf: pointer): boolean;
var
recsec: longword;
res: boolean;
secentry: word;
begin
try
res:=true;
if (cluster > countofclusters+1) then
begin
Debug(format('ReadDataSec error, wrong parameter: cluster %d (valid range is 0-%d)',
[cluster, countofclusters+1]), debugHigh);
res:=false;
end;
if (res) then
begin
with BootSec do
begin
if cluster = 0 then { use sector paramter ? }
begin
if clussec > 0 then { read next sector ? }
begin
clussec:=0;
inc(sector);
end;
recsec:=sector;
end
else begin { none root }
if clussec >= BPB_SecPerClus then { n鋍hsten Cluster laden? }
begin
if useFAT > 0 then cluster:=GetFAT(cluster, useFAT-1)
else inc(cluster);
if IsEOF(cluster) then res:=false { EndOfDir! }
else begin
clussec:=0;
end;
end;
if res then recsec:=cluster2sec(cluster) + clussec;
end;
if res then
begin
if FWorkSec <> recsec then
begin
ReadSec(recsec, 1, @FworkSecBuf, true);
FWorkSec:=recsec;
end;
move(Fworksecbuf[0], xferbuf^, BPB_BytesPSec);
inc(clussec);
end;
end;
end;
result:=res;
except
else result:=false;
end;
end;
{ sector paramter is only used if cluster=0 (for FAT12/16) }
function TFATdrive.GetNextRecord(var cluster: longword; var sector: longword; var recno: word; xferbuf: pointer): boolean;
var
recsec: longword;
res: boolean;
secentry: word;
begin
try
res:=true;
if (cluster > countofclusters+1) then
begin
Debug(format('GetNextRecord error, wrong parameter: cluster %d (valid range is 0-%d)',
[cluster, countofclusters+1]), debugHigh);
res:=false;
end;
if (res) then
begin
with BootSec do
begin
if cluster = 0 then { use sector paramter ? }
begin
if recno >= (BPB_BytesPSec div 32) then { read next sector ? }
begin
recno:=0; inc(sector);
end;
recsec:=sector + (recno*32 div BPB_BytesPSec);
end
else begin { none root }
{writeln('recno: ',recno, ' sec: ',recsec);}
if recno >= (BytePerClus div 32) then { n鋍hsten Cluster laden? }
begin
{write('getnxtrec cluster:',cluster);}
if useFAT > 0 then cluster:=GetFAT(cluster, useFAT-1)
else inc(cluster);
{writeln('getnxtrec getfatcluster:',cluster);
if iseof(cluster) then writeln('iseof!');
readkey;}
if IsEOF(cluster) then res:=false { EndOfDir! }
else begin
{write('curr cluster is: ',cluster, ' next cluster is: ');
writeln(cluster);
readkey;}
recno:=0;
end;
end;
if res then recsec:=cluster2sec(cluster)+(recno*32 div BPB_BytesPSec);
end;
if res then
begin
if FWorkSec <> recsec then
begin
{writeln('neue sec:',recsec);}
ReadSec(recsec, 1, @FworkSecBuf, true);
FWorkSec:=recsec;
end;
secentry:=recno mod (BPB_BytesPSec div 32);
move(Fworksecbuf[secentry*32], xferbuf^, 32);
inc(recno);
end;
end;
end;
GetNextRecord:=res;
except
else GetNextRecord:=false;
end;
end;
{ ermittelt langen Dateinamen an aktueller Position und gibt zugeh鰎igen kurzen Dateieintrag
(DirEntry) zur點k }
function TFATdrive.GetLongName(var cluster: longword; var recsec: longword; var recno: word;
entry: PDirEntry; var longname: string): boolean;
var
oldcluster: longword;
oldrecno: longword;
chksum, sum: byte;
res: boolean;
slotno: byte;
N: byte;
uname: array[0..255] of word;
len: byte;
p: byte;
lnentry: Tdirentry;
i: integer;
multibytebuf: array[0..510] of byte;
begin
res:=true;
with PLnDirEntry(entry)^ do
begin
if (DIR_Attr = $0f) AND (DIR_First = 0) AND (DIR_sig AND $40=$40) then
begin
{ ---- long name dir entry found ------- }
//N:=DIR_Sig AND (NOT $40);
N:=18; // maximum is slotno=18
slotno:=N; p:=N*13; len:=0;
chksum:=DIR_chksum;
{ ---- check for valid long name entry... ------- }
while (DIR_attr = $0f) AND (DIR_first = 0) {AND (DIR_Sig AND (NOT $40)=slotno)}
AND (slotno > 0) AND (DIR_chksum = chksum) do
begin
if p >= 13 then dec(p,13);
inc(len,13);
move(DIR_LName1, uname[p+0], 10);
move(DIR_LName2, uname[p+5], 12);
move(DIR_LName3, uname[p+11], 4);
dec(slotno);
{ ----- get next directory record .... ------- }
if slotno > 0 then res:=GetNextRecord(cluster, recsec, recno, entry);
end;
{ ------- long filename is build - get following short -------- }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -