mirror of
https://github.com/reactos/reactos.git
synced 2025-04-19 12:08:55 +00:00
[FREELDR] iso.c: Remember the last directory that was accessed (#7734)
This patch reduces the number of sectors read by 709 (from 8788 to 8079)
This commit is contained in:
parent
564be44f45
commit
5fb6fad175
1 changed files with 113 additions and 41 deletions
|
@ -33,10 +33,34 @@ typedef struct _ISO_VOLUME_INFO
|
||||||
{
|
{
|
||||||
ULONG PvdDirectorySector;
|
ULONG PvdDirectorySector;
|
||||||
ULONG PvdDirectoryLength;
|
ULONG PvdDirectoryLength;
|
||||||
|
ULONG DirectoryPathLength;
|
||||||
|
ULONG DirectoryLength;
|
||||||
|
PVOID DirectoryBuffer;
|
||||||
|
UCHAR DirectoryPath[261];
|
||||||
} ISO_VOLUME_INFO, *PISO_VOLUME_INFO;
|
} ISO_VOLUME_INFO, *PISO_VOLUME_INFO;
|
||||||
|
|
||||||
static PISO_VOLUME_INFO IsoVolumes[MAX_FDS];
|
static PISO_VOLUME_INFO IsoVolumes[MAX_FDS];
|
||||||
|
|
||||||
|
static
|
||||||
|
PCSTR
|
||||||
|
IsoLastPathSeparator(
|
||||||
|
_In_ PCSTR Path)
|
||||||
|
{
|
||||||
|
PCSTR Last = NULL;
|
||||||
|
|
||||||
|
ASSERT(Path != NULL);
|
||||||
|
|
||||||
|
while (*Path != ANSI_NULL)
|
||||||
|
{
|
||||||
|
if (*Path == '\\' || *Path == '/')
|
||||||
|
Last = Path;
|
||||||
|
|
||||||
|
++Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Last;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOLEAN IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectoryLength, PCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer)
|
static BOOLEAN IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectoryLength, PCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer)
|
||||||
{
|
{
|
||||||
PDIR_RECORD Record;
|
PDIR_RECORD Record;
|
||||||
|
@ -145,7 +169,6 @@ static ARC_STATUS IsoBufferDirectory(ULONG DeviceId, ULONG DirectoryStartSector,
|
||||||
return ESUCCESS;
|
return ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IsoLookupFile()
|
* IsoLookupFile()
|
||||||
* This function searches the file system for the
|
* This function searches the file system for the
|
||||||
|
@ -154,65 +177,113 @@ static ARC_STATUS IsoBufferDirectory(ULONG DeviceId, ULONG DirectoryStartSector,
|
||||||
*/
|
*/
|
||||||
static ARC_STATUS IsoLookupFile(PCSTR FileName, ULONG DeviceId, PISO_FILE_INFO IsoFileInfo)
|
static ARC_STATUS IsoLookupFile(PCSTR FileName, ULONG DeviceId, PISO_FILE_INFO IsoFileInfo)
|
||||||
{
|
{
|
||||||
|
PCSTR FullPath = FileName;
|
||||||
PISO_VOLUME_INFO Volume;
|
PISO_VOLUME_INFO Volume;
|
||||||
UINT32 i;
|
PCSTR FileNameStr;
|
||||||
ULONG NumberOfPathParts;
|
ULONG i, DirectoryPathLength, DirectorySector, DirectoryLength;
|
||||||
CHAR PathPart[261];
|
|
||||||
PVOID DirectoryBuffer;
|
PVOID DirectoryBuffer;
|
||||||
ULONG DirectorySector;
|
ULONG NumberOfPathParts;
|
||||||
ULONG DirectoryLength;
|
CHAR PathBuffer[261];
|
||||||
|
CHAR* PathPart;
|
||||||
ARC_STATUS Status;
|
ARC_STATUS Status;
|
||||||
|
BOOLEAN DoFullLookup;
|
||||||
|
|
||||||
TRACE("IsoLookupFile() FileName = %s\n", FileName);
|
TRACE("IsoLookupFile() FileName = %s\n", FileName);
|
||||||
|
|
||||||
Volume = IsoVolumes[DeviceId];
|
Volume = IsoVolumes[DeviceId];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract the file name
|
||||||
|
* '\test.ini' --> 'test.ini'
|
||||||
|
* '\folder\app.exe' --> 'app.exe'
|
||||||
|
*/
|
||||||
|
FileNameStr = IsoLastPathSeparator(FileName) + 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract the directory path, including trailing slash
|
||||||
|
* '\test.ini' --> '\'
|
||||||
|
* '\folder\app.exe' --> '\folder\'
|
||||||
|
*/
|
||||||
|
DirectoryPathLength = FileNameStr - FileName;
|
||||||
|
|
||||||
|
/* See if this directory has been buffered before */
|
||||||
|
DoFullLookup = (DirectoryPathLength != Volume->DirectoryPathLength) ||
|
||||||
|
!RtlEqualMemory(FileName, Volume->DirectoryPath, DirectoryPathLength);
|
||||||
|
if (!DoFullLookup)
|
||||||
|
{
|
||||||
|
PathPart = (CHAR*)FileNameStr;
|
||||||
|
DirectoryBuffer = Volume->DirectoryBuffer;
|
||||||
|
DirectoryLength = Volume->DirectoryLength;
|
||||||
|
|
||||||
|
NumberOfPathParts = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PathPart = PathBuffer;
|
||||||
DirectorySector = Volume->PvdDirectorySector;
|
DirectorySector = Volume->PvdDirectorySector;
|
||||||
DirectoryLength = Volume->PvdDirectoryLength;
|
DirectoryLength = Volume->PvdDirectoryLength;
|
||||||
|
|
||||||
/* Skip leading path separator, if any */
|
/* Skip leading path separator, if any */
|
||||||
if (*FileName == '\\' || *FileName == '/')
|
if (*FileName == '\\' || *FileName == '/')
|
||||||
++FileName;
|
++FileName;
|
||||||
//
|
|
||||||
// Figure out how many sub-directories we are nested in
|
/* Figure out how many sub-directories we are nested in */
|
||||||
//
|
|
||||||
NumberOfPathParts = FsGetNumPathParts(FileName);
|
NumberOfPathParts = FsGetNumPathParts(FileName);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop once for each part
|
// Loop once for each part
|
||||||
//
|
//
|
||||||
for (i=0; i<NumberOfPathParts; i++)
|
for (i=0; i<NumberOfPathParts; i++)
|
||||||
{
|
{
|
||||||
//
|
if (DoFullLookup)
|
||||||
// Get first path part
|
{
|
||||||
//
|
/* Get first path part */
|
||||||
FsGetFirstNameFromPath(PathPart, FileName);
|
FsGetFirstNameFromPath(PathPart, FileName);
|
||||||
|
|
||||||
//
|
/* Advance to the next part of the path */
|
||||||
// Advance to the next part of the path
|
while ((*FileName != ANSI_NULL) && (*FileName != '\\') && (*FileName != '/'))
|
||||||
//
|
|
||||||
for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
|
|
||||||
{
|
{
|
||||||
|
FileName++;
|
||||||
}
|
}
|
||||||
FileName++;
|
FileName++;
|
||||||
|
|
||||||
//
|
/* Buffer the directory contents */
|
||||||
// Buffer the directory contents
|
Status = IsoBufferDirectory(DeviceId,
|
||||||
//
|
DirectorySector,
|
||||||
Status = IsoBufferDirectory(DeviceId, DirectorySector, DirectoryLength, &DirectoryBuffer);
|
DirectoryLength,
|
||||||
|
&DirectoryBuffer);
|
||||||
if (Status != ESUCCESS)
|
if (Status != ESUCCESS)
|
||||||
return Status;
|
return Status;
|
||||||
|
|
||||||
//
|
/* Save the directory buffer */
|
||||||
// Search for file name in directory
|
if ((i + 1) >= NumberOfPathParts)
|
||||||
//
|
|
||||||
if (!IsoSearchDirectoryBufferForFile(DirectoryBuffer, DirectoryLength, PathPart, IsoFileInfo))
|
|
||||||
{
|
{
|
||||||
FrLdrTempFree(DirectoryBuffer, TAG_ISO_BUFFER);
|
if (Volume->DirectoryBuffer)
|
||||||
return ENOENT;
|
FrLdrTempFree(Volume->DirectoryBuffer, TAG_ISO_BUFFER);
|
||||||
|
|
||||||
|
Volume->DirectoryPathLength = DirectoryPathLength;
|
||||||
|
Volume->DirectoryBuffer = DirectoryBuffer;
|
||||||
|
Volume->DirectoryLength = DirectoryLength;
|
||||||
|
|
||||||
|
RtlCopyMemory(Volume->DirectoryPath, FullPath, DirectoryPathLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Search for file name in directory */
|
||||||
|
if (!IsoSearchDirectoryBufferForFile(DirectoryBuffer,
|
||||||
|
DirectoryLength,
|
||||||
|
PathPart,
|
||||||
|
IsoFileInfo))
|
||||||
|
{
|
||||||
|
/* Free the directory buffer that wasn't cached */
|
||||||
|
if ((i + 1) < NumberOfPathParts)
|
||||||
|
{
|
||||||
|
ASSERT(DirectoryBuffer != Volume->DirectoryBuffer);
|
||||||
FrLdrTempFree(DirectoryBuffer, TAG_ISO_BUFFER);
|
FrLdrTempFree(DirectoryBuffer, TAG_ISO_BUFFER);
|
||||||
|
}
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we have another sub-directory to go then
|
// If we have another sub-directory to go then
|
||||||
|
@ -220,10 +291,11 @@ static ARC_STATUS IsoLookupFile(PCSTR FileName, ULONG DeviceId, PISO_FILE_INFO I
|
||||||
//
|
//
|
||||||
if ((i+1) < NumberOfPathParts)
|
if ((i+1) < NumberOfPathParts)
|
||||||
{
|
{
|
||||||
|
FrLdrTempFree(DirectoryBuffer, TAG_ISO_BUFFER);
|
||||||
|
|
||||||
DirectorySector = IsoFileInfo->FileStart;
|
DirectorySector = IsoFileInfo->FileStart;
|
||||||
DirectoryLength = IsoFileInfo->FileSize;
|
DirectoryLength = IsoFileInfo->FileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESUCCESS;
|
return ESUCCESS;
|
||||||
|
|
Loading…
Reference in a new issue