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