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 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 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 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