open.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 820 行 · 第 1/2 页
C
820 行
OpenMode - Open mode.
Attributes - Attributes to set if the file is created.
Returns:
Status Code.
--*/
{
FAT_OFILE *SubDir;
FAT_VOLUME *Vol;
EFI_STATUS Status;
CHAR16 CompName[EFI_FILE_STRING_SIZE];
CHAR16 *OrigName;
UINTN DirCount;
UINT8 CaseFlag;
UINTN FileStringBufferSize;
BOOLEAN DirIntended;
Vol = OFile->Vol;
OrigName = FileName;
DirIntended = FALSE;
if (EfiStrLen(FileName) > 0) {
if (FileName [EfiStrLen(FileName) - 1] == '\\') {
DirIntended = TRUE;
}
}
ASSERT_VOLUME_LOCKED(Vol);
//
// If attempting to open for write access, make a couple of checks
//
if (OpenMode & EFI_FILE_MODE_WRITE) {
//
// Can't open for create and apply the read only attribute
//
if ((OpenMode & EFI_FILE_MODE_CREATE) && (Attributes & EFI_FILE_READ_ONLY)) {
return EFI_INVALID_PARAMETER;
}
//
// Conficts between dir intention and attribute
//
if ((OpenMode & EFI_FILE_MODE_CREATE) && !(Attributes & EFI_FILE_DIRECTORY)
&& DirIntended) {
return EFI_NOT_FOUND;
}
//
// Can't open for write if the volume is read only
//
if (Vol->ReadOnly) {
return EFI_WRITE_PROTECTED;
}
}
//
// Verify the source file handle isn't in an error state
//
Status = OFile->Error;
if (EFI_ERROR(Status)) {
goto Done;
}
//
// Get new OFile for the file
//
Status = FatOFileFromPath (OFile, &FileName, &OFile, CompName);
if (EFI_ERROR(Status)) {
goto Done;
}
if (*FileName) {
//
// If there's a remaining part of the name, then we had
// better be creating the file in the directory
//
//
// can only create new files/dirs in existing dirs
//
if (OFile->DirType != IsDir) {
Status = EFI_NOT_FOUND;
goto Done;
}
if (!(OpenMode & EFI_FILE_MODE_CREATE)) {
Status = EFI_NOT_FOUND;
goto Done;
}
//
// Make sure volume is read/write
//
if (Vol->ReadOnly) {
Status = EFI_WRITE_PROTECTED;
goto Done;
}
FatGetNameComp (FileName, CompName);
//
// Check if the file name to be created is valid
//
if (!FatLfnIsValid(CompName)) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
//
// Determine the file's directory entry size
//
DirCount = FatNameToDirEntryCount (CompName, &CaseFlag);
//
//
// Create the file in the OFile directory
//
Status = FatNewDirEntry (OFile, DirCount, &OFile);
if (EFI_ERROR(Status)) {
goto Done;
}
//
// Invalidate parent directory's NameNotFound
//
if (OFile->Parent->NameNotFound) {
gBS->FreePool (OFile->Parent->NameNotFound);
OFile->Parent->NameNotFound = NULL;
}
//
// Initialize file entry
//
// N.B. need to fill the filestring with 0xFF for unused chars
// written to Lfn dir entries
//
OFile->DirType = (Attributes & EFI_FILE_DIRECTORY) ? IsDir : IsFile;
OFile->DirCount = DirCount;
OFile->Attributes = (UINT8) (Attributes | FAT_ATTRIBUTE_ARCHIVE);
OFile->CaseFlag = CaseFlag;
FileStringBufferSize = ((EfiStrLen (CompName) + 1 + 12) / 13) * 26;
if (OFile->FileString) {
gBS->FreePool (OFile->FileString);
}
OFile->FileString = EfiLibAllocateZeroPool (FileStringBufferSize);
if (!OFile->FileString) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
EfiSetMem (OFile->FileString, FileStringBufferSize, 0xFF);
EfiStrCpy (OFile->FileString, CompName);
Status = FatGenerate8Dot3Name (OFile->Vol, OFile->Parent, OFile);
//
// Case flag is the NtReserved field in the DirEntry. Set to 0
// when a file is created as required by Fat Spec
//
OFile->CaseFlag = 0;
if (EFI_ERROR(Status) || OFile->File8Dot3Name[0] == ' ') {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
DEBUG ((EFI_D_INFO, "FSOpen: Created new file '%S'\n", OFile->FileString));
//
// If we just created a directory, we need to create "." and ".."
//
if (Attributes & EFI_FILE_DIRECTORY) {
//
// Create "."
//
Status = FatNewDirEntry (OFile, 1, &SubDir);
if (EFI_ERROR(Status)) {
OFile->DirType = IsEmpty;
goto Done;
}
SubDir->DirType = IsDir;
SubDir->Attributes = EFI_FILE_DIRECTORY;
SubDir->FileCluster = OFile->FileCluster;
SubDir->FileCurrentCluster = OFile->FileCluster;
//EfiStrCpy (SubDir->FileString, L".");
if (SubDir->FileString) {
gBS->FreePool (SubDir->FileString);
}
SubDir->FileString = EfiLibAllocateZeroPool (26);
if (!SubDir->FileString) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
EfiSetMem (SubDir->FileString, 26, 0xFF);
EfiStrCpy (SubDir->FileString, L".");
//
// Create ".."
//
Status = FatNewDirEntry (OFile, 1, &SubDir);
if (EFI_ERROR(Status) || !(OFile->Parent)) {
Status = EFI_VOLUME_CORRUPTED;
goto Done;
}
SubDir->DirType = IsDir;
SubDir->Attributes = EFI_FILE_DIRECTORY;
//
// The root directory in FAT32 can and will have a valid beginning
// cluster number. However for COMPATABILITY reasons, we need to
// zero the FileCluster field for the first subdirectory under the root.
// If we didn't, the corresponding CHKDSK/SCANDISK utilities for
// Windows 200x and Windows 98 will detect an error, and force the fields
// to zero anyway.
//
if (OFile->Parent->FileCluster == OFile->Vol->RootCluster) {
SubDir->FileCluster = 0;
SubDir->FileCurrentCluster = 0;
} else {
SubDir->FileCluster = OFile->Parent->FileCluster;
SubDir->FileCurrentCluster = OFile->Parent->FileCluster;
}
//EfiStrCpy (SubDir->FileString, L"..");
if (SubDir->FileString) {
gBS->FreePool (SubDir->FileString);
}
SubDir->FileString = EfiLibAllocateZeroPool (26);
if (!SubDir->FileString) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
EfiSetMem (SubDir->FileString, 26, 0xFF);
EfiStrCpy (SubDir->FileString, L"..");
}
}
//
// If the file's attribute is read only, and the open is for
// read-write fail it.
//
if ((OFile->Attributes & EFI_FILE_READ_ONLY) && (OpenMode & EFI_FILE_MODE_WRITE)
&& (OFile->DirType == IsFile)) {
Status = EFI_ACCESS_DENIED;
goto Done;
}
//
// Conflicts between dir intention and attribute
//
if (!(OFile->Attributes & EFI_FILE_DIRECTORY) && DirIntended) {
Status = EFI_NOT_FOUND;
goto Done;
}
//
// Create an open instance of the OFile
//
Status = FatAllocateIFile(OFile, NewIFile);
if (!EFI_ERROR(Status)) {
//
// If the file was opened read-only, set the read-only flag
//
if (!(OpenMode & EFI_FILE_MODE_WRITE)) {
(*NewIFile)->ReadOnly = TRUE;
}
}
Done:
DEBUG((EFI_D_INFO, "FSOpen: Open '%S' %r\n", OrigName, Status));
return Status;
}
EFI_STATUS
EFIAPI
FatOpen (
IN EFI_FILE *FHand,
OUT EFI_FILE **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
/*++
Routine Description:
Implements Open() of Simple File System Protocol.
Arguments:
FHand - File handle of the file serves as a starting reference point.
NewHandle - Handle of the file that is newly opened.
FileName - File name relative to FHand.
OpenMode - Open mode.
Attributes- Attributes to set if the file is created.
Returns:
Status Code.
--*/
{
CHAR16 *FileNameStr;
FAT_IFILE *IFile;
FAT_IFILE *NewIFile;
FAT_OFILE *OFile;
EFI_STATUS Status;
//
// Perform some parameter checking
//
if (FileName == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// The passed in file name may be a const string, so we shouldn't modify it directly.
// Duplicate it first.
//
FileNameStr = EfiLibAllocatePool (EfiStrSize (FileName));
if (FileNameStr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
EfiStrCpy (FileNameStr, FileName);
// Don't allow empty file name
EfiStrTrim (FileNameStr, ' ');
if (*FileNameStr == 0) {
return EFI_INVALID_PARAMETER;
}
IFile = IFILE_FROM_FHAND(FHand);
OFile = IFile->OFile;
//
// Check for a valid mode
//
switch (OpenMode) {
case EFI_FILE_MODE_READ :
case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE :
case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE :
break;
default :
return EFI_INVALID_PARAMETER;
}
//
// Check for valid attributes
//
if (Attributes & ~(EFI_FILE_VALID_ATTR)) {
return EFI_INVALID_PARAMETER;
}
//
// Lock
//
FatAcquireLock ();
//
// Open the file
//
Status = FatOFileOpen (OFile, &NewIFile, FileNameStr, OpenMode, Attributes);
//
// If the file was opened, return the handle to the caller
//
if (!EFI_ERROR(Status)) {
*NewHandle = &NewIFile->Handle;
OFile = NewIFile->OFile;
}
//
// Unlock
//
Status = FatCleanupVolume (OFile->Vol, NULL, Status);
FatReleaseLock();
gBS->FreePool (FileNameStr);
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?