]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
ShellPkg/Level2Command: Use UnicodeCollation in StrinCmp
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Cd.c
index c753702e816be46ff7489d552ff6cb72049b22fb..d5dc9804d4dc33c148bf575e0dc0ee00d6e9f2bb 100644 (file)
@@ -1,7 +1,9 @@
 /** @file\r
   Main file for attrib shell level 2 function.\r
 \r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright (c) 2009 - 2018, 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
 \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 - (UINTN) FullPath) != ((UINTN) Splitter2 - (UINTN) Cwd)) {\r
+    return FALSE;\r
+  } else {\r
+    if (StrniCmp (FullPath, Cwd, ((UINTN) Splitter1 - (UINTN) FullPath) / sizeof (CHAR16)) == 0) {\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
@@ -29,20 +181,26 @@ ShellCommandRunCd (
 {\r
   EFI_STATUS        Status;\r
   LIST_ENTRY        *Package;\r
-  CONST CHAR16      *Directory;\r
+  CONST CHAR16      *Cwd;\r
   CHAR16            *Path;\r
   CHAR16            *Drive;\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            *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
@@ -59,7 +217,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
@@ -73,7 +231,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
@@ -82,149 +240,104 @@ ShellCommandRunCd (
     // 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);\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
-      Param1Copy = PathCleanUpDirectories(Param1Copy);\r
-      if (StrCmp(Param1Copy, L".") == 0) {\r
+      Param1 = ShellCommandLineGetRawValue (Package, 1);\r
+      if (Param1 == NULL) {\r
         //\r
-        // nothing to do... change to current directory\r
+        // display the 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);\r
-          ShellStatus = SHELL_NOT_FOUND;\r
-        } else {\r
-          Drive = GetFullyQualifiedPath(Directory);\r
-          PathRemoveLastItem(Drive);\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);\r
-            ShellStatus = SHELL_NOT_FOUND;\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
         }\r
-      } else if (StrCmp(Param1Copy, 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 (PathRemoveLastItem(Drive)) ;\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);\r
-            ShellStatus = SHELL_NOT_FOUND;\r
+\r
+        if (Param1Copy != NULL && IsCurrentFileSystem (Param1Copy, Cwd)) {\r
+          Status = ReplaceDriveWithCwd (&Param1Copy,Cwd);\r
+          if (!EFI_ERROR (Status)) {\r
+            Param1Copy = PathCleanUpDirectories (Param1Copy);\r
           }\r
-        }\r
-      } else if (StrStr(Param1Copy, 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 (*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
+          // Can't use cd command to change filesystem.\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
-            ShellStatus = SHELL_NOT_FOUND;\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);\r
-              ShellStatus = SHELL_NOT_FOUND;\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
+              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
+          } 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
-          }\r
-          if (Handle != NULL) {\r
-            gEfiShellProtocol->CloseFile(Handle);\r
-            DEBUG_CODE(Handle = NULL;);\r
           }\r
         }\r
-      } else {\r
-        //\r
-        // change directory on other drive letter\r
-        //\r
-        Drive = AllocateZeroPool(StrSize(Param1Copy));\r
-        if (Drive == NULL) {\r
-          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle);\r
-          ShellStatus = SHELL_OUT_OF_RESOURCES;\r
-        } else {\r
-          Drive = StrCpy(Drive, Param1Copy);\r
-          Path = StrStr(Drive, L":");\r
-          ASSERT(Path != NULL);\r
-          if (*(Path+1) == CHAR_NULL) {\r
-            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);\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+1) = CHAR_NULL;\r
-            if (Path == Drive + StrLen(Drive)) {\r
-              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);\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
-              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);\r
-            Status = SHELL_NOT_FOUND;\r
-          } else if (EFI_ERROR(Status)) {\r
-            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, Param1Copy);\r
-            Status = SHELL_NOT_FOUND;\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