]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
ShellPkg/Level2Command: Use UnicodeCollation in StrinCmp
[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
630cb850 6 Copyright (c) 2009 - 2018, 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
d9bb3ca3
RN
19/**\r
20 Function will replace drive identifier with CWD.\r
21\r
22 If FullPath begining with ':' is invalid path, then ASSERT.\r
23 If FullPath not include dirve identifier , then do nothing.\r
24 If FullPath likes "fs0:\xx" or "fs0:/xx" , then do nothing.\r
25 If FullPath likes "fs0:xxx" or "fs0:", the drive replaced by CWD.\r
26\r
27 @param[in, out] FullPath The pointer to the string containing the path.\r
28 @param[in] Cwd Current directory.\r
29\r
30 @retval EFI_SUCCESS Success.\r
31 @retval EFI_OUT_OF_SOURCES A memory allocation failed.\r
32**/\r
33EFI_STATUS\r
34ReplaceDriveWithCwd (\r
35 IN OUT CHAR16 **FullPath,\r
36 IN CONST CHAR16 *Cwd\r
37 )\r
38{\r
39 CHAR16 *Splitter;\r
40 CHAR16 *TempBuffer;\r
41 UINTN TotalSize;\r
42\r
43 Splitter = NULL;\r
44 TempBuffer = NULL;\r
45 TotalSize = 0;\r
46\r
47 if (FullPath == NULL || *FullPath == NULL) {\r
48 return EFI_SUCCESS;\r
49 }\r
50\r
51 Splitter = StrStr (*FullPath, L":");\r
52 ASSERT(Splitter != *FullPath);\r
53\r
54 if (Splitter != NULL && *(Splitter + 1) != L'\\' && *(Splitter + 1) != L'/') {\r
55 TotalSize = StrSize (Cwd) + StrSize (Splitter + 1);\r
56 TempBuffer = AllocateZeroPool (TotalSize);\r
57 if (TempBuffer == NULL) {\r
58 return EFI_OUT_OF_RESOURCES;\r
59 }\r
60\r
61 StrCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd);\r
62 StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), L"\\");\r
63 StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Splitter + 1);\r
64\r
65 FreePool(*FullPath);\r
66 *FullPath = TempBuffer;\r
67 }\r
68\r
69 return EFI_SUCCESS;\r
70}\r
71\r
72/**\r
73 function to determine if FullPath is under current filesystem.\r
74\r
75 @param[in] FullPath The target location to determine.\r
76 @param[in] Cwd Current directory.\r
77\r
78 @retval TRUE The FullPath is in the current filesystem.\r
79 @retval FALSE The FullPaht isn't in the current filesystem.\r
80**/\r
81BOOLEAN\r
82IsCurrentFileSystem (\r
83 IN CONST CHAR16 *FullPath,\r
84 IN CONST CHAR16 *Cwd\r
85 )\r
86{\r
87 CHAR16 *Splitter1;\r
88 CHAR16 *Splitter2;\r
89\r
90 Splitter1 = NULL;\r
91 Splitter2 = NULL;\r
92\r
93 ASSERT(FullPath != NULL);\r
94\r
95 Splitter1 = StrStr (FullPath, L":");\r
96 if (Splitter1 == NULL) {\r
97 return TRUE;\r
98 }\r
99\r
100 Splitter2 = StrStr (Cwd, L":");\r
101\r
810c635d 102 if (((UINTN) Splitter1 - (UINTN) FullPath) != ((UINTN) Splitter2 - (UINTN) Cwd)) {\r
d9bb3ca3
RN
103 return FALSE;\r
104 } else {\r
630cb850 105 if (StrniCmp (FullPath, Cwd, ((UINTN) Splitter1 - (UINTN) FullPath) / sizeof (CHAR16)) == 0) {\r
d9bb3ca3
RN
106 return TRUE;\r
107 } else {\r
108 return FALSE;\r
109 }\r
110 }\r
111}\r
112\r
113/**\r
114 Extract drive string and path string from FullPath.\r
115\r
116 The caller must be free Drive and Path.\r
117\r
118 @param[in] FullPath A path to be extracted.\r
119 @param[out] Drive Buffer to save drive identifier.\r
120 @param[out] Path Buffer to save path.\r
121\r
122 @retval EFI_SUCCESS Success.\r
123 @retval EFI_OUT_OF_RESOUCES A memory allocation failed.\r
124**/\r
125EFI_STATUS\r
126ExtractDriveAndPath (\r
127 IN CONST CHAR16 *FullPath,\r
128 OUT CHAR16 **Drive,\r
129 OUT CHAR16 **Path\r
130 )\r
131{\r
132 CHAR16 *Splitter;\r
133\r
134 ASSERT (FullPath != NULL);\r
135\r
136 Splitter = StrStr (FullPath, L":");\r
137\r
138 if (Splitter == NULL) {\r
139 *Drive = NULL;\r
140 *Path = AllocateCopyPool (StrSize (FullPath), FullPath);\r
141 if (*Path == NULL) {\r
142 return EFI_OUT_OF_RESOURCES;\r
143 }\r
144 } else {\r
145 if (*(Splitter + 1) == CHAR_NULL) {\r
146 *Drive = AllocateCopyPool (StrSize (FullPath), FullPath);\r
147 *Path = NULL;\r
148 if (*Drive == NULL) {\r
149 return EFI_OUT_OF_RESOURCES;\r
150 }\r
151 } else {\r
152 *Drive = AllocateCopyPool ((Splitter - FullPath + 2) * sizeof(CHAR16), FullPath);\r
153 if (*Drive == NULL) {\r
154 return EFI_OUT_OF_RESOURCES;\r
155 }\r
156 (*Drive)[Splitter - FullPath + 1] = CHAR_NULL;\r
157\r
158 *Path = AllocateCopyPool (StrSize (Splitter + 1), Splitter + 1);\r
159 if (*Path == NULL) {\r
160 FreePool (*Drive);\r
161 return EFI_OUT_OF_RESOURCES;\r
162 }\r
163 }\r
164 }\r
165\r
166 return EFI_SUCCESS;\r
167}\r
168\r
a405b86d 169/**\r
170 Function for 'cd' command.\r
171\r
172 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
173 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
174**/\r
175SHELL_STATUS\r
176EFIAPI\r
177ShellCommandRunCd (\r
178 IN EFI_HANDLE ImageHandle,\r
179 IN EFI_SYSTEM_TABLE *SystemTable\r
180 )\r
181{\r
182 EFI_STATUS Status;\r
183 LIST_ENTRY *Package;\r
d9bb3ca3 184 CONST CHAR16 *Cwd;\r
a405b86d 185 CHAR16 *Path;\r
186 CHAR16 *Drive;\r
a405b86d 187 CHAR16 *ProblemParam;\r
188 SHELL_STATUS ShellStatus;\r
a405b86d 189 CONST CHAR16 *Param1;\r
1fc3749d 190 CHAR16 *Param1Copy;\r
d9bb3ca3
RN
191 CHAR16 *Walker;\r
192 CHAR16 *Splitter;\r
193 CHAR16 *TempBuffer;\r
194 UINTN TotalSize;\r
a405b86d 195\r
d9bb3ca3
RN
196 ProblemParam = NULL;\r
197 ShellStatus = SHELL_SUCCESS;\r
198 Cwd = NULL;\r
199 Path = NULL;\r
200 Drive = NULL;\r
201 Splitter = NULL;\r
202 TempBuffer = NULL;\r
203 TotalSize = 0;\r
a405b86d 204\r
205 Status = CommandInit();\r
206 ASSERT_EFI_ERROR(Status);\r
207\r
208 //\r
209 // initialize the shell lib (we must be in non-auto-init...)\r
210 //\r
211 Status = ShellInitialize();\r
212 ASSERT_EFI_ERROR(Status);\r
213\r
214 //\r
215 // parse the command line\r
216 //\r
217 Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);\r
218 if (EFI_ERROR(Status)) {\r
219 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
099e8ff5 220 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cd", ProblemParam); \r
a405b86d 221 FreePool(ProblemParam);\r
222 ShellStatus = SHELL_INVALID_PARAMETER;\r
223 } else {\r
224 ASSERT(FALSE);\r
225 }\r
226 }\r
227\r
228 //\r
229 // check for "-?"\r
230 //\r
231 if (ShellCommandLineGetFlag(Package, L"-?")) {\r
232 ASSERT(FALSE);\r
233 } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {\r
099e8ff5 234 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"cd"); \r
a405b86d 235 ShellStatus = SHELL_INVALID_PARAMETER;\r
236 } else {\r
237 //\r
238 // remember that param 0 is the command name\r
239 // If there are 0 value parameters, then print the current directory\r
240 // else If there are 2 value parameters, then print the error message\r
241 // else If there is 1 value paramerer , then change the directory\r
242 //\r
d9bb3ca3
RN
243 Cwd = ShellGetCurrentDir (NULL);\r
244 if (Cwd == NULL) {\r
245 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");\r
246 ShellStatus = SHELL_NOT_FOUND;\r
a405b86d 247 } else {\r
d9bb3ca3
RN
248 Param1 = ShellCommandLineGetRawValue (Package, 1);\r
249 if (Param1 == NULL) {\r
250 //\r
251 // display the current directory\r
252 //\r
253 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT), gShellLevel2HiiHandle, Cwd);\r
254 } else {\r
255 Param1Copy = CatSPrint (NULL, L"%s", Param1, NULL);\r
256 for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL; Walker++) {\r
257 if (*Walker == L'\"') {\r
258 CopyMem (Walker, Walker + 1, StrSize(Walker) - sizeof(Walker[0]));\r
a405b86d 259 }\r
d9bb3ca3
RN
260 }\r
261\r
262 if (Param1Copy != NULL && IsCurrentFileSystem (Param1Copy, Cwd)) {\r
263 Status = ReplaceDriveWithCwd (&Param1Copy,Cwd);\r
264 if (!EFI_ERROR (Status)) {\r
265 Param1Copy = PathCleanUpDirectories (Param1Copy);\r
beab0fc5 266 }\r
d9bb3ca3 267 } else {\r
a405b86d 268 //\r
d9bb3ca3 269 // Can't use cd command to change filesystem.\r
a405b86d 270 //\r
d9bb3ca3
RN
271 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");\r
272 Status = EFI_NOT_FOUND;\r
273 }\r
274\r
275 if (!EFI_ERROR(Status) && Param1Copy != NULL) {\r
276 Splitter = StrStr (Cwd, L":");\r
277 if (Param1Copy[0] == L'\\') {\r
a405b86d 278 //\r
d9bb3ca3 279 // Absolute Path on current drive letter.\r
a405b86d 280 //\r
d9bb3ca3
RN
281 TotalSize = ((Splitter - Cwd + 1) * sizeof(CHAR16)) + StrSize(Param1Copy);\r
282 TempBuffer = AllocateZeroPool (TotalSize);\r
283 if (TempBuffer == NULL) {\r
284 Status = EFI_OUT_OF_RESOURCES;\r
beab0fc5 285 } else {\r
d9bb3ca3
RN
286 StrnCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd, (Splitter - Cwd + 1));\r
287 StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Param1Copy);\r
288\r
289 FreePool (Param1Copy);\r
290 Param1Copy = TempBuffer;\r
291 TempBuffer = NULL;\r
beab0fc5 292 }\r
d9bb3ca3
RN
293 } else {\r
294 if (StrStr (Param1Copy,L":") == NULL) {\r
295 TotalSize = StrSize (Cwd) + StrSize (Param1Copy);\r
296 TempBuffer = AllocateZeroPool (TotalSize);\r
297 if (TempBuffer == NULL) {\r
298 Status = EFI_OUT_OF_RESOURCES;\r
299 } else {\r
300 StrCpyS (TempBuffer, TotalSize / sizeof (CHAR16), Cwd);\r
301 StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), L"\\");\r
302 StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), Param1Copy);\r
303\r
304 FreePool (Param1Copy);\r
305 Param1Copy = PathCleanUpDirectories (TempBuffer);\r
beab0fc5 306 }\r
307 }\r
a405b86d 308 }\r
d9bb3ca3
RN
309 }\r
310\r
311 if (!EFI_ERROR(Status)) {\r
312 Status = ExtractDriveAndPath (Param1Copy, &Drive, &Path);\r
313 }\r
314\r
315 if (!EFI_ERROR (Status) && Drive != NULL && Path != NULL) {\r
316 if (EFI_ERROR(ShellIsDirectory (Param1Copy))) {\r
317 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy);\r
318 ShellStatus = SHELL_NOT_FOUND;\r
9ea69f8a 319 } else {\r
d9bb3ca3
RN
320 Status = gEfiShellProtocol->SetCurDir (Drive, Path + 1);\r
321 if (EFI_ERROR (Status)) {\r
322 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy);\r
b54fd049 323 ShellStatus = SHELL_NOT_FOUND;\r
b54fd049 324 }\r
9ea69f8a 325 }\r
a405b86d 326 }\r
d9bb3ca3
RN
327\r
328 if (Drive != NULL) {\r
329 FreePool (Drive);\r
330 }\r
331\r
332 if (Path != NULL) {\r
333 FreePool (Path);\r
334 }\r
335\r
336 FreePool (Param1Copy);\r
a405b86d 337 }\r
338 }\r
339 }\r
340\r
a405b86d 341 //\r
342 // free the command line package\r
343 //\r
344 ShellCommandLineFreeVarList (Package);\r
345\r
346 //\r
347 // return the status\r
348 //\r
349 return (ShellStatus);\r
350}\r
351\r