]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
ShellPkg/Cp: Handle memory allocation failure
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Cd.c
index 78403c22748bae815907aed756d1dd99a02a9047..2e51b4cb4dd152e18e6daeda11e0fe83a65ff488 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
   Main file for attrib shell level 2 function.\r
 \r
 /** @file\r
   Main file for attrib shell level 2 function.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -30,13 +31,17 @@ ShellCommandRunCd (
   EFI_STATUS        Status;\r
   LIST_ENTRY        *Package;\r
   CONST CHAR16      *Directory;\r
   EFI_STATUS        Status;\r
   LIST_ENTRY        *Package;\r
   CONST CHAR16      *Directory;\r
+  CHAR16            *Cwd;\r
   CHAR16            *Path;\r
   CHAR16            *Drive;\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
   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
 \r
   ProblemParam = NULL;\r
   ShellStatus = SHELL_SUCCESS;\r
 \r
   ProblemParam = NULL;\r
   ShellStatus = SHELL_SUCCESS;\r
@@ -58,7 +63,7 @@ ShellCommandRunCd (
   Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);\r
   if (EFI_ERROR(Status)) {\r
     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
   Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);\r
   if (EFI_ERROR(Status)) {\r
     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
-      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cd", ProblemParam);  \r
       FreePool(ProblemParam);\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
     } else {\r
       FreePool(ProblemParam);\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
     } else {\r
@@ -72,7 +77,7 @@ ShellCommandRunCd (
   if (ShellCommandLineGetFlag(Package, L"-?")) {\r
     ASSERT(FALSE);\r
   } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {\r
   if (ShellCommandLineGetFlag(Package, L"-?")) {\r
     ASSERT(FALSE);\r
   } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {\r
-    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"cd");  \r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
   } else {\r
     //\r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
   } else {\r
     //\r
@@ -90,81 +95,78 @@ ShellCommandRunCd (
       if (Directory != NULL) {\r
         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, Directory);\r
       } else {\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);\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");  \r
         ShellStatus = SHELL_NOT_FOUND;\r
       }\r
     } else {\r
         ShellStatus = SHELL_NOT_FOUND;\r
       }\r
     } else {\r
-      if (StrCmp(Param1, L".") == 0) {\r
-        //\r
-        // nothing to do... change to current directory\r
-        //\r
-      } else if (StrCmp(Param1, 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);\r
-          ShellStatus = SHELL_NOT_FOUND;\r
-        } else {\r
-          Drive = GetFullyQualifiedPath(Directory);\r
-          ChopLastSlash(Drive);\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
-        if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {\r
+      }\r
+      \r
+      if (Param1Copy != NULL) {\r
+        Param1Copy = PathCleanUpDirectories(Param1Copy);\r
+      }\r
+      if (Param1Copy != NULL) {\r
+        if (StrCmp(Param1Copy, L".") == 0) {\r
           //\r
           //\r
-          // change directory on current drive letter\r
+          // nothing to do... change to current directory\r
           //\r
           //\r
-          Status = gEfiShellProtocol->SetCurDir(NULL, Drive);\r
-          if (Status == EFI_NOT_FOUND) {\r
-            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);\r
-            ShellStatus = SHELL_NOT_FOUND;\r
-          }\r
-        }\r
-      } else if (StrCmp(Param1, L"\\") == 0) {\r
-        //\r
-        // Move to root of current drive\r
-        //\r
-        Directory = ShellGetCurrentDir(NULL);\r
-        if (Directory == NULL) {\r
-          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);\r
-          ShellStatus = SHELL_NOT_FOUND;\r
-        } else {\r
-          Drive = GetFullyQualifiedPath(Directory);\r
-          while (ChopLastSlash(Drive)) ;\r
-        }\r
-        if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {\r
+        } else if (StrCmp(Param1Copy, L"..") == 0) {\r
           //\r
           //\r
-          // change directory on current drive letter\r
+          // Change up one directory...\r
           //\r
           //\r
-          Status = gEfiShellProtocol->SetCurDir(NULL, Drive);\r
-          if (Status == EFI_NOT_FOUND) {\r
-            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);\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
             ShellStatus = SHELL_NOT_FOUND;\r
-          }\r
-        }\r
-      } else if (StrStr(Param1, L":") == NULL) {\r
-        if (ShellGetCurrentDir(NULL) == NULL) {\r
-          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);\r
-          ShellStatus = SHELL_NOT_FOUND;\r
-        } else {\r
-          ASSERT((Drive == NULL && DriveSize == 0) || (Drive != NULL));\r
-          Drive = StrnCatGrow(&Drive, &DriveSize, ShellGetCurrentDir(NULL), 0);\r
-          if (*Param1 == L'\\') {\r
-            while (ChopLastSlash(Drive)) ;\r
-            Drive = StrnCatGrow(&Drive, &DriveSize, Param1+1, 0);\r
           } else {\r
           } else {\r
-            Drive = StrnCatGrow(&Drive, &DriveSize, Param1, 0);\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
           }\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
+        } else if (StrCmp(Param1Copy, L"\\") == 0) {\r
           //\r
           //\r
-          // Verify that this is a valid directory\r
+          // Move to root of current drive\r
           //\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, 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, Drive);\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
             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
+              FreePool (Cwd);\r
+            }\r
           }\r
           if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {\r
             //\r
           }\r
           if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {\r
             //\r
@@ -172,33 +174,91 @@ ShellCommandRunCd (
             //\r
             Status = gEfiShellProtocol->SetCurDir(NULL, Drive);\r
             if (Status == EFI_NOT_FOUND) {\r
             //\r
             Status = gEfiShellProtocol->SetCurDir(NULL, Drive);\r
             if (Status == EFI_NOT_FOUND) {\r
-              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);\r
+              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");  \r
               ShellStatus = SHELL_NOT_FOUND;\r
             }\r
           }\r
               ShellStatus = SHELL_NOT_FOUND;\r
             }\r
           }\r
-          if (Handle != NULL) {\r
-            gEfiShellProtocol->CloseFile(Handle);\r
-            DEBUG_CODE(Handle = NULL;);\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
+            } 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
+            }\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
+            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
+          } 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
+              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
+            }\r
           }\r
           }\r
-        }\r
-      } else {\r
-        //\r
-        // change directory on other drive letter\r
-        //\r
-        Drive = AllocateZeroPool(StrSize(Param1));\r
-        Drive = StrCpy(Drive, Param1);\r
-        Path = StrStr(Drive, L":");\r
-        *(++Path) = CHAR_NULL;\r
-        Status = gEfiShellProtocol->SetCurDir(Drive, ++Path);\r
-\r
-        if (Status == EFI_NOT_FOUND) {\r
-          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);\r
-          Status = SHELL_NOT_FOUND;\r
-        } else if (EFI_ERROR(Status)) {\r
-          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, Param1);\r
-          Status = SHELL_NOT_FOUND;\r
         }\r
       }\r
         }\r
       }\r
+      FreePool(Param1Copy);\r
     }\r
   }\r
 \r
     }\r
   }\r
 \r