1 /** @file
2 Main file for Touch shell level 3 function.
3
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2009 - 2011, 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 "UefiShellLevel3CommandsLib.h"
17
18 #include <Library/ShellLib.h>
19
20 /**
21 Do the touch operation on a single handle.
22
23 @param[in] Handle The handle to update the date/time on.
24
25 @retval EFI_ACCESS_DENIED The file referenced by Handle is read only.
26 @retval EFI_SUCCESS The operation was successful.
27 **/
28 EFI_STATUS
29 EFIAPI
TouchFileByHandle(IN EFI_HANDLE Handle)30 TouchFileByHandle (
31 IN EFI_HANDLE Handle
32 )
33 {
34 EFI_STATUS Status;
35 EFI_FILE_INFO *FileInfo;
36
37 FileInfo = gEfiShellProtocol->GetFileInfo(Handle);
38 if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) != 0){
39 return (EFI_ACCESS_DENIED);
40 }
41 Status = gRT->GetTime(&FileInfo->ModificationTime, NULL);
42 if (EFI_ERROR(Status)) {
43 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"gRT->GetTime", Status);
44 return (SHELL_DEVICE_ERROR);
45 }
46
47 CopyMem(&FileInfo->LastAccessTime, &FileInfo->ModificationTime, sizeof(EFI_TIME));
48
49 Status = gEfiShellProtocol->SetFileInfo(Handle, FileInfo);
50
51 FreePool(FileInfo);
52
53 return (Status);
54 }
55
56 /**
57 Touch a given file and potantially recurse down if it was a directory.
58
59 @param[in] Name The name of this file.
60 @param[in] FS The name of the file system this file is on.
61 @param[in] Handle The handle of this file already opened.
62 @param[in] Rec TRUE to recurse if possible.
63
64 @retval EFI_INVALID_PARAMETER A parameter was invalid.
65 @retval EFI_SUCCESS The operation was successful.
66 **/
67 EFI_STATUS
68 EFIAPI
DoTouchByHandle(IN CONST CHAR16 * Name,IN CHAR16 * FS,IN SHELL_FILE_HANDLE Handle,IN BOOLEAN Rec)69 DoTouchByHandle (
70 IN CONST CHAR16 *Name,
71 IN CHAR16 *FS,
72 IN SHELL_FILE_HANDLE Handle,
73 IN BOOLEAN Rec
74 )
75 {
76 EFI_STATUS Status;
77 EFI_SHELL_FILE_INFO *FileList;
78 EFI_SHELL_FILE_INFO *Walker;
79 CHAR16 *TempSpot;
80
81 Status = EFI_SUCCESS;
82 FileList = NULL;
83 Walker = NULL;
84
85 if (FS == NULL) {
86 FS = StrnCatGrow(&FS, NULL, Name, 0);
87 if (FS != NULL) {
88 TempSpot = StrStr(FS, L"\\");
89 if (TempSpot != NULL) {
90 *TempSpot = CHAR_NULL;
91 }
92 }
93 }
94 if (FS == NULL) {
95 return (EFI_INVALID_PARAMETER);
96 }
97
98 //
99 // do it
100 //
101 Status = TouchFileByHandle(Handle);
102 if (EFI_ERROR(Status)) {
103 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Name);
104 return (Status);
105 }
106
107 //
108 // if it's a directory recurse...
109 //
110 if (FileHandleIsDirectory(Handle) == EFI_SUCCESS && Rec) {
111 //
112 // get each file under this directory
113 //
114 if (EFI_ERROR(gEfiShellProtocol->FindFilesInDir(Handle, &FileList))) {
115 Status = EFI_INVALID_PARAMETER;
116 }
117
118 //
119 // recurse on each
120 //
121 for (Walker = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
122 ; FileList != NULL && !IsNull(&FileList->Link, &Walker->Link) && !EFI_ERROR(Status)
123 ; Walker = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Walker->Link)
124 ){
125 if ( (StrCmp(Walker->FileName, L".") != 0)
126 && (StrCmp(Walker->FileName, L"..") != 0)
127 ){
128 //
129 // Open the file since we need that handle.
130 //
131 Status = gEfiShellProtocol->OpenFileByName (Walker->FullName, &Walker->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE);
132 if (EFI_ERROR(Status)) {
133 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Walker->FullName);
134 Status = EFI_ACCESS_DENIED;
135 } else {
136 Status = DoTouchByHandle(Walker->FullName, FS, Walker->Handle, TRUE);
137 gEfiShellProtocol->CloseFile(Walker->Handle);
138 Walker->Handle = NULL;
139 }
140 }
141 }
142
143 //
144 // free stuff
145 //
146 if (FileList != NULL && EFI_ERROR(gEfiShellProtocol->FreeFileList(&FileList))) {
147 Status = EFI_INVALID_PARAMETER;
148 }
149 }
150
151 return (Status);
152 }
153
154 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
155 {L"-r", TypeFlag},
156 {NULL, TypeMax}
157 };
158
159 /**
160 Function for 'touch' command.
161
162 @param[in] ImageHandle Handle to the Image (NULL if Internal).
163 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
164 **/
165 SHELL_STATUS
166 EFIAPI
ShellCommandRunTouch(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)167 ShellCommandRunTouch (
168 IN EFI_HANDLE ImageHandle,
169 IN EFI_SYSTEM_TABLE *SystemTable
170 )
171 {
172 EFI_STATUS Status;
173 LIST_ENTRY *Package;
174 CHAR16 *ProblemParam;
175 CONST CHAR16 *Param;
176 SHELL_STATUS ShellStatus;
177 UINTN ParamCount;
178 EFI_SHELL_FILE_INFO *FileList;
179 EFI_SHELL_FILE_INFO *Node;
180
181 ProblemParam = NULL;
182 ShellStatus = SHELL_SUCCESS;
183 ParamCount = 0;
184 FileList = NULL;
185
186 //
187 // initialize the shell lib (we must be in non-auto-init...)
188 //
189 Status = ShellInitialize();
190 ASSERT_EFI_ERROR(Status);
191
192 Status = CommandInit();
193 ASSERT_EFI_ERROR(Status);
194
195 //
196 // parse the command line
197 //
198 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
199 if (EFI_ERROR(Status)) {
200 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
201 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"touch", ProblemParam);
202 FreePool(ProblemParam);
203 ShellStatus = SHELL_INVALID_PARAMETER;
204 } else {
205 ASSERT(FALSE);
206 }
207 } else {
208 //
209 // check for "-?"
210 //
211 if (ShellCommandLineGetFlag(Package, L"-?")) {
212 ASSERT(FALSE);
213 }
214 if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
215 //
216 // we insufficient parameters
217 //
218 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"touch");
219 ShellStatus = SHELL_INVALID_PARAMETER;
220 } else {
221 //
222 // get a list with each file specified by parameters
223 // if parameter is a directory then add all the files below it to the list
224 //
225 for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
226 ; Param != NULL
227 ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
228 ){
229 Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, &FileList);
230 if (EFI_ERROR(Status)) {
231 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"touch", (CHAR16*)Param);
232 ShellStatus = SHELL_NOT_FOUND;
233 break;
234 }
235 //
236 // make sure we completed the param parsing sucessfully...
237 // Also make sure that any previous action was sucessful
238 //
239 if (ShellStatus == SHELL_SUCCESS) {
240 //
241 // check that we have at least 1 file
242 //
243 if (FileList == NULL || IsListEmpty(&FileList->Link)) {
244 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, L"touch", Param);
245 continue;
246 } else {
247 //
248 // loop through the list and make sure we are not aborting...
249 //
250 for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
251 ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
252 ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
253 ){
254 //
255 // make sure the file opened ok
256 //
257 if (EFI_ERROR(Node->Status)){
258 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Node->FileName);
259 ShellStatus = SHELL_NOT_FOUND;
260 continue;
261 }
262
263 Status = DoTouchByHandle(Node->FullName, NULL, Node->Handle, ShellCommandLineGetFlag(Package, L"-r"));
264 if (EFI_ERROR(Status) && Status != EFI_ACCESS_DENIED) {
265 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Node->FileName);
266 ShellStatus = SHELL_NOT_FOUND;
267 }
268 }
269 }
270 }
271 //
272 // Free the fileList
273 //
274 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
275 Status = ShellCloseFileMetaArg(&FileList);
276 ASSERT_EFI_ERROR(Status);
277 }
278 FileList = NULL;
279 }
280 }
281
282 //
283 // free the command line package
284 //
285 ShellCommandLineFreeVarList (Package);
286 }
287
288 if (ShellGetExecutionBreakFlag()) {
289 return (SHELL_ABORTED);
290 }
291
292 return (ShellStatus);
293 }
294
295