summaryrefslogtreecommitdiffstats
path: root/ShellPkg
diff options
context:
space:
mode:
authorRuiyu Ni <ruiyu.ni@intel.com>2016-12-21 16:04:19 +0800
committerRuiyu Ni <ruiyu.ni@intel.com>2016-12-29 09:35:14 +0800
commitd9bb3ca3c2a1bd3f7b78adf27e82e5605f665e16 (patch)
tree54e7bd39ce8c610386cec76e9f0ae87445dba20e /ShellPkg
parentbb99e3282c9e69fbd6365d117c58d15589e34c5d (diff)
downloadedk2-d9bb3ca3c2a1bd3f7b78adf27e82e5605f665e16.tar.gz
edk2-d9bb3ca3c2a1bd3f7b78adf27e82e5605f665e16.tar.bz2
edk2-d9bb3ca3c2a1bd3f7b78adf27e82e5605f665e16.zip
ShellPkg/cd: Fix "cd" to support "fs0:dir" (no slash after ':')
When "fs0:dir"(drive letter without slash) is used as destination of "cd", "cd" tries to change to "dir" in root directory of "fs0:". It's incorrect. The correct behavior is to change to "dir" in current directory of "fs0:" Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Signed-off-by: Chen A Chen <chen.a.chen@intel.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
Diffstat (limited to 'ShellPkg')
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c417
1 files changed, 241 insertions, 176 deletions
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
index 0967bc7c52..d459a7a67e 100644
--- a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
@@ -17,6 +17,156 @@
#include "UefiShellLevel2CommandsLib.h"
/**
+ Function will replace drive identifier with CWD.
+
+ If FullPath begining with ':' is invalid path, then ASSERT.
+ If FullPath not include dirve identifier , then do nothing.
+ If FullPath likes "fs0:\xx" or "fs0:/xx" , then do nothing.
+ If FullPath likes "fs0:xxx" or "fs0:", the drive replaced by CWD.
+
+ @param[in, out] FullPath The pointer to the string containing the path.
+ @param[in] Cwd Current directory.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_OUT_OF_SOURCES A memory allocation failed.
+**/
+EFI_STATUS
+ReplaceDriveWithCwd (
+ IN OUT CHAR16 **FullPath,
+ IN CONST CHAR16 *Cwd
+ )
+{
+ CHAR16 *Splitter;
+ CHAR16 *TempBuffer;
+ UINTN TotalSize;
+
+ Splitter = NULL;
+ TempBuffer = NULL;
+ TotalSize = 0;
+
+ if (FullPath == NULL || *FullPath == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Splitter = StrStr (*FullPath, L":");
+ ASSERT(Splitter != *FullPath);
+
+ if (Splitter != NULL && *(Splitter + 1) != L'\\' && *(Splitter + 1) != L'/') {
+ TotalSize = StrSize (Cwd) + StrSize (Splitter + 1);
+ TempBuffer = AllocateZeroPool (TotalSize);
+ if (TempBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd);
+ StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), L"\\");
+ StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Splitter + 1);
+
+ FreePool(*FullPath);
+ *FullPath = TempBuffer;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ function to determine if FullPath is under current filesystem.
+
+ @param[in] FullPath The target location to determine.
+ @param[in] Cwd Current directory.
+
+ @retval TRUE The FullPath is in the current filesystem.
+ @retval FALSE The FullPaht isn't in the current filesystem.
+**/
+BOOLEAN
+IsCurrentFileSystem (
+ IN CONST CHAR16 *FullPath,
+ IN CONST CHAR16 *Cwd
+ )
+{
+ CHAR16 *Splitter1;
+ CHAR16 *Splitter2;
+
+ Splitter1 = NULL;
+ Splitter2 = NULL;
+
+ ASSERT(FullPath != NULL);
+
+ Splitter1 = StrStr (FullPath, L":");
+ if (Splitter1 == NULL) {
+ return TRUE;
+ }
+
+ Splitter2 = StrStr (Cwd, L":");
+
+ if ((UINTN) (Splitter1 - FullPath) != (UINTN) (Splitter2 - Cwd)) {
+ return FALSE;
+ } else {
+ if (StrniCmp (FullPath, Cwd, (UINTN) (Splitter1 - FullPath)) == NULL) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+}
+
+/**
+ Extract drive string and path string from FullPath.
+
+ The caller must be free Drive and Path.
+
+ @param[in] FullPath A path to be extracted.
+ @param[out] Drive Buffer to save drive identifier.
+ @param[out] Path Buffer to save path.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_OUT_OF_RESOUCES A memory allocation failed.
+**/
+EFI_STATUS
+ExtractDriveAndPath (
+ IN CONST CHAR16 *FullPath,
+ OUT CHAR16 **Drive,
+ OUT CHAR16 **Path
+ )
+{
+ CHAR16 *Splitter;
+
+ ASSERT (FullPath != NULL);
+
+ Splitter = StrStr (FullPath, L":");
+
+ if (Splitter == NULL) {
+ *Drive = NULL;
+ *Path = AllocateCopyPool (StrSize (FullPath), FullPath);
+ if (*Path == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ if (*(Splitter + 1) == CHAR_NULL) {
+ *Drive = AllocateCopyPool (StrSize (FullPath), FullPath);
+ *Path = NULL;
+ if (*Drive == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ *Drive = AllocateCopyPool ((Splitter - FullPath + 2) * sizeof(CHAR16), FullPath);
+ if (*Drive == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ (*Drive)[Splitter - FullPath + 1] = CHAR_NULL;
+
+ *Path = AllocateCopyPool (StrSize (Splitter + 1), Splitter + 1);
+ if (*Path == NULL) {
+ FreePool (*Drive);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
Function for 'cd' command.
@param[in] ImageHandle Handle to the Image (NULL if Internal).
@@ -31,23 +181,26 @@ ShellCommandRunCd (
{
EFI_STATUS Status;
LIST_ENTRY *Package;
- CONST CHAR16 *Directory;
- CHAR16 *Cwd;
+ CONST CHAR16 *Cwd;
CHAR16 *Path;
CHAR16 *Drive;
- UINTN CwdSize;
- UINTN DriveSize;
CHAR16 *ProblemParam;
SHELL_STATUS ShellStatus;
- SHELL_FILE_HANDLE Handle;
CONST CHAR16 *Param1;
CHAR16 *Param1Copy;
- CHAR16* Walker;
+ CHAR16 *Walker;
+ CHAR16 *Splitter;
+ CHAR16 *TempBuffer;
+ UINTN TotalSize;
- ProblemParam = NULL;
- ShellStatus = SHELL_SUCCESS;
- Drive = NULL;
- DriveSize = 0;
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ Cwd = NULL;
+ Path = NULL;
+ Drive = NULL;
+ Splitter = NULL;
+ TempBuffer = NULL;
+ TotalSize = 0;
Status = CommandInit();
ASSERT_EFI_ERROR(Status);
@@ -87,194 +240,106 @@ ShellCommandRunCd (
// else If there are 2 value parameters, then print the error message
// else If there is 1 value paramerer , then change the directory
//
- Param1 = ShellCommandLineGetRawValue(Package, 1);
- if (Param1 == NULL) {
- //
- // display the current directory
- //
- Directory = ShellGetCurrentDir(NULL);
- if (Directory != NULL) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, Directory);
- } else {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_NOT_FOUND;
- }
+ Cwd = ShellGetCurrentDir (NULL);
+ if (Cwd == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
} else {
- Param1Copy = CatSPrint(NULL, L"%s", Param1, NULL);
- for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {
- if (*Walker == L'\"') {
- CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));
- }
- }
-
- if (Param1Copy != NULL) {
- Param1Copy = PathCleanUpDirectories(Param1Copy);
- }
- if (Param1Copy != NULL) {
- if (StrCmp(Param1Copy, L".") == 0) {
- //
- // nothing to do... change to current directory
- //
- } else if (StrCmp(Param1Copy, L"..") == 0) {
- //
- // Change up one directory...
- //
- Directory = ShellGetCurrentDir(NULL);
- if (Directory == NULL) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_NOT_FOUND;
- } else {
- CwdSize = StrSize(Directory) + sizeof(CHAR16);
- Cwd = AllocateZeroPool(CwdSize);
- if (Cwd == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_OUT_OF_RESOURCES;
- } else {
- StrCpyS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, Directory);
- StrCatS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, L"\\");
- Drive = GetFullyQualifiedPath (Cwd);
- PathRemoveLastItem (Drive);
- FreePool (Cwd);
- }
+ Param1 = ShellCommandLineGetRawValue (Package, 1);
+ if (Param1 == NULL) {
+ //
+ // display the current directory
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT), gShellLevel2HiiHandle, Cwd);
+ } else {
+ Param1Copy = CatSPrint (NULL, L"%s", Param1, NULL);
+ for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL; Walker++) {
+ if (*Walker == L'\"') {
+ CopyMem (Walker, Walker + 1, StrSize(Walker) - sizeof(Walker[0]));
}
- if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
- //
- // change directory on current drive letter
- //
- Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
- if (Status == EFI_NOT_FOUND) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_NOT_FOUND;
- }
+ }
+
+ if (Param1Copy != NULL && IsCurrentFileSystem (Param1Copy, Cwd)) {
+ Status = ReplaceDriveWithCwd (&Param1Copy,Cwd);
+ if (!EFI_ERROR (Status)) {
+ Param1Copy = PathCleanUpDirectories (Param1Copy);
}
- } else if (StrCmp(Param1Copy, L"\\") == 0) {
+ } else {
//
- // Move to root of current drive
+ // Can't use cd command to change filesystem.
//
- Directory = ShellGetCurrentDir(NULL);
- if (Directory == NULL) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_NOT_FOUND;
- } else {
- CwdSize = StrSize(Directory) + sizeof(CHAR16);
- Cwd = AllocateZeroPool(CwdSize);
- if (Cwd == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_OUT_OF_RESOURCES;
- } else {
- StrCpyS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, Directory);
- StrCatS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, L"\\");
- Drive = GetFullyQualifiedPath (Cwd);
- while (PathRemoveLastItem (Drive)) {
- //
- // Check if Drive contains 'fsx:\' only or still points to a sub-directory.
- // Don't remove trailing '\' from Drive if it points to the root directory.
- //
- Path = StrStr (Drive, L":\\");
- if ((Path != NULL) && (*(Path + 2) == CHAR_NULL)) {
- break;
- }
- }
- FreePool (Cwd);
- }
- }
- if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
+ Status = EFI_NOT_FOUND;
+ }
+
+ if (!EFI_ERROR(Status) && Param1Copy != NULL) {
+ Splitter = StrStr (Cwd, L":");
+ if (Param1Copy[0] == L'\\') {
//
- // change directory on current drive letter
+ // Absolute Path on current drive letter.
//
- Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
- if (Status == EFI_NOT_FOUND) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_NOT_FOUND;
- }
- }
- } else if (StrStr(Param1Copy, L":") == NULL) {
- //
- // change directory without a drive identifier
- //
- if (ShellGetCurrentDir(NULL) == NULL) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_NOT_FOUND;
- } else {
- ASSERT((Drive == NULL && DriveSize == 0) || (Drive != NULL));
- Drive = StrnCatGrow(&Drive, &DriveSize, ShellGetCurrentDir(NULL), 0);
- Drive = StrnCatGrow(&Drive, &DriveSize, L"\\", 0);
- if (*Param1Copy == L'\\') {
- while (PathRemoveLastItem(Drive)) ;
- Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy+1, 0);
+ TotalSize = ((Splitter - Cwd + 1) * sizeof(CHAR16)) + StrSize(Param1Copy);
+ TempBuffer = AllocateZeroPool (TotalSize);
+ if (TempBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
} else {
- Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy, 0);
- }
- //
- // Verify that this is a valid directory
- //
- Status = gEfiShellProtocol->OpenFileByName(Drive, &Handle, EFI_FILE_MODE_READ);
- if (EFI_ERROR(Status)) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Drive);
- ShellStatus = SHELL_NOT_FOUND;
- } else if (EFI_ERROR(FileHandleIsDirectory(Handle))) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Drive);
- ShellStatus = SHELL_NOT_FOUND;
+ StrnCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd, (Splitter - Cwd + 1));
+ StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Param1Copy);
+
+ FreePool (Param1Copy);
+ Param1Copy = TempBuffer;
+ TempBuffer = NULL;
}
- if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
- //
- // change directory on current drive letter
- //
- Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
- if (Status == EFI_NOT_FOUND) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ if (StrStr (Param1Copy,L":") == NULL) {
+ TotalSize = StrSize (Cwd) + StrSize (Param1Copy);
+ TempBuffer = AllocateZeroPool (TotalSize);
+ if (TempBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ StrCpyS (TempBuffer, TotalSize / sizeof (CHAR16), Cwd);
+ StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), L"\\");
+ StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), Param1Copy);
+
+ FreePool (Param1Copy);
+ Param1Copy = PathCleanUpDirectories (TempBuffer);
}
}
- if (Handle != NULL) {
- gEfiShellProtocol->CloseFile(Handle);
- DEBUG_CODE(Handle = NULL;);
- }
}
- } else {
- //
- // change directory with a drive letter
- //
- Drive = AllocateCopyPool(StrSize(Param1Copy), Param1Copy);
- if (Drive == NULL) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_OUT_OF_RESOURCES;
+ }
+
+ if (!EFI_ERROR(Status)) {
+ Status = ExtractDriveAndPath (Param1Copy, &Drive, &Path);
+ }
+
+ if (!EFI_ERROR (Status) && Drive != NULL && Path != NULL) {
+ if (EFI_ERROR(ShellIsDirectory (Param1Copy))) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy);
+ ShellStatus = SHELL_NOT_FOUND;
} else {
- Path = StrStr(Drive, L":");
- ASSERT(Path != NULL);
- if (EFI_ERROR(ShellIsDirectory(Param1Copy))) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy);
- ShellStatus = SHELL_NOT_FOUND;
- } else if (*(Path+1) == CHAR_NULL) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
+ Status = gEfiShellProtocol->SetCurDir (Drive, Path + 1);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy);
ShellStatus = SHELL_NOT_FOUND;
} else {
- *(Path+1) = CHAR_NULL;
- if (Path == Drive + StrLen(Drive)) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
- ShellStatus = SHELL_NOT_FOUND;
- } else {
- Status = gEfiShellProtocol->SetCurDir(Drive, Path+2);
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, ShellGetCurrentDir(Drive));
- }
- }
- if (Status == EFI_NOT_FOUND) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
- Status = SHELL_NOT_FOUND;
- } else if (EFI_ERROR(Status)) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy);
- Status = SHELL_NOT_FOUND;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT), gShellLevel2HiiHandle, ShellGetCurrentDir(Drive));
}
}
}
+
+ if (Drive != NULL) {
+ FreePool (Drive);
+ }
+
+ if (Path != NULL) {
+ FreePool (Path);
+ }
+
+ FreePool (Param1Copy);
}
- FreePool(Param1Copy);
}
}
- if (Drive != NULL) {
- FreePool(Drive);
- }
//
// free the command line package
//