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