/** @file Main file for attrib shell level 2 function. (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "UefiShellLevel2CommandsLib.h" STATIC CONST CHAR16 AllFiles[] = L"*"; STATIC CONST SHELL_PARAM_ITEM AttribParamList[] = { {L"-a", TypeFlag}, {L"+a", TypeFlag}, {L"-s", TypeFlag}, {L"+s", TypeFlag}, {L"-h", TypeFlag}, {L"+h", TypeFlag}, {L"-r", TypeFlag}, {L"+r", TypeFlag}, {NULL, TypeMax} }; /** Function for 'attrib' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunAttrib ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { UINT64 FileAttributesToAdd; UINT64 FileAttributesToRemove; EFI_STATUS Status; LIST_ENTRY *Package; CHAR16 *ProblemParam; SHELL_STATUS ShellStatus; UINTN ParamNumberCount; CONST CHAR16 *FileName; EFI_SHELL_FILE_INFO *ListOfFiles; EFI_SHELL_FILE_INFO *FileNode; EFI_FILE_INFO *FileInfo; ListOfFiles = NULL; ShellStatus = SHELL_SUCCESS; ProblemParam = NULL; // // initialize the shell lib (we must be in non-auto-init...) // Status = ShellInitialize(); ASSERT_EFI_ERROR(Status); // // parse the command line // Status = ShellCommandLineParse (AttribParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"attrib", ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; } else { ASSERT(FALSE); } } else { // // check for "-?" // if (ShellCommandLineGetFlag(Package, L"-?")) { ASSERT(FALSE); } else { FileAttributesToAdd = 0; FileAttributesToRemove = 0; // // apply or remove each flag // if (ShellCommandLineGetFlag(Package, L"+a")) { FileAttributesToAdd |= EFI_FILE_ARCHIVE; } if (ShellCommandLineGetFlag(Package, L"-a")) { FileAttributesToRemove |= EFI_FILE_ARCHIVE; } if (ShellCommandLineGetFlag(Package, L"+s")) { FileAttributesToAdd |= EFI_FILE_SYSTEM; } if (ShellCommandLineGetFlag(Package, L"-s")) { FileAttributesToRemove |= EFI_FILE_SYSTEM; } if (ShellCommandLineGetFlag(Package, L"+h")) { FileAttributesToAdd |= EFI_FILE_HIDDEN; } if (ShellCommandLineGetFlag(Package, L"-h")) { FileAttributesToRemove |= EFI_FILE_HIDDEN; } if (ShellCommandLineGetFlag(Package, L"+r")) { FileAttributesToAdd |= EFI_FILE_READ_ONLY; } if (ShellCommandLineGetFlag(Package, L"-r")) { FileAttributesToRemove |= EFI_FILE_READ_ONLY; } if (FileAttributesToRemove == 0 && FileAttributesToAdd == 0) { // // Do display as we have no attributes to change // for ( ParamNumberCount = 1 ; ; ParamNumberCount++ ){ FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount); // if we dont have anything left, move on... if (FileName == NULL && ParamNumberCount == 1) { FileName = (CHAR16*)AllFiles; } else if (FileName == NULL) { break; } ASSERT(ListOfFiles == NULL); Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); ShellStatus = SHELL_NOT_FOUND; } else { for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link) ; !IsNull(&ListOfFiles->Link, &FileNode->Link) ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link) ){ ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_ATTRIB_OUTPUT_LINE), gShellLevel2HiiHandle, FileNode->Info->Attribute&EFI_FILE_DIRECTORY? L'D':L' ', FileNode->Info->Attribute&EFI_FILE_ARCHIVE? L'A':L' ', FileNode->Info->Attribute&EFI_FILE_SYSTEM? L'S':L' ', FileNode->Info->Attribute&EFI_FILE_HIDDEN? L'H':L' ', FileNode->Info->Attribute&EFI_FILE_READ_ONLY? L'R':L' ', FileNode->FileName ); if (ShellGetExecutionBreakFlag()) { ShellStatus = SHELL_ABORTED; break; } } Status = ShellCloseFileMetaArg(&ListOfFiles); ListOfFiles = NULL; if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); ShellStatus = SHELL_NOT_FOUND; } } // for loop for handling wildcard filenames } // for loop for printing out the info } else if ((FileAttributesToRemove & FileAttributesToAdd) != 0) { // // fail as we have conflcting params. // ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle, L"attrib"); ShellStatus = SHELL_INVALID_PARAMETER; } else { // // enumerate through all the files/directories and apply the attributes // for ( ParamNumberCount = 1 ; ; ParamNumberCount++ ){ FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount); // if we dont have anything left, move on... if (FileName == NULL) { // // make sure we are not failing on the first one we do... if yes that's an error... // if (ParamNumberCount == 1) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"attrib"); ShellStatus = SHELL_INVALID_PARAMETER; } break; } // // OpenFileByName / GetFileInfo / Change attributes / SetFileInfo / CloseFile / free memory // for each file or directory on the line. // // // Open the file(s) // ASSERT(ListOfFiles == NULL); Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); ShellStatus = SHELL_NOT_FOUND; } else { for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link) ; !IsNull(&ListOfFiles->Link, &FileNode->Link) ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link) ){ // // skip the directory traversing stuff... // if (StrCmp(FileNode->FileName, L".") == 0 || StrCmp(FileNode->FileName, L"..") == 0) { continue; } FileInfo = gEfiShellProtocol->GetFileInfo(FileNode->Handle); // // if we are removing Read-Only we need to do that alone // if ((FileAttributesToRemove & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) { FileInfo->Attribute &= ~EFI_FILE_READ_ONLY; // // SetFileInfo // Status = ShellSetFileInfo(FileNode->Handle, FileInfo); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); ShellStatus = SHELL_ACCESS_DENIED; } } // // change the attribute // FileInfo->Attribute &= ~FileAttributesToRemove; FileInfo->Attribute |= FileAttributesToAdd; // // SetFileInfo // Status = ShellSetFileInfo(FileNode->Handle, FileInfo); if (EFI_ERROR(Status)) {; ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); ShellStatus = SHELL_ACCESS_DENIED; } SHELL_FREE_NON_NULL(FileInfo); } Status = ShellCloseFileMetaArg(&ListOfFiles); ListOfFiles = NULL; if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); ShellStatus = SHELL_NOT_FOUND; } } // for loop for handling wildcard filenames } } } } // // free the command line package // ShellCommandLineFreeVarList (Package); // // return the status // return (ShellStatus); }