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