https://git.reactos.org/?p=reactos.git;a=commitdiff;h=220bc820eb888455c8d8d…
commit 220bc820eb888455c8d8d554962c273f5f602188
Author: Victor Perevertkin <victor(a)perevertkin.ru>
AuthorDate: Fri Jul 19 02:57:11 2019 +0300
Commit: Victor Perevertkin <victor(a)perevertkin.ru>
CommitDate: Sun Sep 29 13:24:31 2019 +0300
[FREELDR] Optimize and refactor the FAT driver.
Do not read the whole cluster chain for file on opening.
This removes restriction for opening files which span
within a large amount of clusters (>65k). That happened because
FrLdrTempAlloc cannot allocate more than about 256 KiB of memory.
Adjacent clusters for file are now read using one disk driver call.
---
boot/freeldr/freeldr/include/fs/fat.h | 7 +-
boot/freeldr/freeldr/lib/fs/fat.c | 319 ++++++++++++++++------------------
2 files changed, 150 insertions(+), 176 deletions(-)
diff --git a/boot/freeldr/freeldr/include/fs/fat.h
b/boot/freeldr/freeldr/include/fs/fat.h
index 7117cb2bad8..85e2998ecb8 100644
--- a/boot/freeldr/freeldr/include/fs/fat.h
+++ b/boot/freeldr/freeldr/include/fs/fat.h
@@ -147,11 +147,12 @@ typedef struct _FAT_VOLUME_INFO *PFAT_VOLUME_INFO;
typedef struct
{
- UCHAR Attributes; /* File attributes */
+ PFAT_VOLUME_INFO Volume;
ULONG FileSize; /* File size */
ULONG FilePointer; /* File pointer */
- ULONG* FileFatChain; /* File fat chain array */
- PFAT_VOLUME_INFO Volume;
+ ULONG CurrentCluster; /* The cluster for file pointer */
+ ULONG StartCluster; /* The first cluster for file */
+ UCHAR Attributes; /* File attributes */
} FAT_FILE_INFO, * PFAT_FILE_INFO;
#define ATTR_NORMAL 0x00
diff --git a/boot/freeldr/freeldr/lib/fs/fat.c b/boot/freeldr/freeldr/lib/fs/fat.c
index b973a64dd70..35233c414b5 100644
--- a/boot/freeldr/freeldr/lib/fs/fat.c
+++ b/boot/freeldr/freeldr/lib/fs/fat.c
@@ -1,21 +1,10 @@
/*
- * FreeLoader
- * Copyright (C) 1998-2003 Brian Palmer <brianp(a)sginet.com>
- * Copyright (C) 2009 Herv� Poussineau
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * PROJECT: FreeLoader
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: FAT filesystem driver for FreeLoader
+ * COPYRIGHT: Copyright 1998-2003 Brian Palmer (brianp(a)sginet.com)
+ * Copyright 2009 Herv� Poussineau
+ * Copyright 2019 Victor Perevertkin (victor.perevertkin(a)reactos.org)
*/
#include <freeldr.h>
@@ -28,13 +17,17 @@ PVOID FatBufferDirectory(PFAT_VOLUME_INFO Volume, ULONG
DirectoryStartCluster
BOOLEAN FatSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID
DirectoryBuffer, ULONG EntryCount, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer);
ARC_STATUS FatLookupFile(PFAT_VOLUME_INFO Volume, PCSTR FileName, PFAT_FILE_INFO
FatFileInfoPointer);
void FatParseShortFileName(PCHAR Buffer, PDIRENTRY DirEntry);
-BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG*
ClusterPointer);
-ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, ULONG StartCluster);
-ULONG* FatGetClusterChainArray(PFAT_VOLUME_INFO Volume, ULONG StartCluster);
-BOOLEAN FatReadClusterChain(PFAT_VOLUME_INFO Volume, ULONG StartClusterNumber, ULONG
NumberOfClusters, PVOID Buffer);
+static BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, UINT32 Cluster, PUINT32
ClusterPointer);
+static ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, UINT32 StartCluster);
+static BOOLEAN FatReadClusterChain(PFAT_VOLUME_INFO Volume, UINT32 StartClusterNumber,
UINT32 NumberOfClusters, PVOID Buffer, PUINT32 LastClusterNumber);
BOOLEAN FatReadPartialCluster(PFAT_VOLUME_INFO Volume, ULONG ClusterNumber, ULONG
StartingOffset, ULONG Length, PVOID Buffer);
BOOLEAN FatReadVolumeSectors(PFAT_VOLUME_INFO Volume, ULONG SectorNumber, ULONG
SectorCount, PVOID Buffer);
+#define FAT_IS_END_CLUSTER(clnumber) \
+ (((Volume->FatType == FAT12) && (clnumber >= 0xff8)) || \
+ ((Volume->FatType == FAT16 || Volume->FatType == FATX16) && (clnumber
>= 0xfff8)) || \
+ ((Volume->FatType == FAT32 || Volume->FatType == FATX32) && (clnumber
>= 0x0ffffff8)))
+
#define TAG_FAT_CHAIN 'CtaT'
#define TAG_FAT_FILE 'FtaF'
#define TAG_FAT_VOLUME 'VtaF'
@@ -494,7 +487,7 @@ PVOID FatBufferDirectory(PFAT_VOLUME_INFO Volume, ULONG
DirectoryStartCluster, U
}
else
{
- if (!FatReadClusterChain(Volume, DirectoryStartCluster, 0xFFFFFFFF,
DirectoryBuffer->Data))
+ if (!FatReadClusterChain(Volume, DirectoryStartCluster, 0xFFFFFFFF,
DirectoryBuffer->Data, NULL))
{
FrLdrTempFree(DirectoryBuffer, TAG_FAT_BUFFER);
return NULL;
@@ -682,6 +675,9 @@ BOOLEAN FatSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID
Directory
FatFileInfoPointer->Attributes = DirEntry->Attr;
FatFileInfoPointer->FileSize = DirEntry->Size;
FatFileInfoPointer->FilePointer = 0;
+ StartCluster = ((ULONG)DirEntry->ClusterHigh << 16) +
DirEntry->ClusterLow;
+ FatFileInfoPointer->CurrentCluster = StartCluster;
+ FatFileInfoPointer->StartCluster = StartCluster;
TRACE("MSDOS Directory Entry:\n");
TRACE("FileName[11] = %c%c%c%c%c%c%c%c%c%c%c\n",
DirEntry->FileName[0], DirEntry->FileName[1], DirEntry->FileName[2],
DirEntry->FileName[3], DirEntry->FileName[4], DirEntry->FileName[5],
DirEntry->FileName[6], DirEntry->FileName[7], DirEntry->FileName[8],
DirEntry->FileName[9], DirEntry->FileName[10]);
@@ -696,21 +692,7 @@ BOOLEAN FatSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume,
PVOID Directory
TRACE("Date = %d\n", DirEntry->Date);
TRACE("ClusterLow = 0x%x\n", DirEntry->ClusterLow);
TRACE("Size = %d\n", DirEntry->Size);
-
- //
- // Get the cluster chain
- //
- StartCluster = ((ULONG)DirEntry->ClusterHigh << 16) +
DirEntry->ClusterLow;
TRACE("StartCluster = 0x%x\n", StartCluster);
- FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(Volume,
StartCluster);
-
- //
- // See if memory allocation failed
- //
- if (FatFileInfoPointer->FileFatChain == NULL)
- {
- return FALSE;
- }
return TRUE;
}
@@ -761,6 +743,8 @@ static BOOLEAN FatXSearchDirectoryBufferForFile(PFAT_VOLUME_INFO
Volume, PVOID D
FatFileInfoPointer->Attributes = DirEntry->Attr;
FatFileInfoPointer->FileSize = DirEntry->Size;
FatFileInfoPointer->FilePointer = 0;
+ FatFileInfoPointer->CurrentCluster = DirEntry->StartCluster;
+ FatFileInfoPointer->StartCluster = DirEntry->StartCluster;
TRACE("FATX Directory Entry:\n");
TRACE("FileNameSize = %d\n", DirEntry->FileNameSize);
@@ -774,19 +758,6 @@ static BOOLEAN FatXSearchDirectoryBufferForFile(PFAT_VOLUME_INFO
Volume, PVOID D
TRACE("LastAccessTime = %d\n", DirEntry->LastAccessTime);
TRACE("LastAccessDate = %d\n", DirEntry->LastAccessDate);
- /*
- * Get the cluster chain
- */
- FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(Volume,
DirEntry->StartCluster);
-
- /*
- * See if memory allocation failed
- */
- if (NULL == FatFileInfoPointer->FileFatChain)
- {
- return FALSE;
- }
-
return TRUE;
}
}
@@ -875,12 +846,9 @@ ARC_STATUS FatLookupFile(PFAT_VOLUME_INFO Volume, PCSTR FileName,
PFAT_FILE_INFO
//
if (!(FatFileInfo.Attributes & ATTR_DIRECTORY))
{
- FrLdrTempFree(FatFileInfo.FileFatChain, TAG_FAT_CHAIN);
return ENOTDIR;
}
- DirectoryStartCluster = FatFileInfo.FileFatChain[0];
- FrLdrTempFree(FatFileInfo.FileFatChain, TAG_FAT_CHAIN);
- FatFileInfo.FileFatChain = NULL;
+ DirectoryStartCluster = FatFileInfo.StartCluster;
}
}
@@ -979,7 +947,8 @@ PUCHAR FatGetFatSector(PFAT_VOLUME_INFO Volume, UINT32
FatSectorNumber)
* FatGetFatEntry()
* returns the Fat entry for a given cluster number
*/
-BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG* ClusterPointer)
+static
+BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, UINT32 Cluster, PUINT32 ClusterPointer)
{
UINT32 FatOffset, ThisFatSecNum, ThisFatEntOffset, fat;
PUCHAR ReadBuffer;
@@ -1047,8 +1016,7 @@ BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster,
ULONG* ClusterPoi
ReadBuffer = FatGetFatSector(Volume, ThisFatSecNum);
if (!ReadBuffer)
{
- Success = FALSE;
- break;
+ return FALSE;
}
// Get the fat entry
@@ -1069,7 +1037,8 @@ BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster,
ULONG* ClusterPoi
return TRUE;
}
-ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, ULONG StartCluster)
+static
+ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, UINT32 StartCluster)
{
ULONG ClusterCount = 0;
@@ -1080,9 +1049,7 @@ ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, ULONG
StartCluster)
//
// If end of chain then break out of our cluster counting loop
//
- if (((Volume->FatType == FAT12) && (StartCluster >= 0xff8)) ||
- ((Volume->FatType == FAT16 || Volume->FatType == FATX16) &&
(StartCluster >= 0xfff8)) ||
- ((Volume->FatType == FAT32 || Volume->FatType == FATX32) &&
(StartCluster >= 0x0ffffff8)))
+ if (FAT_IS_END_CLUSTER(StartCluster))
{
break;
}
@@ -1106,119 +1073,76 @@ ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, ULONG
StartCluster)
return ClusterCount;
}
-ULONG* FatGetClusterChainArray(PFAT_VOLUME_INFO Volume, ULONG StartCluster)
+static
+BOOLEAN FatReadAdjacentClusters(
+ PFAT_VOLUME_INFO Volume,
+ UINT32 StartClusterNumber,
+ UINT32 MaxClusters,
+ PVOID Buffer,
+ PUINT32 ClustersRead,
+ PUINT32 LastClusterNumber)
{
- ULONG ClusterCount;
- ULONG ArraySize;
- ULONG* ArrayPointer;
- ULONG Idx;
+ UINT32 NextClusterNumber;
+ UINT32 ClustersToRead = 1;
+ UINT32 PrevClusterNumber = StartClusterNumber;
+ UINT32 ClusterStartSector = ((PrevClusterNumber - 2) * Volume->SectorsPerCluster)
+ Volume->DataSectorStart;
- TRACE("FatGetClusterChainArray() StartCluster = %d\n", StartCluster);
-
- ClusterCount = FatCountClustersInChain(Volume, StartCluster) + 1; // Lets get the
0x0ffffff8 on the end of the array
- ArraySize = ClusterCount * sizeof(ULONG);
-
- //
- // Allocate array memory
- //
- ArrayPointer = FrLdrTempAlloc(ArraySize, TAG_FAT_CHAIN);
+ *ClustersRead = 0;
+ *LastClusterNumber = 0;
- if (ArrayPointer == NULL)
+ if (!FatGetFatEntry(Volume, StartClusterNumber, &NextClusterNumber))
{
- return NULL;
+ return FALSE;
}
- //
- // Loop through and set array values
- //
- for (Idx=0; Idx<ClusterCount; Idx++)
+ // getting the number of adjacent clusters
+ while (!FAT_IS_END_CLUSTER(NextClusterNumber) && ClustersToRead <
MaxClusters && (NextClusterNumber == PrevClusterNumber + 1))
{
- //
- // Set current cluster
- //
- ArrayPointer[Idx] = StartCluster;
-
- //
- // Don't try to get next cluster for last cluster
- //
- if (((Volume->FatType == FAT12) && (StartCluster >= 0xff8)) ||
- ((Volume->FatType == FAT16 || Volume->FatType == FATX16) &&
(StartCluster >= 0xfff8)) ||
- ((Volume->FatType == FAT32 || Volume->FatType == FATX32) &&
(StartCluster >= 0x0ffffff8)))
+ ClustersToRead++;
+ PrevClusterNumber = NextClusterNumber;
+ if (!FatGetFatEntry(Volume, PrevClusterNumber, &NextClusterNumber))
{
- Idx++;
- break;
+ return FALSE;
}
+ }
- //
- // Get next cluster
- //
- if (!FatGetFatEntry(Volume, StartCluster, &StartCluster))
- {
- FrLdrTempFree(ArrayPointer, TAG_FAT_CHAIN);
- return NULL;
- }
+ if (!FatReadVolumeSectors(Volume, ClusterStartSector, ClustersToRead *
Volume->SectorsPerCluster, Buffer))
+ {
+ return FALSE;
}
- return ArrayPointer;
+ *ClustersRead = ClustersToRead;
+ *LastClusterNumber = NextClusterNumber;
+
+ return !FAT_IS_END_CLUSTER(NextClusterNumber) && ClustersToRead <
MaxClusters;
}
/*
* FatReadClusterChain()
* Reads the specified clusters into memory
*/
-BOOLEAN FatReadClusterChain(PFAT_VOLUME_INFO Volume, ULONG StartClusterNumber, ULONG
NumberOfClusters, PVOID Buffer)
+static
+BOOLEAN FatReadClusterChain(PFAT_VOLUME_INFO Volume, UINT32 StartClusterNumber, UINT32
NumberOfClusters, PVOID Buffer, PUINT32 LastClusterNumber)
{
- ULONG ClusterStartSector;
+ UINT32 ClustersRead, NextClusterNumber, ClustersLeft = NumberOfClusters;
TRACE("FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d
Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer);
- while (NumberOfClusters > 0)
- {
+ ASSERT(NumberOfClusters > 0);
- //TRACE("FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d
Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer);
- //
- // Calculate starting sector for cluster
- //
- ClusterStartSector = ((StartClusterNumber - 2) * Volume->SectorsPerCluster) +
Volume->DataSectorStart;
-
- //
- // Read cluster into memory
- //
- if (!FatReadVolumeSectors(Volume, ClusterStartSector,
Volume->SectorsPerCluster, Buffer))
- {
- return FALSE;
- }
-
- //
- // Decrement count of clusters left to read
- //
- NumberOfClusters--;
-
- //
- // Increment buffer address by cluster size
- //
- Buffer = (PVOID)((ULONG_PTR)Buffer + (Volume->SectorsPerCluster *
Volume->BytesPerSector));
-
- //
- // Get next cluster
- //
- if (!FatGetFatEntry(Volume, StartClusterNumber, &StartClusterNumber))
- {
- return FALSE;
- }
+ while (FatReadAdjacentClusters(Volume, StartClusterNumber, ClustersLeft, Buffer,
&ClustersRead, &NextClusterNumber))
+ {
+ ClustersLeft -= ClustersRead;
+ Buffer = (PVOID)((ULONG_PTR)Buffer + (ClustersRead * Volume->SectorsPerCluster
* Volume->BytesPerSector));
+ StartClusterNumber = NextClusterNumber;
+ }
- //
- // If end of chain then break out of our cluster reading loop
- //
- if (((Volume->FatType == FAT12) && (StartClusterNumber >= 0xff8))
||
- ((Volume->FatType == FAT16 || Volume->FatType == FATX16) &&
(StartClusterNumber >= 0xfff8)) ||
- ((Volume->FatType == FAT32 || Volume->FatType == FATX32) &&
(StartClusterNumber >= 0x0ffffff8)))
- {
- break;
- }
+ if (LastClusterNumber)
+ {
+ *LastClusterNumber = NextClusterNumber;
}
- return TRUE;
+ return (ClustersRead > 0);
}
/*
@@ -1268,14 +1192,11 @@ BOOLEAN FatReadPartialCluster(PFAT_VOLUME_INFO Volume, ULONG
ClusterNumber, ULON
* Reads BytesToRead from open file and
* returns the number of bytes read in BytesRead
*/
+static
BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG* BytesRead,
PVOID Buffer)
{
PFAT_VOLUME_INFO Volume = FatFileInfo->Volume;
- ULONG ClusterNumber;
- ULONG OffsetInCluster;
- ULONG LengthInCluster;
- ULONG NumberOfClusters;
- ULONG BytesPerCluster;
+ UINT32 NextClusterNumber, BytesPerCluster;
TRACE("FatReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead,
Buffer);
@@ -1342,15 +1263,15 @@ BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead,
ULONG* BytesR
//
// Do the math for our first read
//
- ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
- ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
- OffsetInCluster = (FatFileInfo->FilePointer % BytesPerCluster);
- LengthInCluster = (BytesToRead > (BytesPerCluster - OffsetInCluster)) ?
(BytesPerCluster - OffsetInCluster) : BytesToRead;
+ UINT32 OffsetInCluster = FatFileInfo->FilePointer % BytesPerCluster;
+ UINT32 LengthInCluster = min(BytesToRead, BytesPerCluster - OffsetInCluster);
+
+ ASSERT(LengthInCluster <= BytesPerCluster && LengthInCluster > 0);
//
// Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
//
- if (!FatReadPartialCluster(Volume, ClusterNumber, OffsetInCluster,
LengthInCluster, Buffer))
+ if (!FatReadPartialCluster(Volume, FatFileInfo->CurrentCluster,
OffsetInCluster, LengthInCluster, Buffer))
{
return FALSE;
}
@@ -1361,6 +1282,18 @@ BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead,
ULONG* BytesR
BytesToRead -= LengthInCluster;
FatFileInfo->FilePointer += LengthInCluster;
Buffer = (PVOID)((ULONG_PTR)Buffer + LengthInCluster);
+
+ // get the next cluster if needed
+ if ((LengthInCluster + OffsetInCluster) == BytesPerCluster)
+ {
+ if (!FatGetFatEntry(Volume, FatFileInfo->CurrentCluster,
&NextClusterNumber))
+ {
+ return FALSE;
+ }
+
+ FatFileInfo->CurrentCluster = NextClusterNumber;
+ TRACE("FatReadFile() FatFileInfo->CurrentCluster = 0x%x\n",
FatFileInfo->CurrentCluster);
+ }
}
//
@@ -1371,27 +1304,33 @@ BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead,
ULONG* BytesR
//
// Determine how many full clusters we need to read
//
- NumberOfClusters = (BytesToRead / BytesPerCluster);
+ UINT32 NumberOfClusters = BytesToRead / BytesPerCluster;
+
+ TRACE("Going to read: %u clusters\n", NumberOfClusters);
if (NumberOfClusters > 0)
{
- ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
- ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
+ UINT32 BytesReadHere = NumberOfClusters * BytesPerCluster;
- //
- // Now do the read and update BytesRead, BytesToRead, FilePointer, &
Buffer
- //
- if (!FatReadClusterChain(Volume, ClusterNumber, NumberOfClusters, Buffer))
+ ASSERT(!FAT_IS_END_CLUSTER(FatFileInfo->CurrentCluster));
+
+ if (!FatReadClusterChain(Volume, FatFileInfo->CurrentCluster,
NumberOfClusters, Buffer, &NextClusterNumber))
{
return FALSE;
}
+
if (BytesRead != NULL)
{
- *BytesRead += (NumberOfClusters * BytesPerCluster);
+ *BytesRead += BytesReadHere;
}
- BytesToRead -= (NumberOfClusters * BytesPerCluster);
- FatFileInfo->FilePointer += (NumberOfClusters * BytesPerCluster);
- Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfClusters * BytesPerCluster));
+ BytesToRead -= BytesReadHere;
+ Buffer = (PVOID)((ULONG_PTR)Buffer + BytesReadHere);
+
+ ASSERT(!FAT_IS_END_CLUSTER(NextClusterNumber) || BytesToRead == 0);
+
+ FatFileInfo->FilePointer += BytesReadHere;
+ FatFileInfo->CurrentCluster = NextClusterNumber;
+ TRACE("FatReadFile() FatFileInfo->CurrentCluster = 0x%x\n",
FatFileInfo->CurrentCluster);
}
}
@@ -1400,13 +1339,12 @@ BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead,
ULONG* BytesR
//
if (BytesToRead > 0)
{
- ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
- ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
+ ASSERT(!FAT_IS_END_CLUSTER(FatFileInfo->CurrentCluster));
//
// Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
//
- if (!FatReadPartialCluster(Volume, ClusterNumber, 0, BytesToRead, Buffer))
+ if (!FatReadPartialCluster(Volume, FatFileInfo->CurrentCluster, 0,
BytesToRead, Buffer))
{
return FALSE;
}
@@ -1460,7 +1398,6 @@ ARC_STATUS FatClose(ULONG FileId)
{
PFAT_FILE_INFO FileHandle = FsGetDeviceSpecific(FileId);
- if (FileHandle->FileFatChain) FrLdrTempFree(FileHandle->FileFatChain,
TAG_FAT_CHAIN);
FrLdrTempFree(FileHandle, TAG_FAT_FILE);
return ESUCCESS;
@@ -1544,6 +1481,7 @@ ARC_STATUS FatRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG*
Count)
ARC_STATUS FatSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
{
PFAT_FILE_INFO FileHandle = FsGetDeviceSpecific(FileId);
+ PFAT_VOLUME_INFO Volume = FileHandle->Volume;
LARGE_INTEGER NewPosition = *Position;
switch (SeekMode)
@@ -1551,7 +1489,7 @@ ARC_STATUS FatSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE
SeekMode)
case SeekAbsolute:
break;
case SeekRelative:
- NewPosition.QuadPart += (ULONGLONG)FileHandle->FilePointer;
+ NewPosition.QuadPart += (UINT64)FileHandle->FilePointer;
break;
default:
ASSERT(FALSE);
@@ -1563,7 +1501,42 @@ ARC_STATUS FatSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE
SeekMode)
if (NewPosition.LowPart >= FileHandle->FileSize)
return EINVAL;
+ TRACE("FatSeek() NewPosition = %u, OldPointer = %u, SeekMode = %d\n",
NewPosition.LowPart, FileHandle->FilePointer, SeekMode);
+
+ {
+ UINT32 OldClusterIdx = FileHandle->FilePointer / (Volume->SectorsPerCluster
* Volume->BytesPerSector);
+ UINT32 NewClusterIdx = NewPosition.LowPart / (Volume->SectorsPerCluster *
Volume->BytesPerSector);
+
+ TRACE("FatSeek() OldClusterIdx: %u, NewClusterIdx: %u\n",
OldClusterIdx, NewClusterIdx);
+
+ if (NewClusterIdx != OldClusterIdx)
+ {
+ UINT32 CurrentClusterIdx, ClusterNumber;
+
+ if (NewClusterIdx > OldClusterIdx)
+ {
+ CurrentClusterIdx = OldClusterIdx;
+ ClusterNumber = FileHandle->CurrentCluster;
+ }
+ else
+ {
+ CurrentClusterIdx = 0;
+ ClusterNumber = FileHandle->StartCluster;
+ }
+
+ for (; CurrentClusterIdx < NewClusterIdx; CurrentClusterIdx++)
+ {
+ if (!FatGetFatEntry(Volume, ClusterNumber, &ClusterNumber))
+ {
+ return EIO;
+ }
+ }
+ FileHandle->CurrentCluster = ClusterNumber;
+ }
+ }
+
FileHandle->FilePointer = NewPosition.LowPart;
+
return ESUCCESS;
}