\r
#include "UefiShellLevel2CommandsLib.h"\r
\r
+/**\r
+ Function will replace drive identifier with CWD.\r
+\r
+ If FullPath begining with ':' is invalid path, then ASSERT.\r
+ If FullPath not include dirve identifier , then do nothing.\r
+ If FullPath likes "fs0:\xx" or "fs0:/xx" , then do nothing.\r
+ If FullPath likes "fs0:xxx" or "fs0:", the drive replaced by CWD.\r
+\r
+ @param[in, out] FullPath The pointer to the string containing the path.\r
+ @param[in] Cwd Current directory.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_OUT_OF_SOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+ReplaceDriveWithCwd (\r
+ IN OUT CHAR16 **FullPath,\r
+ IN CONST CHAR16 *Cwd\r
+ )\r
+{\r
+ CHAR16 *Splitter;\r
+ CHAR16 *TempBuffer;\r
+ UINTN TotalSize;\r
+\r
+ Splitter = NULL;\r
+ TempBuffer = NULL;\r
+ TotalSize = 0;\r
+\r
+ if (FullPath == NULL || *FullPath == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Splitter = StrStr (*FullPath, L":");\r
+ ASSERT(Splitter != *FullPath);\r
+\r
+ if (Splitter != NULL && *(Splitter + 1) != L'\\' && *(Splitter + 1) != L'/') {\r
+ TotalSize = StrSize (Cwd) + StrSize (Splitter + 1);\r
+ TempBuffer = AllocateZeroPool (TotalSize);\r
+ if (TempBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StrCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd);\r
+ StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), L"\\");\r
+ StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Splitter + 1);\r
+\r
+ FreePool(*FullPath);\r
+ *FullPath = TempBuffer;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ function to determine if FullPath is under current filesystem.\r
+\r
+ @param[in] FullPath The target location to determine.\r
+ @param[in] Cwd Current directory.\r
+\r
+ @retval TRUE The FullPath is in the current filesystem.\r
+ @retval FALSE The FullPaht isn't in the current filesystem.\r
+**/\r
+BOOLEAN\r
+IsCurrentFileSystem (\r
+ IN CONST CHAR16 *FullPath,\r
+ IN CONST CHAR16 *Cwd\r
+ )\r
+{\r
+ CHAR16 *Splitter1;\r
+ CHAR16 *Splitter2;\r
+\r
+ Splitter1 = NULL;\r
+ Splitter2 = NULL;\r
+\r
+ ASSERT(FullPath != NULL);\r
+\r
+ Splitter1 = StrStr (FullPath, L":");\r
+ if (Splitter1 == NULL) {\r
+ return TRUE;\r
+ }\r
+\r
+ Splitter2 = StrStr (Cwd, L":");\r
+\r
+ if ((UINTN) (Splitter1 - FullPath) != (UINTN) (Splitter2 - Cwd)) {\r
+ return FALSE;\r
+ } else {\r
+ if (StrniCmp (FullPath, Cwd, (UINTN) (Splitter1 - FullPath)) == NULL) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Extract drive string and path string from FullPath.\r
+\r
+ The caller must be free Drive and Path.\r
+\r
+ @param[in] FullPath A path to be extracted.\r
+ @param[out] Drive Buffer to save drive identifier.\r
+ @param[out] Path Buffer to save path.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_OUT_OF_RESOUCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+ExtractDriveAndPath (\r
+ IN CONST CHAR16 *FullPath,\r
+ OUT CHAR16 **Drive,\r
+ OUT CHAR16 **Path\r
+ )\r
+{\r
+ CHAR16 *Splitter;\r
+\r
+ ASSERT (FullPath != NULL);\r
+\r
+ Splitter = StrStr (FullPath, L":");\r
+\r
+ if (Splitter == NULL) {\r
+ *Drive = NULL;\r
+ *Path = AllocateCopyPool (StrSize (FullPath), FullPath);\r
+ if (*Path == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ if (*(Splitter + 1) == CHAR_NULL) {\r
+ *Drive = AllocateCopyPool (StrSize (FullPath), FullPath);\r
+ *Path = NULL;\r
+ if (*Drive == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ *Drive = AllocateCopyPool ((Splitter - FullPath + 2) * sizeof(CHAR16), FullPath);\r
+ if (*Drive == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ (*Drive)[Splitter - FullPath + 1] = CHAR_NULL;\r
+\r
+ *Path = AllocateCopyPool (StrSize (Splitter + 1), Splitter + 1);\r
+ if (*Path == NULL) {\r
+ FreePool (*Drive);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Function for 'cd' command.\r
\r
{\r
EFI_STATUS Status;\r
LIST_ENTRY *Package;\r
- CONST CHAR16 *Directory;\r
- CHAR16 *Cwd;\r
+ CONST CHAR16 *Cwd;\r
CHAR16 *Path;\r
CHAR16 *Drive;\r
- UINTN CwdSize;\r
- UINTN DriveSize;\r
CHAR16 *ProblemParam;\r
SHELL_STATUS ShellStatus;\r
- SHELL_FILE_HANDLE Handle;\r
CONST CHAR16 *Param1;\r
CHAR16 *Param1Copy;\r
- CHAR16* Walker;\r
+ CHAR16 *Walker;\r
+ CHAR16 *Splitter;\r
+ CHAR16 *TempBuffer;\r
+ UINTN TotalSize;\r
\r
- ProblemParam = NULL;\r
- ShellStatus = SHELL_SUCCESS;\r
- Drive = NULL;\r
- DriveSize = 0;\r
+ ProblemParam = NULL;\r
+ ShellStatus = SHELL_SUCCESS;\r
+ Cwd = NULL;\r
+ Path = NULL;\r
+ Drive = NULL;\r
+ Splitter = NULL;\r
+ TempBuffer = NULL;\r
+ TotalSize = 0;\r
\r
Status = CommandInit();\r
ASSERT_EFI_ERROR(Status);\r
// else If there are 2 value parameters, then print the error message\r
// else If there is 1 value paramerer , then change the directory\r
//\r
- Param1 = ShellCommandLineGetRawValue(Package, 1);\r
- if (Param1 == NULL) {\r
- //\r
- // display the current directory\r
- //\r
- Directory = ShellGetCurrentDir(NULL);\r
- if (Directory != NULL) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, Directory);\r
- } else {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd"); \r
- ShellStatus = SHELL_NOT_FOUND;\r
- }\r
+ Cwd = ShellGetCurrentDir (NULL);\r
+ if (Cwd == NULL) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");\r
+ ShellStatus = SHELL_NOT_FOUND;\r
} else {\r
- Param1Copy = CatSPrint(NULL, L"%s", Param1, NULL);\r
- for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {\r
- if (*Walker == L'\"') {\r
- CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));\r
- }\r
- }\r
- \r
- if (Param1Copy != NULL) {\r
- Param1Copy = PathCleanUpDirectories(Param1Copy);\r
- }\r
- if (Param1Copy != NULL) {\r
- if (StrCmp(Param1Copy, L".") == 0) {\r
- //\r
- // nothing to do... change to current directory\r
- //\r
- } else if (StrCmp(Param1Copy, L"..") == 0) {\r
- //\r
- // Change up one directory...\r
- //\r
- Directory = ShellGetCurrentDir(NULL);\r
- if (Directory == NULL) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd"); \r
- ShellStatus = SHELL_NOT_FOUND;\r
- } else {\r
- CwdSize = StrSize(Directory) + sizeof(CHAR16);\r
- Cwd = AllocateZeroPool(CwdSize);\r
- if (Cwd == NULL) {\r
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cd");\r
- ShellStatus = SHELL_OUT_OF_RESOURCES;\r
- } else {\r
- StrCpyS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, Directory);\r
- StrCatS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, L"\\");\r
- Drive = GetFullyQualifiedPath (Cwd);\r
- PathRemoveLastItem (Drive);\r
- FreePool (Cwd);\r
- }\r
+ Param1 = ShellCommandLineGetRawValue (Package, 1);\r
+ if (Param1 == NULL) {\r
+ //\r
+ // display the current directory\r
+ //\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT), gShellLevel2HiiHandle, Cwd);\r
+ } else {\r
+ Param1Copy = CatSPrint (NULL, L"%s", Param1, NULL);\r
+ for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL; Walker++) {\r
+ if (*Walker == L'\"') {\r
+ CopyMem (Walker, Walker + 1, StrSize(Walker) - sizeof(Walker[0]));\r
}\r
- if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {\r
- //\r
- // change directory on current drive letter\r
- //\r
- Status = gEfiShellProtocol->SetCurDir(NULL, Drive);\r
- if (Status == EFI_NOT_FOUND) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd"); \r
- ShellStatus = SHELL_NOT_FOUND;\r
- }\r
+ }\r
+\r
+ if (Param1Copy != NULL && IsCurrentFileSystem (Param1Copy, Cwd)) {\r
+ Status = ReplaceDriveWithCwd (&Param1Copy,Cwd);\r
+ if (!EFI_ERROR (Status)) {\r
+ Param1Copy = PathCleanUpDirectories (Param1Copy);\r
}\r
- } else if (StrCmp(Param1Copy, L"\\") == 0) {\r
+ } else {\r
//\r
- // Move to root of current drive\r
+ // Can't use cd command to change filesystem.\r
//\r
- Directory = ShellGetCurrentDir(NULL);\r
- if (Directory == NULL) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd"); \r
- ShellStatus = SHELL_NOT_FOUND;\r
- } else {\r
- CwdSize = StrSize(Directory) + sizeof(CHAR16);\r
- Cwd = AllocateZeroPool(CwdSize);\r
- if (Cwd == NULL) {\r
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cd");\r
- ShellStatus = SHELL_OUT_OF_RESOURCES;\r
- } else {\r
- StrCpyS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, Directory);\r
- StrCatS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, L"\\");\r
- Drive = GetFullyQualifiedPath (Cwd);\r
- while (PathRemoveLastItem (Drive)) {\r
- //\r
- // Check if Drive contains 'fsx:\' only or still points to a sub-directory.\r
- // Don't remove trailing '\' from Drive if it points to the root directory.\r
- //\r
- Path = StrStr (Drive, L":\\");\r
- if ((Path != NULL) && (*(Path + 2) == CHAR_NULL)) {\r
- break;\r
- }\r
- }\r
- FreePool (Cwd);\r
- }\r
- }\r
- if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (!EFI_ERROR(Status) && Param1Copy != NULL) {\r
+ Splitter = StrStr (Cwd, L":");\r
+ if (Param1Copy[0] == L'\\') {\r
//\r
- // change directory on current drive letter\r
+ // Absolute Path on current drive letter.\r
//\r
- Status = gEfiShellProtocol->SetCurDir(NULL, Drive);\r
- if (Status == EFI_NOT_FOUND) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd"); \r
- ShellStatus = SHELL_NOT_FOUND;\r
- }\r
- }\r
- } else if (StrStr(Param1Copy, L":") == NULL) {\r
- //\r
- // change directory without a drive identifier\r
- //\r
- if (ShellGetCurrentDir(NULL) == NULL) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd"); \r
- ShellStatus = SHELL_NOT_FOUND;\r
- } else {\r
- ASSERT((Drive == NULL && DriveSize == 0) || (Drive != NULL));\r
- Drive = StrnCatGrow(&Drive, &DriveSize, ShellGetCurrentDir(NULL), 0);\r
- Drive = StrnCatGrow(&Drive, &DriveSize, L"\\", 0);\r
- if (*Param1Copy == L'\\') {\r
- while (PathRemoveLastItem(Drive)) ;\r
- Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy+1, 0);\r
+ TotalSize = ((Splitter - Cwd + 1) * sizeof(CHAR16)) + StrSize(Param1Copy);\r
+ TempBuffer = AllocateZeroPool (TotalSize);\r
+ if (TempBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
} else {\r
- Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy, 0);\r
- }\r
- //\r
- // Verify that this is a valid directory\r
- //\r
- Status = gEfiShellProtocol->OpenFileByName(Drive, &Handle, EFI_FILE_MODE_READ);\r
- if (EFI_ERROR(Status)) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Drive); \r
- ShellStatus = SHELL_NOT_FOUND;\r
- } else if (EFI_ERROR(FileHandleIsDirectory(Handle))) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Drive); \r
- ShellStatus = SHELL_NOT_FOUND;\r
+ StrnCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd, (Splitter - Cwd + 1));\r
+ StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Param1Copy);\r
+\r
+ FreePool (Param1Copy);\r
+ Param1Copy = TempBuffer;\r
+ TempBuffer = NULL;\r
}\r
- if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {\r
- //\r
- // change directory on current drive letter\r
- //\r
- Status = gEfiShellProtocol->SetCurDir(NULL, Drive);\r
- if (Status == EFI_NOT_FOUND) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd"); \r
- ShellStatus = SHELL_NOT_FOUND;\r
+ } else {\r
+ if (StrStr (Param1Copy,L":") == NULL) {\r
+ TotalSize = StrSize (Cwd) + StrSize (Param1Copy);\r
+ TempBuffer = AllocateZeroPool (TotalSize);\r
+ if (TempBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ StrCpyS (TempBuffer, TotalSize / sizeof (CHAR16), Cwd);\r
+ StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), L"\\");\r
+ StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), Param1Copy);\r
+\r
+ FreePool (Param1Copy);\r
+ Param1Copy = PathCleanUpDirectories (TempBuffer);\r
}\r
}\r
- if (Handle != NULL) {\r
- gEfiShellProtocol->CloseFile(Handle);\r
- DEBUG_CODE(Handle = NULL;);\r
- }\r
}\r
- } else {\r
- //\r
- // change directory with a drive letter\r
- //\r
- Drive = AllocateCopyPool(StrSize(Param1Copy), Param1Copy);\r
- if (Drive == NULL) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle, L"cd"); \r
- ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = ExtractDriveAndPath (Param1Copy, &Drive, &Path);\r
+ }\r
+\r
+ if (!EFI_ERROR (Status) && Drive != NULL && Path != NULL) {\r
+ if (EFI_ERROR(ShellIsDirectory (Param1Copy))) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy);\r
+ ShellStatus = SHELL_NOT_FOUND;\r
} else {\r
- Path = StrStr(Drive, L":");\r
- ASSERT(Path != NULL);\r
- if (EFI_ERROR(ShellIsDirectory(Param1Copy))) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy); \r
- ShellStatus = SHELL_NOT_FOUND;\r
- } else if (*(Path+1) == CHAR_NULL) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd"); \r
+ Status = gEfiShellProtocol->SetCurDir (Drive, Path + 1);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy);\r
ShellStatus = SHELL_NOT_FOUND;\r
} else {\r
- *(Path+1) = CHAR_NULL;\r
- if (Path == Drive + StrLen(Drive)) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd"); \r
- ShellStatus = SHELL_NOT_FOUND;\r
- } else {\r
- Status = gEfiShellProtocol->SetCurDir(Drive, Path+2);\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, ShellGetCurrentDir(Drive));\r
- }\r
- }\r
- if (Status == EFI_NOT_FOUND) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd"); \r
- Status = SHELL_NOT_FOUND;\r
- } else if (EFI_ERROR(Status)) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy); \r
- Status = SHELL_NOT_FOUND;\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT), gShellLevel2HiiHandle, ShellGetCurrentDir(Drive));\r
}\r
}\r
}\r
+\r
+ if (Drive != NULL) {\r
+ FreePool (Drive);\r
+ }\r
+\r
+ if (Path != NULL) {\r
+ FreePool (Path);\r
+ }\r
+\r
+ FreePool (Param1Copy);\r
}\r
- FreePool(Param1Copy);\r
}\r
}\r
\r
- if (Drive != NULL) {\r
- FreePool(Drive);\r
- }\r
//\r
// free the command line package\r
//\r