• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
ShellCommandRunCd(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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