|
|
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
marg.c Abstract:
Revision History
--*/
#include "shelle.h"
/*
* */
typedef struct _CWD { struct _CWD *Next; CHAR16 Name[1]; } SENV_CWD;
CHAR16 * SEnvFileHandleToFileName ( IN EFI_FILE_HANDLE Handle ) { UINTN BufferSize, bs; SENV_CWD *CwdHead, *Cwd; POOL_PRINT Str; EFI_FILE_INFO *Info; EFI_STATUS Status; EFI_FILE_HANDLE NextDir;
ASSERT_LOCKED(&SEnvLock);
Status = EFI_SUCCESS; CwdHead = NULL; ZeroMem (&Str, sizeof(Str));
/*
* */
Status = Handle->Open(Handle, &Handle, L".", EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { Handle = NULL; goto Done; }
BufferSize = SIZE_OF_EFI_FILE_INFO + 1024; Info = AllocatePool(BufferSize); if (!Info) { goto Done; }
/*
* Reverse out the current directory on the device */
for (; ;) { bs = BufferSize; Status = Handle->GetInfo(Handle, &GenericFileInfo, &bs, Info); if (EFI_ERROR(Status)) { goto Done; }
/*
* Allocate & chain in a new name node */
Cwd = AllocatePool (sizeof(SENV_CWD) + StrSize (Info->FileName)); if (!Cwd) { goto Done; }
StrCpy (Cwd->Name, Info->FileName);
Cwd->Next = CwdHead; CwdHead = Cwd;
/*
* Move to the parent directory */
Status = Handle->Open (Handle, &NextDir, L"..", EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { break; }
Handle->Close (Handle); Handle = NextDir; }
/*
* Build the name string of the current path */
if (CwdHead->Next) { for (Cwd=CwdHead->Next; Cwd; Cwd=Cwd->Next) { CatPrint (&Str, L"\\%s", Cwd->Name); } } else { /* must be in the root */ Str.str = StrDuplicate (L"\\"); }
Done: while (CwdHead) { Cwd = CwdHead; CwdHead = CwdHead->Next; FreePool (Cwd); }
if (Info) { FreePool (Info); }
if (Handle) { Handle->Close (Handle); }
return Str.str; }
VOID SEnvFreeFileArg ( IN SHELL_FILE_ARG *Arg ) { if (Arg->Parent) { Arg->Parent->Close (Arg->Parent); }
if (Arg->ParentName) { FreePool (Arg->ParentName); }
if (Arg->ParentDevicePath) { FreePool (Arg->ParentDevicePath); }
if (Arg->FullName) { FreePool (Arg->FullName); }
if (Arg->FileName) { FreePool (Arg->FileName); }
if (Arg->Handle) { Arg->Handle->Close (Arg->Handle); }
if (Arg->Info) { FreePool (Arg->Info); }
if (Arg->Link.Flink) { RemoveEntryList (&Arg->Link); }
FreePool(Arg); }
EFI_STATUS SEnvFreeFileList ( IN OUT LIST_ENTRY *ListHead ) { SHELL_FILE_ARG *Arg;
while (!IsListEmpty(ListHead)) { Arg = CR(ListHead->Flink, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE); SEnvFreeFileArg (Arg); }
return EFI_SUCCESS; }
SHELL_FILE_ARG * SEnvNewFileArg ( IN EFI_FILE_HANDLE Parent, IN UINT64 OpenMode, IN EFI_DEVICE_PATH *ParentPath, IN CHAR16 *ParentName, IN CHAR16 *FileName ) { SHELL_FILE_ARG *Arg; CHAR16 *LPath, *p; UINTN Len;
Arg = NULL;
/*
* Allocate a new arg structure */
Arg = AllocateZeroPool (sizeof(SHELL_FILE_ARG)); if (!Arg) { goto Done; }
Arg->Signature = SHELL_FILE_ARG_SIGNATURE; Parent->Open (Parent, &Arg->Parent, L".", OpenMode, 0); Arg->ParentDevicePath = DuplicateDevicePath (ParentPath); Arg->ParentName = StrDuplicate(ParentName); if (!Arg->Parent || !Arg->ParentDevicePath || !Arg->ParentName) { Arg->Status = EFI_OUT_OF_RESOURCES; goto Done; }
/*
* Open the target file */
Arg->Status = Parent->Open( Parent, &Arg->Handle, FileName, OpenMode, 0 );
if (Arg->Status == EFI_WRITE_PROTECTED) { OpenMode = OpenMode & ~EFI_FILE_MODE_WRITE; Arg->Status = Parent->Open ( Parent, &Arg->Handle, FileName, OpenMode, 0 ); }
Arg->OpenMode = OpenMode; if (Arg->Handle) { Arg->Info = LibFileInfo(Arg->Handle); }
/*
* Compute the file's full name */
Arg->FileName = StrDuplicate(FileName); if (StriCmp (FileName, L".") == 0) { /* it is the same as the parent */ Arg->FullName = StrDuplicate(Arg->ParentName); } else if (StriCmp(FileName, L"..") == 0) {
LPath = NULL; for (p=Arg->ParentName; *p; p++) { if (*p == L'\\') { LPath = p; } }
if (LPath) { Arg->FullName = PoolPrint(L"%.*s", (UINTN) (LPath - Arg->ParentName), Arg->ParentName); } }
if (!Arg->FullName) { /* append filename to parent's name to get the file's full name */ Len = StrLen(Arg->ParentName); if (Len && Arg->ParentName[Len-1] == '\\') { Len -= 1; }
if (FileName[0] == '\\') { FileName += 1; }
Arg->FullName = PoolPrint(L"%.*s\\%s", Len, Arg->ParentName, FileName); }
if (!Arg->FileName || !Arg->FileName) { Arg->Status = EFI_OUT_OF_RESOURCES; }
Done: if (Arg && Arg->Status == EFI_OUT_OF_RESOURCES) { SEnvFreeFileArg (Arg); Arg = NULL; }
if (Arg && !EFI_ERROR(Arg->Status) && !Arg->Handle) { Arg->Status = EFI_NOT_FOUND; } return Arg; }
EFI_STATUS SEnvFileMetaArg ( IN CHAR16 *Path, IN OUT LIST_ENTRY *ListHead ) { VARIABLE_ID *Var; EFI_STATUS Status; EFI_DEVICE_PATH *RPath, *TPath; EFI_DEVICE_PATH *ParentPath; FILEPATH_DEVICE_PATH *FilePath; EFI_FILE_INFO *Info; UINTN bs, BufferSize; EFI_FILE_HANDLE Parent; SHELL_FILE_ARG *Arg; CHAR16 *ParentName; CHAR16 *LPath, *p; UINT64 OpenMode; BOOLEAN Found;
RPath = NULL; Parent = NULL; ParentPath = NULL; ParentName = NULL;
AcquireLock (&SEnvLock);
BufferSize = SIZE_OF_EFI_FILE_INFO + 1024; Info = AllocatePool (BufferSize); if (!Info) { Status = EFI_OUT_OF_RESOURCES; goto Done; }
/*
* Get the device */
Var = SEnvMapDeviceFromName (&Path); if (!Var) { Arg = AllocateZeroPool (sizeof(SHELL_FILE_ARG)); Arg->Signature = SHELL_FILE_ARG_SIGNATURE; Arg->Status = EFI_NO_MAPPING; Arg->ParentName = StrDuplicate(Path); Arg->FullName = StrDuplicate(Path); Arg->FileName = StrDuplicate(Path); InsertTailList (ListHead, &Arg->Link); Status = EFI_SUCCESS; goto Done; }
ParentPath = DuplicateDevicePath ((EFI_DEVICE_PATH *) Var->u.Value);
/*
* If the path is realitve, append the current dir of the device to the dpath */
if (*Path != '\\') { RPath = SEnvIFileNameToPath (Var->CurDir ? Var->CurDir : L"\\"); TPath = AppendDevicePath (ParentPath, RPath); if (!RPath || !TPath) { Status = EFI_OUT_OF_RESOURCES; goto Done; }
FreePool (ParentPath); FreePool (RPath); RPath = NULL; ParentPath = TPath; }
/*
* If there is a path before the last node of the name, then * append it and strip path to the last node. */
LPath = NULL; for(p=Path; *p; p++) { if (*p == '\\') { LPath = p; } }
if (LPath) { *LPath = 0; RPath = SEnvIFileNameToPath(Path); TPath = AppendDevicePath (ParentPath, RPath); if (!RPath || !TPath) { Status = EFI_OUT_OF_RESOURCES; goto Done; }
FreePool (ParentPath); FreePool (RPath); RPath = NULL; ParentPath = TPath; Path = LPath + 1; }
/*
* Open the parent dir */
OpenMode = EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE; Parent = ShellOpenFilePath(ParentPath, OpenMode); if (!Parent) { OpenMode = EFI_FILE_MODE_READ; Parent = ShellOpenFilePath(ParentPath, OpenMode); }
if (Parent) { p = SEnvFileHandleToFileName(Parent); if (p) { ParentName = PoolPrint(L"%s:%s", Var->Name, p); FreePool (p); } }
if (!Parent) { Status = EFI_NOT_FOUND; goto Done; }
bs = BufferSize; Status = Parent->GetInfo(Parent, &GenericFileInfo, &bs, Info); if (EFI_ERROR(Status)) { goto Done; }
/*
* Parent - file handle to parent directory * ParentPath - device path of parent dir * ParentName - name string of parent directory * ParentGuid - last guid of parent path * * Path - remaining node name */
/*
* BUGBUG: if the name doesn't have any meta chars, * then just open the one file */
Found = FALSE; for (p=Path; *p && !Found; p++) { /* BUGBUG: need to handle '^' */
switch (*p) { case '*': case '[': case '?': Found = TRUE; break; } }
if (!Found) {
TPath = SEnvIFileNameToPath (Path); ASSERT (DevicePathType(TPath) == MEDIA_DEVICE_PATH && DevicePathSubType(TPath) == MEDIA_FILEPATH_DP); FilePath = (FILEPATH_DEVICE_PATH *) TPath;
Arg = SEnvNewFileArg(Parent, OpenMode, ParentPath, ParentName, FilePath->PathName); FreePool (TPath);
if (!Arg) { Status = EFI_OUT_OF_RESOURCES; goto Done; }
InsertTailList (ListHead, &Arg->Link);
} else {
/*
* Check all the files for matches */
Parent->SetPosition (Parent, 0);
Found = FALSE; for (; ;) {
/*
* Read each file entry */
bs = BufferSize; Status = Parent->Read (Parent, &bs, Info); if (EFI_ERROR(Status) || bs == 0) { break; }
/*
* Skip "." and ".." */
if (StriCmp(Info->FileName, L".") == 0 || StriCmp(Info->FileName, L"..") == 0) { continue; }
/*
* See if this one matches */
if (!MetaiMatch(Info->FileName, Path)) { continue; }
Found = TRUE; Arg = SEnvNewFileArg(Parent, OpenMode, ParentPath, ParentName, Info->FileName); if (!Arg) { Status = EFI_OUT_OF_RESOURCES; goto Done; }
InsertTailList (ListHead, &Arg->Link);
/* check next file entry */ }
/*
* If no match was found, then add a not-found entry for this name */
if (!Found) { Arg = SEnvNewFileArg(Parent, OpenMode, ParentPath, ParentName, Path); if (!Arg) { Status = EFI_OUT_OF_RESOURCES; goto Done; }
Arg->Status = EFI_NOT_FOUND; InsertTailList (ListHead, &Arg->Link); } }
/*
* Done */
Done: ReleaseLock (&SEnvLock);
if (Parent) { Parent->Close (Parent); }
if (RPath) { FreePool (RPath); }
if (ParentPath) { FreePool (ParentPath); }
if (ParentName) { FreePool (ParentName); }
if (Info) { FreePool (Info); }
return Status; }
|