From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.zytor.com (terminus.zytor.com [65.50.211.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A94B721E0C31A for ; Tue, 8 Aug 2017 12:33:02 -0700 (PDT) Received: from localhost.localdomain ([IPv6:2804:7f4:c480:4886:0:0:0:4]) (authenticated bits=0) by mail.zytor.com (8.15.2/8.15.2) with ESMTPSA id v78JWiKN019064 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Tue, 8 Aug 2017 12:33:03 -0700 From: Paulo Alcantara To: edk2-devel@lists.01.org Cc: Paulo Alcantara , Star Zeng , Eric Dong , Laszlo Ersek Date: Tue, 8 Aug 2017 16:31:42 -0300 Message-Id: <20170808193143.18128-4-pcacjr@zytor.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170808193143.18128-1-pcacjr@zytor.com> References: <20170808193143.18128-1-pcacjr@zytor.com> Subject: [PATCH 3/4] MdeModulePkg/UdfDxe: Add seek, read and listing support on files X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Aug 2017 19:33:02 -0000 This patch implements UdfRead(), UdfGetPosition() and UdfSetPosition() functions. Cc: Star Zeng Cc: Eric Dong Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara --- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 264 ++++++++++++++++++++- .../Universal/Disk/UdfDxe/FileSystemOperations.c | 102 ++++++-- MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 33 +++ 3 files changed, 371 insertions(+), 28 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/File.c b/MdeModulePkg/Universal/Disk/UdfDxe/File.c index dcb9ff2cf5..3b93beb3f8 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/File.c +++ b/MdeModulePkg/Universal/Disk/UdfDxe/File.c @@ -198,7 +198,7 @@ UdfOpen ( // // Build full path // - if (FileName[0] == L'\\') { + if (*FileName == L'\\') { StrCpyS (FilePath, UDF_PATH_LENGTH, FileName); } else { StrCpyS (FilePath, UDF_PATH_LENGTH, PrivFileData->AbsoluteFileName); @@ -247,6 +247,7 @@ UdfOpen ( } StrCpyS (NewPrivFileData->FileName, UDF_PATH_LENGTH, FileName); + Status = GetFileSize ( PrivFsData->BlockIo, PrivFsData->DiskIo, @@ -308,7 +309,197 @@ UdfRead ( OUT VOID *Buffer ) { - return EFI_VOLUME_CORRUPTED; + EFI_TPL OldTpl; + EFI_STATUS Status; + PRIVATE_UDF_FILE_DATA *PrivFileData; + PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData; + UDF_VOLUME_INFO *Volume; + UDF_FILE_INFO *Parent; + UDF_READ_DIRECTORY_INFO *ReadDirInfo; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + UDF_FILE_INFO FoundFile; + UDF_FILE_IDENTIFIER_DESCRIPTOR *NewFileIdentifierDesc; + VOID *NewFileEntryData; + CHAR16 FileName[UDF_FILENAME_LENGTH] = { 0 }; + UINT64 FileSize; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + if (This == NULL || BufferSize == NULL || (*BufferSize != 0 && + Buffer == NULL)) { + Status = EFI_INVALID_PARAMETER; + goto Error_Invalid_Params; + } + + PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This); + + PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs); + + BlockIo = PrivFsData->BlockIo; + DiskIo = PrivFsData->DiskIo; + Volume = &PrivFsData->Volume; + ReadDirInfo = &PrivFileData->ReadDirInfo; + NewFileIdentifierDesc = NULL; + NewFileEntryData = NULL; + + Parent = _PARENT_FILE (PrivFileData); + + Status = EFI_VOLUME_CORRUPTED; + + if (IS_FID_NORMAL_FILE (Parent->FileIdentifierDesc)) { + if (PrivFileData->FilePosition > PrivFileData->FileSize) { + // + // File's position is beyond the EOF + // + Status = EFI_DEVICE_ERROR; + goto Error_File_Beyond_The_Eof; + } + + if (PrivFileData->FilePosition == PrivFileData->FileSize) { + *BufferSize = 0; + Status = EFI_SUCCESS; + goto Done; + } + + Status = ReadFileData ( + BlockIo, + DiskIo, + Volume, + Parent, + PrivFileData->FileSize, + &PrivFileData->FilePosition, + Buffer, + BufferSize + ); + } else if (IS_FID_DIRECTORY_FILE (Parent->FileIdentifierDesc)) { + if (ReadDirInfo->FidOffset == 0 && PrivFileData->FilePosition > 0) { + Status = EFI_DEVICE_ERROR; + *BufferSize = 0; + goto Done; + } + + for (;;) { + Status = ReadDirectoryEntry ( + BlockIo, + DiskIo, + Volume, + &Parent->FileIdentifierDesc->Icb, + Parent->FileEntry, + ReadDirInfo, + &NewFileIdentifierDesc + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_DEVICE_ERROR) { + FreePool (ReadDirInfo->DirectoryData); + ZeroMem ((VOID *)ReadDirInfo, sizeof (UDF_READ_DIRECTORY_INFO)); + + *BufferSize = 0; + Status = EFI_SUCCESS; + } + + goto Done; + } + + if (!IS_FID_PARENT_FILE (NewFileIdentifierDesc)) { + break; + } + + FreePool ((VOID *)NewFileIdentifierDesc); + } + + Status = FindFileEntry ( + BlockIo, + DiskIo, + Volume, + &NewFileIdentifierDesc->Icb, + &NewFileEntryData + ); + if (EFI_ERROR (Status)) { + goto Error_Find_Fe; + } + + if (IS_FE_SYMLINK (NewFileEntryData)) { + Status = ResolveSymlink ( + BlockIo, + DiskIo, + Volume, + Parent, + NewFileEntryData, + &FoundFile + ); + if (EFI_ERROR (Status)) { + goto Error_Resolve_Symlink; + } + + FreePool ((VOID *)NewFileEntryData); + NewFileEntryData = FoundFile.FileEntry; + + Status = GetFileNameFromFid (NewFileIdentifierDesc, FileName); + if (EFI_ERROR (Status)) { + FreePool ((VOID *)FoundFile.FileIdentifierDesc); + goto Error_Get_FileName; + } + + FreePool ((VOID *)NewFileIdentifierDesc); + NewFileIdentifierDesc = FoundFile.FileIdentifierDesc; + } else { + FoundFile.FileIdentifierDesc = NewFileIdentifierDesc; + FoundFile.FileEntry = NewFileEntryData; + + Status = GetFileNameFromFid (FoundFile.FileIdentifierDesc, FileName); + if (EFI_ERROR (Status)) { + goto Error_Get_FileName; + } + } + + Status = GetFileSize ( + BlockIo, + DiskIo, + Volume, + &FoundFile, + &FileSize + ); + if (EFI_ERROR (Status)) { + goto Error_Get_File_Size; + } + + Status = SetFileInfo ( + &FoundFile, + FileSize, + FileName, + BufferSize, + Buffer + ); + if (EFI_ERROR (Status)) { + goto Error_Set_File_Info; + } + + PrivFileData->FilePosition++; + Status = EFI_SUCCESS; + } else if (IS_FID_DELETED_FILE (Parent->FileIdentifierDesc)) { + Status = EFI_DEVICE_ERROR; + } + +Error_Set_File_Info: +Error_Get_File_Size: +Error_Get_FileName: +Error_Resolve_Symlink: + if (NewFileEntryData != NULL) { + FreePool (NewFileEntryData); + } + +Error_Find_Fe: + if (NewFileIdentifierDesc != NULL) { + FreePool ((VOID *)NewFileIdentifierDesc); + } + +Done: +Error_File_Beyond_The_Eof: +Error_Invalid_Params: + gBS->RestoreTPL (OldTpl); + + return Status; } /** @@ -346,7 +537,7 @@ UdfClose ( if (!PrivFileData->IsRootDirectory) { CleanupFileInformation (&PrivFileData->File); - if (PrivFileData->ReadDirInfo.DirectoryData) { + if (PrivFileData->ReadDirInfo.DirectoryData != NULL) { FreePool (PrivFileData->ReadDirInfo.DirectoryData); } } @@ -439,7 +630,28 @@ UdfGetPosition ( OUT UINT64 *Position ) { - return EFI_UNSUPPORTED; + PRIVATE_UDF_FILE_DATA *PrivFileData; + + if (This == NULL || Position == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This); + + // + // As per UEFI spec, if the file handle is a directory, then the current file + // position has no meaning and the operation is not supported. + // + if (IS_FID_DIRECTORY_FILE (&PrivFileData->File.FileIdentifierDesc)) { + return EFI_UNSUPPORTED; + } + + // + // The file is not a directory. So, return its position. + // + *Position = PrivFileData->FilePosition; + + return EFI_SUCCESS; } /** @@ -459,7 +671,45 @@ UdfSetPosition ( IN UINT64 Position ) { - return EFI_UNSUPPORTED; + EFI_STATUS Status; + PRIVATE_UDF_FILE_DATA *PrivFileData; + UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_UNSUPPORTED; + + PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This); + + FileIdentifierDesc = PrivFileData->File.FileIdentifierDesc; + if (IS_FID_DIRECTORY_FILE (FileIdentifierDesc)) { + // + // If the file handle is a directory, the _only_ position that may be set is + // zero. This has no effect of starting the read proccess of the directory + // entries over. + // + if (Position == 0) { + PrivFileData->FilePosition = Position; + PrivFileData->ReadDirInfo.FidOffset = 0; + Status = EFI_SUCCESS; + } + } else if (IS_FID_NORMAL_FILE (FileIdentifierDesc)) { + // + // Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to be + // set to the EOF. + // + if (Position == 0xFFFFFFFFFFFFFFFF) { + PrivFileData->FilePosition = PrivFileData->FileSize - 1; + } else { + PrivFileData->FilePosition = Position; + } + + Status = EFI_SUCCESS; + } + + return Status; } /** @@ -505,7 +755,7 @@ UdfGetInfo ( UINT64 FreeSpaceSize; CHAR16 VolumeLabel[64]; - if (This == NULL || InformationType == NULL || BufferSize == 0 || + if (This == NULL || InformationType == NULL || BufferSize == NULL || (*BufferSize != 0 && Buffer == NULL)) { return EFI_INVALID_PARAMETER; } @@ -553,7 +803,7 @@ UdfGetInfo ( // NULL-terminated OSTA compressed format, so we must check for the NULL // character. // - if (!*String) { + if (*String == L'\0') { break; } diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c index 2f7f945479..65cf8dc057 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c +++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c @@ -384,7 +384,7 @@ GetFileSetDescriptors ( for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) { FileSetDesc = AllocateZeroPool (sizeof (UDF_FILE_SET_DESCRIPTOR)); - if (!FileSetDesc) { + if (FileSetDesc == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error_Alloc_Fsd; } @@ -533,13 +533,13 @@ GetFileEntryData ( ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData; *Length = ExtendedFileEntry->InformationLength; - *Data = (VOID *)((UINT8 *)&ExtendedFileEntry->Data[0] + + *Data = (VOID *)((UINT8 *)ExtendedFileEntry->Data + ExtendedFileEntry->LengthOfExtendedAttributes); } else if (IS_FE (FileEntryData)) { FileEntry = (UDF_FILE_ENTRY *)FileEntryData; *Length = FileEntry->InformationLength; - *Data = (VOID *)((UINT8 *)&FileEntry->Data[0] + + *Data = (VOID *)((UINT8 *)FileEntry->Data + FileEntry->LengthOfExtendedAttributes); } } @@ -561,13 +561,13 @@ GetAdsInformation ( ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData; *Length = ExtendedFileEntry->LengthOfAllocationDescriptors; - *AdsData = (VOID *)((UINT8 *)&ExtendedFileEntry->Data[0] + + *AdsData = (VOID *)((UINT8 *)ExtendedFileEntry->Data + ExtendedFileEntry->LengthOfExtendedAttributes); } else if (IS_FE (FileEntryData)) { FileEntry = (UDF_FILE_ENTRY *)FileEntryData; *Length = FileEntry->LengthOfAllocationDescriptors; - *AdsData = (VOID *)((UINT8 *)&FileEntry->Data[0] + + *AdsData = (VOID *)((UINT8 *)FileEntry->Data + FileEntry->LengthOfExtendedAttributes); } } @@ -955,7 +955,7 @@ ReadFile ( // Allocate buffer for starting read data. // ReadFileInfo->FileData = AllocatePool (Length); - if (!ReadFileInfo->FileData) { + if (ReadFileInfo->FileData == NULL) { return EFI_OUT_OF_RESOURCES; } @@ -1135,7 +1135,7 @@ ReadFile ( ReadFileInfo->FilePosition += DataLength; BytesLeft -= DataLength; - if (!BytesLeft) { + if (BytesLeft == 0) { // // There is no more file data to read. // @@ -1155,7 +1155,8 @@ ReadFile ( break; case EXTENDED_ADS_SEQUENCE: - // Not supported. Haven't got a volume with that yet. + // FIXME: Not supported. Got no volume with it, yet. + ASSERT (FALSE); Status = EFI_UNSUPPORTED; break; } @@ -1214,7 +1215,7 @@ InternalFindFile ( // If FileName is current file or working directory, just duplicate Parent's // FE/EFE and FID descriptors. // - if (!StrCmp (FileName, L".")) { + if (StrCmp (FileName, L".") == 0) { DuplicateFe (BlockIo, Volume, Parent->FileEntry, &File->FileEntry); DuplicateFid (Parent->FileIdentifierDesc, &File->FileIdentifierDesc); @@ -1254,7 +1255,7 @@ InternalFindFile ( // directory (Parent), and if FileName is either ".." or "\\", then it's // the expected FID. // - if (!StrCmp (FileName, L"..") || !StrCmp (FileName, L"\\")) { + if (StrCmp (FileName, L"..") == 0 || StrCmp (FileName, L"\\") == 0) { Found = TRUE; break; } @@ -1268,14 +1269,14 @@ InternalFindFile ( } // - // OK - their filename lengths match. Now, compare if their filenames. + // OK - their filename lengths match. Now, compare their characters. // Status = GetFileNameFromFid (FileIdentifierDesc, FoundFileName); if (EFI_ERROR (Status)) { break; } - if (!StrCmp (FileName, FoundFileName)) { + if (StrCmp (FileName, FoundFileName) == 0) { // // FID has been found. Prepare to find its respective FE/EFE. // @@ -1288,7 +1289,7 @@ InternalFindFile ( FreePool ((VOID *)FileIdentifierDesc); } - if (ReadDirInfo.DirectoryData) { + if (ReadDirInfo.DirectoryData != NULL) { // // Free all allocated resources for the directory listing. // @@ -1306,7 +1307,7 @@ InternalFindFile ( // // Otherwise, find FE/EFE from the respective FID. // - if (StrCmp (FileName, L"\\")) { + if (StrCmp (FileName, L"\\") != 0) { Status = FindFileEntry ( BlockIo, DiskIo, @@ -1685,7 +1686,7 @@ FindFile ( // // Open root directory. // - if (!Root) { + if (Root == NULL) { // // There is no file found for the root directory yet. So, find only its // FID by now. @@ -1798,7 +1799,7 @@ ReadDirectoryEntry ( UDF_READ_FILE_INFO ReadFileInfo; UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc; - if (!ReadDirInfo->DirectoryData) { + if (ReadDirInfo->DirectoryData == NULL) { // // The directory's recorded data has not been read yet. So let's cache it // into memory and the next calls won't need to read it again. @@ -1873,7 +1874,7 @@ GetFileNameFromFid ( OstaCompressed = (UINT8 *)( - (UINT8 *)&FileIdentifierDesc->Data[0] + + (UINT8 *)FileIdentifierDesc->Data + FileIdentifierDesc->LengthOfImplementationUse ); @@ -2235,8 +2236,7 @@ SetFileInfo ( // FileInfoLength = sizeof (EFI_FILE_INFO) + (FileName ? StrSize (FileName) : - sizeof (CHAR16) - ); + sizeof (CHAR16)); if (*BufferSize < FileInfoLength) { // // The given Buffer has no size enough for EFI_FILE_INFO structure. @@ -2434,7 +2434,7 @@ GetVolumeSize ( Length = LogicalVolInt->NumberOfPartitions; for (Index = 0; Index < Length; Index += sizeof (UINT32)) { - LsnsNo = *(UINT32 *)((UINT8 *)&LogicalVolInt->Data[0] + Index); + LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index); if (LsnsNo == 0xFFFFFFFFUL) { // // Size not specified. @@ -2447,7 +2447,7 @@ GetVolumeSize ( Length = (LogicalVolInt->NumberOfPartitions * sizeof (UINT32)) << 1; for (; Index < Length; Index += sizeof (UINT32)) { - LsnsNo = *(UINT32 *)((UINT8 *)&LogicalVolInt->Data[0] + Index); + LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index); if (LsnsNo == 0xFFFFFFFFUL) { // // Size not specified. @@ -2470,3 +2470,63 @@ GetVolumeSize ( return EFI_SUCCESS; } + +/** + Seek a file and read its data into memory on an UDF volume. + + @param[in] BlockIo BlockIo interface. + @param[in] DiskIo DiskIo interface. + @param[in] Volume UDF volume information structure. + @param[in] File File information structure. + @param[in] FileSize Size of the file. + @param[in out] FilePosition File position. + @param[in out] Buffer File data. + @param[in out] BufferSize Read size. + + @retval EFI_SUCCESS File seeked and read. + @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_OUT_OF_RESOURCES The file's recorded data was not read due to lack + of resources. + +**/ +EFI_STATUS +ReadFileData ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN UDF_VOLUME_INFO *Volume, + IN UDF_FILE_INFO *File, + IN UINT64 FileSize, + IN OUT UINT64 *FilePosition, + IN OUT VOID *Buffer, + IN OUT UINT64 *BufferSize + ) +{ + EFI_STATUS Status; + UDF_READ_FILE_INFO ReadFileInfo; + + ReadFileInfo.Flags = READ_FILE_SEEK_AND_READ; + ReadFileInfo.FilePosition = *FilePosition; + ReadFileInfo.FileData = Buffer; + ReadFileInfo.FileDataSize = *BufferSize; + ReadFileInfo.FileSize = FileSize; + + Status = ReadFile ( + BlockIo, + DiskIo, + Volume, + &File->FileIdentifierDesc->Icb, + File->FileEntry, + &ReadFileInfo + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *BufferSize = ReadFileInfo.FileDataSize; + *FilePosition = ReadFileInfo.FilePosition; + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h index 37d7c613e1..ccea385e22 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h +++ b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h @@ -1032,6 +1032,39 @@ GetVolumeSize ( ); /** + Seek a file and read its data into memory on an UDF volume. + + @param[in] BlockIo BlockIo interface. + @param[in] DiskIo DiskIo interface. + @param[in] Volume UDF volume information structure. + @param[in] File File information structure. + @param[in] FileSize Size of the file. + @param[in out] FilePosition File position. + @param[in out] Buffer File data. + @param[in out] BufferSize Read size. + + @retval EFI_SUCCESS File seeked and read. + @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_OUT_OF_RESOURCES The file's recorded data was not read due to lack + of resources. + +**/ +EFI_STATUS +ReadFileData ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN UDF_VOLUME_INFO *Volume, + IN UDF_FILE_INFO *File, + IN UINT64 FileSize, + IN OUT UINT64 *FilePosition, + IN OUT VOID *Buffer, + IN OUT UINT64 *BufferSize + ); + +/** Mangle a filename by cutting off trailing whitespaces, "\\", "." and "..". @param[in] FileName Filename. -- 2.11.0