mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[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.
This commit is contained in:
parent
195dc30484
commit
220bc820eb
2 changed files with 152 additions and 178 deletions
|
@ -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
|
||||
|
|
|
@ -1,21 +1,10 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 1998-2003 Brian Palmer <brianp@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@sginet.com)
|
||||
* Copyright 2009 Hervé Poussineau
|
||||
* Copyright 2019 Victor Perevertkin (victor.perevertkin@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);
|
||||
*ClustersRead = 0;
|
||||
*LastClusterNumber = 0;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//
|
||||
// Get next cluster
|
||||
//
|
||||
if (!FatGetFatEntry(Volume, StartCluster, &StartCluster))
|
||||
{
|
||||
FrLdrTempFree(ArrayPointer, TAG_FAT_CHAIN);
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayPointer;
|
||||
if (!FatReadVolumeSectors(Volume, ClusterStartSector, ClustersToRead * Volume->SectorsPerCluster, Buffer))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*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);
|
||||
|
||||
while (FatReadAdjacentClusters(Volume, StartClusterNumber, ClustersLeft, Buffer, &ClustersRead, &NextClusterNumber))
|
||||
{
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
ClustersLeft -= ClustersRead;
|
||||
Buffer = (PVOID)((ULONG_PTR)Buffer + (ClustersRead * Volume->SectorsPerCluster * Volume->BytesPerSector));
|
||||
StartClusterNumber = NextClusterNumber;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
if (LastClusterNumber)
|
||||
{
|
||||
*LastClusterNumber = NextClusterNumber;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue