]> 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
-  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
@@ -30,13 +31,17 @@ ShellCommandRunCd (
   EFI_STATUS        Status;\r
   LIST_ENTRY        *Package;\r
   CONST CHAR16      *Directory;\r
+  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
 \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
-      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
@@ -72,7 +77,7 @@ ShellCommandRunCd (
   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
@@ -90,81 +95,78 @@ ShellCommandRunCd (
       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
-      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
-        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
-          // change directory on current drive letter\r
+          // nothing to do... change to current directory\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
-          // change directory on current drive letter\r
+          // Change up one directory...\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
-          }\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
-            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
+          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
-          // Verify that this is a valid directory\r
+          // Move to root of current drive\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
+          } 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
@@ -172,33 +174,91 @@ ShellCommandRunCd (
             //\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
-          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
-      } 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
+      FreePool(Param1Copy);\r
     }\r
   }\r
 \r