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