Home | History | Annotate | Download | only in UefiShellLevel2CommandsLib
      1 /** @file
      2   Main file for attrib shell level 2 function.
      3 
      4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "UefiShellLevel2CommandsLib.h"
     17 
     18 /**
     19   Function for 'cd' command.
     20 
     21   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
     22   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
     23 **/
     24 SHELL_STATUS
     25 EFIAPI
     26 ShellCommandRunCd (
     27   IN EFI_HANDLE        ImageHandle,
     28   IN EFI_SYSTEM_TABLE  *SystemTable
     29   )
     30 {
     31   EFI_STATUS        Status;
     32   LIST_ENTRY        *Package;
     33   CONST CHAR16      *Directory;
     34   CHAR16            *Cwd;
     35   CHAR16            *Path;
     36   CHAR16            *Drive;
     37   UINTN             CwdSize;
     38   UINTN             DriveSize;
     39   CHAR16            *ProblemParam;
     40   SHELL_STATUS      ShellStatus;
     41   SHELL_FILE_HANDLE Handle;
     42   CONST CHAR16      *Param1;
     43   CHAR16            *Param1Copy;
     44   CHAR16*           Walker;
     45 
     46   ProblemParam = NULL;
     47   ShellStatus = SHELL_SUCCESS;
     48   Drive = NULL;
     49   DriveSize = 0;
     50 
     51   Status = CommandInit();
     52   ASSERT_EFI_ERROR(Status);
     53 
     54   //
     55   // initialize the shell lib (we must be in non-auto-init...)
     56   //
     57   Status = ShellInitialize();
     58   ASSERT_EFI_ERROR(Status);
     59 
     60   //
     61   // parse the command line
     62   //
     63   Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
     64   if (EFI_ERROR(Status)) {
     65     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
     66       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cd", ProblemParam);
     67       FreePool(ProblemParam);
     68       ShellStatus = SHELL_INVALID_PARAMETER;
     69     } else {
     70       ASSERT(FALSE);
     71     }
     72   }
     73 
     74   //
     75   // check for "-?"
     76   //
     77   if (ShellCommandLineGetFlag(Package, L"-?")) {
     78     ASSERT(FALSE);
     79   } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
     80     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"cd");
     81     ShellStatus = SHELL_INVALID_PARAMETER;
     82   } else {
     83     //
     84     // remember that param 0 is the command name
     85     // If there are 0 value parameters, then print the current directory
     86     // else If there are 2 value parameters, then print the error message
     87     // else If there is  1 value paramerer , then change the directory
     88     //
     89     Param1 = ShellCommandLineGetRawValue(Package, 1);
     90     if (Param1 == NULL) {
     91       //
     92       // display the current directory
     93       //
     94       Directory = ShellGetCurrentDir(NULL);
     95       if (Directory != NULL) {
     96         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, Directory);
     97       } else {
     98         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
     99         ShellStatus = SHELL_NOT_FOUND;
    100       }
    101     } else {
    102       Param1Copy = CatSPrint(NULL, L"%s", Param1, NULL);
    103       for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {
    104         if (*Walker == L'\"') {
    105           CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));
    106         }
    107       }
    108 
    109       if (Param1Copy != NULL) {
    110         Param1Copy = PathCleanUpDirectories(Param1Copy);
    111       }
    112       if (Param1Copy != NULL) {
    113         if (StrCmp(Param1Copy, L".") == 0) {
    114           //
    115           // nothing to do... change to current directory
    116           //
    117         } else if (StrCmp(Param1Copy, L"..") == 0) {
    118           //
    119           // Change up one directory...
    120           //
    121           Directory = ShellGetCurrentDir(NULL);
    122           if (Directory == NULL) {
    123             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
    124             ShellStatus = SHELL_NOT_FOUND;
    125           } else {
    126             CwdSize = StrSize(Directory) + sizeof(CHAR16);
    127             Cwd = AllocateZeroPool(CwdSize);
    128             ASSERT(Cwd!=NULL);
    129             StrCpyS(Cwd, StrSize(Directory)/sizeof(CHAR16)+1, Directory);
    130             StrCatS(Cwd, StrSize(Directory)/sizeof(CHAR16)+1, L"\\");
    131             Drive = GetFullyQualifiedPath(Cwd);
    132             PathRemoveLastItem(Drive);
    133             FreePool(Cwd);
    134           }
    135           if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
    136             //
    137             // change directory on current drive letter
    138             //
    139             Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
    140             if (Status == EFI_NOT_FOUND) {
    141               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
    142               ShellStatus = SHELL_NOT_FOUND;
    143             }
    144           }
    145         } else if (StrCmp(Param1Copy, L"\\") == 0) {
    146           //
    147           // Move to root of current drive
    148           //
    149           Directory = ShellGetCurrentDir(NULL);
    150           if (Directory == NULL) {
    151             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
    152             ShellStatus = SHELL_NOT_FOUND;
    153           } else {
    154             CwdSize = StrSize(Directory) + sizeof(CHAR16);
    155             Cwd = AllocateZeroPool(CwdSize);
    156             ASSERT(Cwd!=NULL);
    157             StrCpyS(Cwd, StrSize(Directory)/sizeof(CHAR16)+1, Directory);
    158             StrCatS(Cwd, StrSize(Directory)/sizeof(CHAR16)+1, L"\\");
    159             Drive = GetFullyQualifiedPath(Cwd);
    160             while (PathRemoveLastItem(Drive));
    161             FreePool(Cwd);
    162           }
    163           if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
    164             //
    165             // change directory on current drive letter
    166             //
    167             Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
    168             if (Status == EFI_NOT_FOUND) {
    169               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
    170               ShellStatus = SHELL_NOT_FOUND;
    171             }
    172           }
    173         } else if (StrStr(Param1Copy, L":") == NULL) {
    174           //
    175           // change directory without a drive identifier
    176           //
    177           if (ShellGetCurrentDir(NULL) == NULL) {
    178             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
    179             ShellStatus = SHELL_NOT_FOUND;
    180           } else {
    181             ASSERT((Drive == NULL && DriveSize == 0) || (Drive != NULL));
    182             Drive = StrnCatGrow(&Drive, &DriveSize, ShellGetCurrentDir(NULL), 0);
    183             Drive = StrnCatGrow(&Drive, &DriveSize, L"\\", 0);
    184             if (*Param1Copy == L'\\') {
    185               while (PathRemoveLastItem(Drive)) ;
    186               Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy+1, 0);
    187             } else {
    188               Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy, 0);
    189             }
    190             //
    191             // Verify that this is a valid directory
    192             //
    193             Status = gEfiShellProtocol->OpenFileByName(Drive, &Handle, EFI_FILE_MODE_READ);
    194             if (EFI_ERROR(Status)) {
    195               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Drive);
    196               ShellStatus = SHELL_NOT_FOUND;
    197             } else if (EFI_ERROR(FileHandleIsDirectory(Handle))) {
    198               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Drive);
    199               ShellStatus = SHELL_NOT_FOUND;
    200             }
    201             if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
    202               //
    203               // change directory on current drive letter
    204               //
    205               Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
    206               if (Status == EFI_NOT_FOUND) {
    207                 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
    208                 ShellStatus = SHELL_NOT_FOUND;
    209               }
    210             }
    211             if (Handle != NULL) {
    212               gEfiShellProtocol->CloseFile(Handle);
    213               DEBUG_CODE(Handle = NULL;);
    214             }
    215           }
    216         } else {
    217           //
    218           // change directory with a drive letter
    219           //
    220           Drive = AllocateCopyPool(StrSize(Param1Copy), Param1Copy);
    221           if (Drive == NULL) {
    222             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle, L"cd");
    223             ShellStatus = SHELL_OUT_OF_RESOURCES;
    224           } else {
    225             Path = StrStr(Drive, L":");
    226             ASSERT(Path != NULL);
    227             if (EFI_ERROR(ShellIsDirectory(Param1Copy))) {
    228               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy);
    229               ShellStatus = SHELL_NOT_FOUND;
    230             } else if (*(Path+1) == CHAR_NULL) {
    231               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
    232               ShellStatus = SHELL_NOT_FOUND;
    233             } else {
    234               *(Path+1) = CHAR_NULL;
    235               if (Path == Drive + StrLen(Drive)) {
    236                 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
    237                 ShellStatus = SHELL_NOT_FOUND;
    238               } else {
    239                 Status = gEfiShellProtocol->SetCurDir(Drive, Path+2);
    240                 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, ShellGetCurrentDir(Drive));
    241               }
    242             }
    243             if (Status == EFI_NOT_FOUND) {
    244               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
    245               Status = SHELL_NOT_FOUND;
    246             } else if (EFI_ERROR(Status)) {
    247               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy);
    248               Status = SHELL_NOT_FOUND;
    249             }
    250           }
    251         }
    252       }
    253       FreePool(Param1Copy);
    254     }
    255   }
    256 
    257   if (Drive != NULL) {
    258     FreePool(Drive);
    259   }
    260   //
    261   // free the command line package
    262   //
    263   ShellCommandLineFreeVarList (Package);
    264 
    265   //
    266   // return the status
    267   //
    268   return (ShellStatus);
    269 }
    270 
    271