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