open.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 820 行 · 第 1/2 页
C
820 行
/*++
Copyright (c) 1999 - 2003 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
open.c
Abstract:
Routines dealing with file open
Revision History
--*/
#include "fat.h"
EFI_STATUS
FatAllocateIFile (
IN FAT_OFILE *OFile,
OUT FAT_IFILE **pIFile
)
{
FAT_IFILE *IFile;
ASSERT_VOLUME_LOCKED (OFile->Vol);
//
// Allocate a new open instance
//
IFile = EfiLibAllocateZeroPool (sizeof(FAT_IFILE));
if (!IFile) {
return EFI_OUT_OF_RESOURCES;
}
IFile->Signature = FAT_IFILE_SIGNATURE;
EfiCopyMem(&(IFile->Handle), &FATFileInterface,sizeof(EFI_FILE));
IFile->Position = 0;
IFile->OFile = OFile;
InsertTailList (&OFile->Opens, &IFile->Link);
*pIFile = IFile;
return EFI_SUCCESS;
}
BOOLEAN
FatMatchFileName (
IN FAT_OFILE *Entry,
IN CHAR16 *Name
)
/*++
Routine Description:
Check if the file matches a name. Compare both LFN and 8Dot3Name
Arguments:
Entry - The file
Name - The Name to match
Returns:
TRUE - Name matches
FALSE - Name not match
--*/
{
CHAR16 UnicodeBuffer[30];
CHAR16 *Ptr;
if (FatStriCmp (Name, Entry->FileString) == 0) {
//
// Just match
//
return TRUE;
} else {
//
// match after starting/trailing blanks and trailing periods
// is removed
//
FatLfnIsValid (Name);
if (FatStriCmp (Name, Entry->FileString) == 0) {
return TRUE;
}
//
// match with the 8Dot3 Name
//
FatFatToStr (8, Entry->File8Dot3Name, UnicodeBuffer);
for (Ptr = UnicodeBuffer + EfiStrLen(UnicodeBuffer) - 1;
Ptr >= UnicodeBuffer && *Ptr == ' ';
Ptr --) {
;
}
*(Ptr + 1) = 0;
if (! (Entry->File8Dot3Name[8] == ' ' &&
Entry->File8Dot3Name[9] == ' ' &&
Entry->File8Dot3Name[10]== ' ')
) {
UnicodeBuffer[EfiStrLen(UnicodeBuffer) + 1] = 0;
UnicodeBuffer[EfiStrLen(UnicodeBuffer)] = '.';
FatFatToStr (3, Entry->File8Dot3Name + 8,
UnicodeBuffer + EfiStrLen(UnicodeBuffer));
for (Ptr = UnicodeBuffer + EfiStrLen(UnicodeBuffer) - 1;
Ptr >= UnicodeBuffer && *Ptr == ' ';
Ptr --) {
;
}
*(Ptr + 1) = 0;
}
if (FatStriCmp (Name, UnicodeBuffer) == 0) {
return TRUE;
}
}
return FALSE;
}
EFI_STATUS
FatOFileFromPath (
IN FAT_OFILE *OFile,
IN OUT CHAR16 **FileName,
IN FAT_OFILE **pOFile,
OUT CHAR16 *CompName
)
/*++
Routine Description:
Traverse filename opening all OFiles that can be opened.
Update filename pointer to the bits that can't be opened.
If more than one name component remains, returns an error.
Arguments:
OFile - The file that serves as a starting reference point.
FileName - The file name relevant to the OFile.
pOFile - The result OFile.
CompName - The last component of the file name if the file name is opened,
otherwise the component after the component that cannot be
opened. The buffer should be already allocated when passed in.
Returns:
Status Code. If error, indicates the file name can't be opened and
there is more than one components within the name left (this means
the name can not be created either)
--*/
{
FAT_OFILE *Entry;
EFI_STATUS Status;
CHAR16 *Next;
UINT64 Position;
UINT64 RefPosition;
UINT64 StartPosition;
BOOLEAN FirstRound;
//
// Start at current location
//
Next = *FileName;
//
// If name starts with '\' then move to root
//
if (*FileName[0] == '\\') {
OFile = OFile->Vol->Root;
Next += 1;
}
Status = EFI_SUCCESS;
while (!EFI_ERROR(Status)) {
//
// Get the next component name
//
*FileName = Next;
Next = FatGetNameComp (*FileName, CompName);
//
// If end of the file name, we're done
//
if (CompName[0] == 0) {
break;
}
//
// if it is an all-blank file name, then current
//
FatLfnIsValid (CompName);
if (CompName[0] == 0) {
continue;
}
//
// If "dot", then current
//
if (EfiStrCmp(CompName, L".") == 0) {
continue;
}
//
// If "dot dot", then parent
//
if (EfiStrCmp(CompName, L"..") == 0) {
OFile = OFile->Parent;
if (!OFile) {
Status = EFI_NOT_FOUND;
break;
}
continue;
}
//
// We have a component name, try to open it
//
if (OFile->DirType != IsDir) {
//
// This file isn't a directory, can't open it
//
Status = EFI_NOT_FOUND;
break;
}
//
// If this name is just the not existing one we knew
//
if (OFile->NameNotFound) {
if (FatStriCmp (CompName, OFile->NameNotFound) == 0) {
Status = EFI_NOT_FOUND;
FatGetNameComp (Next, CompName);
if (CompName[0] == 0) {
// it's the
// last component name - return with the open
// path and the remaining name
//
Status = EFI_SUCCESS;
}
break;
}
}
//
// Search the hash table first
//
Entry = FatHashSearch (OFile, CompName, (UINT32)(OFile->CurrentEntryPos));
if (Entry) {
//
// Found in the Hash table
//
OFile = Entry;
} else {
//
// Not found in the Hash table, search from the entry at HashTopPosition.
// OFile->CurrentEntryPos is favoured.
//
FirstRound = TRUE;
Position = OFile->CurrentEntryPos > OFile->HashTopPosition ?
OFile->CurrentEntryPos : OFile->HashTopPosition;
RefPosition = Position;
StartPosition = OFile->HashTopPosition;
for (; ;) {
Status = FatGetDirOFile (OFile, &Position, &Entry);
if (EFI_ERROR(Status) && FirstRound) {
Position = StartPosition;
FirstRound = FALSE;
continue;
}
if (EFI_ERROR(Status) && !FirstRound) {
break;
}
if (Entry->IsBlank && FirstRound) {
//
// This is not what we want.
// Try to free this OFile if it is not referenced.
//
FatCheckOFileRef (Entry);
Position = StartPosition;
FirstRound = FALSE;
continue;
}
if ((Position > RefPosition || Entry->IsBlank) && !FirstRound) {
Status = EFI_NOT_FOUND;
break;
}
//
// If this isn't a file or directory, skip it
//
if (Entry->DirType != IsFile && Entry->DirType != IsDir) {
//
// This is not what we want.
// Try to free this OFile if it is not referenced.
//
FatCheckOFileRef (Entry);
continue;
}
//
// If the filename matches, we're done
//
if (FatMatchFileName (Entry, CompName)) {
OFile->CurrentEntryPos = Entry->DirPosition;
OFile = Entry;
break;
}
//
// This is not what we want.
// Try to free this OFile if it is not referenced.
//
FatCheckOFileRef (Entry);
}
}
if (Status == EFI_NOT_FOUND) {
//
// The component name isn't found, remember the name
//
if (OFile->NameNotFound) {
gBS->FreePool (OFile->NameNotFound);
}
OFile->NameNotFound = EfiLibAllocateZeroPool (EfiStrSize(CompName));
if (OFile->NameNotFound) {
EfiStrCpy(OFile->NameNotFound, CompName);
}
FatGetNameComp (Next, CompName);
if (CompName[0] == 0) {
// it's the
// last component name - return with the open
// path and the remaining name
//
Status = EFI_SUCCESS;
}
break;
}
}
if (!EFI_ERROR(Status)) {
*pOFile = OFile;
}
return Status;
}
EFI_STATUS
FatOFileOpen (
IN FAT_OFILE *OFile,
OUT FAT_IFILE **NewIFile,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
/*++
Routine Description:
Open a file for a file name relative to an existing OFile.
The IFile of the newly opened file is passed out.
Arguments:
OFile - The file that serves as a starting reference point.
NewIFile - The newly generated IFile instance.
FileName - The file name relative to the OFile.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?