/** function to determine if a move is between file systems. @param FullName [in] The name of the file to move. @param Cwd [in] The current working directory @param DestPath [in] The target location to move to @retval TRUE The move is across file system. @retval FALSE The move is within a file system. **/ BOOLEAN EFIAPI IsBetweenFileSystem( IN CONST CHAR16 *FullName, IN CONST CHAR16 *Cwd, IN CONST CHAR16 *DestPath ) { CHAR16 *Test; CHAR16 *Test1; UINTN Result; Test = StrStr(FullName, L":"); if (Test == NULL && Cwd != NULL) { Test = StrStr(Cwd, L":"); } Test1 = StrStr(DestPath, L":"); if (Test1 == NULL && Cwd != NULL) { Test1 = StrStr(Cwd, L":"); } if (Test1 != NULL && Test != NULL) { *Test = CHAR_NULL; *Test1 = CHAR_NULL; Result = StringNoCaseCompare(&FullName, &DestPath); *Test = L':'; *Test1 = L':'; if (Result != 0) { return (TRUE); } } return (FALSE); }
/** Function to validate that moving a specific file (FileName) to a specific location (DestPath) is valid. This function will verify that the destination is not a subdirectory of FullName, that the Current working Directory is not being moved, and that the directory is not read only. if the move is invalid this function will report the error to StdOut. @param SourcePath [in] The name of the file to move. @param Cwd [in] The current working directory @param DestPath [in] The target location to move to @param Attribute [in] The Attribute of the file @param DestAttr [in] The Attribute of the destination @param FileStatus [in] The Status of the file when opened @retval TRUE The move is valid @retval FALSE The move is not **/ BOOLEAN EFIAPI IsValidMove( IN CONST CHAR16 *SourcePath, IN CONST CHAR16 *Cwd, IN CONST CHAR16 *DestPath, IN CONST UINT64 Attribute, IN CONST UINT64 DestAttr, IN CONST EFI_STATUS FileStatus ) { CHAR16 *DestPathCopy; CHAR16 *DestPathWalker; if (Cwd != NULL && StrCmp(SourcePath, Cwd) == 0) { // // Invalid move // ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_CWD), gShellLevel2HiiHandle); return (FALSE); } // // invalid to move read only or move to a read only destination // if (((Attribute & EFI_FILE_READ_ONLY) != 0) || (FileStatus == EFI_WRITE_PROTECTED) || ((DestAttr & EFI_FILE_READ_ONLY) != 0) ) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_RO), gShellLevel2HiiHandle, SourcePath); return (FALSE); } DestPathCopy = AllocateCopyPool(StrSize(DestPath), DestPath); if (DestPathCopy == NULL) { return (FALSE); } for (DestPathWalker = DestPathCopy; *DestPathWalker == L'\\'; DestPathWalker++) ; while(DestPathWalker != NULL && DestPathWalker[StrLen(DestPathWalker)-1] == L'\\') { DestPathWalker[StrLen(DestPathWalker)-1] = CHAR_NULL; } ASSERT(DestPathWalker != NULL); ASSERT(SourcePath != NULL); // // If they're the same, or if source is "above" dest on file path tree // if ( StringNoCaseCompare (&DestPathWalker, &SourcePath) == 0 || ((StrStr(DestPathWalker, SourcePath) == DestPathWalker) && (DestPathWalker[StrLen(SourcePath)] == '\\') ) ) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_SUB), gShellLevel2HiiHandle); FreePool(DestPathCopy); return (FALSE); } FreePool(DestPathCopy); return (TRUE); }
/** Save lines in HBufferImage to disk. @param[in] FileName The file name. @retval EFI_SUCCESS The operation was successful. @retval EFI_OUT_OF_RESOURCES A memory allocation failed. @retval EFI_LOAD_ERROR A load error occured. **/ EFI_STATUS HFileImageSave ( IN CHAR16 *FileName ) { LIST_ENTRY *Link; HEFI_EDITOR_LINE *Line; CHAR16 *Str; EFI_STATUS Status; UINTN NumLines; SHELL_FILE_HANDLE FileHandle; UINTN TotalSize; UINT8 *Buffer; UINT8 *Ptr; EDIT_FILE_TYPE BufferTypeBackup; BufferTypeBackup = HBufferImage.BufferType; HBufferImage.BufferType = FileTypeFileBuffer; // // if is the old file // if (HFileImage.FileName != NULL && FileName != NULL && StrCmp (FileName, HFileImage.FileName) == 0) { // // check whether file exists on disk // if (ShellIsFile(FileName) == EFI_SUCCESS) { // // current file exists on disk // so if not modified, then not save // if (HBufferImage.Modified == FALSE) { return EFI_SUCCESS; } // // if file is read-only, set error // if (HFileImage.ReadOnly == TRUE) { StatusBarSetStatusString (L"Read Only File Can Not Be Saved"); return EFI_SUCCESS; } } } if (ShellIsDirectory(FileName) == EFI_SUCCESS) { StatusBarSetStatusString (L"Directory Can Not Be Saved"); return EFI_LOAD_ERROR; } Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0); if (!EFI_ERROR (Status)) { // // the file exits, delete it // Status = ShellDeleteFile (&FileHandle); if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) { StatusBarSetStatusString (L"Write File Failed"); return EFI_LOAD_ERROR; } } // // write all the lines back to disk // NumLines = 0; TotalSize = 0; for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) { Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); if (Line->Size != 0) { TotalSize += Line->Size; } // // end of if Line -> Size != 0 // NumLines++; } // // end of for Link // Buffer = AllocateZeroPool (TotalSize); if (Buffer == NULL) { return EFI_OUT_OF_RESOURCES; } Ptr = Buffer; for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) { Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); if (Line->Size != 0) { CopyMem (Ptr, Line->Buffer, Line->Size); Ptr += Line->Size; } // // end of if Line -> Size != 0 // } Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); if (EFI_ERROR (Status)) { StatusBarSetStatusString (L"Create File Failed"); return EFI_LOAD_ERROR; } Status = ShellWriteFile (FileHandle, &TotalSize, Buffer); FreePool (Buffer); if (EFI_ERROR (Status)) { ShellDeleteFile (&FileHandle); return EFI_LOAD_ERROR; } ShellCloseFile(&FileHandle); HBufferImage.Modified = FALSE; // // set status string // Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines); StatusBarSetStatusString (Str); FreePool (Str); // // now everything is ready , you can set the new file name to filebuffer // if ((BufferTypeBackup != FileTypeFileBuffer && FileName != NULL) || (FileName != NULL && HFileImage.FileName != NULL && StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0)){ // // not the same // HFileImageSetFileName (FileName); if (HFileImage.FileName == NULL) { return EFI_OUT_OF_RESOURCES; } } HFileImage.ReadOnly = FALSE; return EFI_SUCCESS; }
/** function to take a list of files to copy and a destination location and do the verification and copying of those files to that location. This function will report any errors to the user and halt. The key is to have this function called ONLY once. this allows for the parameter verification to happen correctly. @param[in] FileList A LIST_ENTRY* based list of files to move. @param[in] DestDir The destination location. @param[in] SilentMode TRUE to eliminate screen output. @param[in] RecursiveMode TRUE to copy directories. @param[in] Resp The response to the overwrite query (if always). @retval SHELL_SUCCESS the files were all moved. @retval SHELL_INVALID_PARAMETER a parameter was invalid @retval SHELL_SECURITY_VIOLATION a security violation ocurred @retval SHELL_WRITE_PROTECTED the destination was write protected @retval SHELL_OUT_OF_RESOURCES a memory allocation failed **/ SHELL_STATUS EFIAPI ValidateAndCopyFiles( IN CONST EFI_SHELL_FILE_INFO *FileList, IN CONST CHAR16 *DestDir, IN BOOLEAN SilentMode, IN BOOLEAN RecursiveMode, IN VOID **Resp ) { CHAR16 *HiiOutput; CHAR16 *HiiResultOk; CONST EFI_SHELL_FILE_INFO *Node; SHELL_STATUS ShellStatus; CHAR16 *DestPath; VOID *Response; UINTN PathLen; CONST CHAR16 *Cwd; CONST CHAR16 *TempLocation; UINTN NewSize; if (Resp == NULL) { Response = NULL; } else { Response = *Resp; } DestPath = NULL; ShellStatus = SHELL_SUCCESS; PathLen = 0; Cwd = ShellGetCurrentDir(NULL); ASSERT(FileList != NULL); ASSERT(DestDir != NULL); // // We already verified that this was present. // ASSERT(Cwd != NULL); // // If we are trying to copy multiple files... make sure we got a directory for the target... // if (EFI_ERROR(ShellIsDirectory(DestDir)) && FileList->Link.ForwardLink != FileList->Link.BackLink) { // // Error for destination not a directory // ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir); return (SHELL_INVALID_PARAMETER); } for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) ; !IsNull(&FileList->Link, &Node->Link) ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) ){ // // skip the directory traversing stuff... // if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { continue; } NewSize = StrSize(DestDir); NewSize += StrSize(Node->FullName); NewSize += StrSize(Cwd); if (NewSize > PathLen) { PathLen = NewSize; } // // Make sure got -r if required // if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle); return (SHELL_INVALID_PARAMETER); } // // make sure got dest as dir if needed // if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(DestDir))) { // // Error for destination not a directory // ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir); return (SHELL_INVALID_PARAMETER); } } HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL); HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL); DestPath = AllocateZeroPool(PathLen); if (DestPath == NULL || HiiOutput == NULL || HiiResultOk == NULL) { SHELL_FREE_NON_NULL(DestPath); SHELL_FREE_NON_NULL(HiiOutput); SHELL_FREE_NON_NULL(HiiResultOk); return (SHELL_OUT_OF_RESOURCES); } // // Go through the list of files to copy... // for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) ; !IsNull(&FileList->Link, &Node->Link) ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) ){ if (ShellGetExecutionBreakFlag()) { break; } ASSERT(Node->FileName != NULL); ASSERT(Node->FullName != NULL); // // skip the directory traversing stuff... // if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { continue; } if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item && EFI_ERROR(ShellIsDirectory(DestDir)) // not an existing directory ) { if (StrStr(DestDir, L":") == NULL) { // // simple copy of a single file // StrCpy(DestPath, Cwd); if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') { StrCat(DestPath, L"\\"); } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') { ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; } StrCat(DestPath, DestDir); } else { StrCpy(DestPath, DestDir); } } else { // // we have multiple files or a directory in the DestDir // // // Check for leading slash // if (DestDir[0] == L'\\') { // // Copy to the root of CWD // StrCpy(DestPath, Cwd); while (PathRemoveLastItem(DestPath)); StrCat(DestPath, DestDir+1); StrCat(DestPath, Node->FileName); } else if (StrStr(DestDir, L":") == NULL) { StrCpy(DestPath, Cwd); if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') { StrCat(DestPath, L"\\"); } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') { ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; } StrCat(DestPath, DestDir); if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') { StrCat(DestPath, L"\\"); } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') { ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; } StrCat(DestPath, Node->FileName); } else { StrCpy(DestPath, DestDir); if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') { StrCat(DestPath, L"\\"); } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') { ((CHAR16*)DestDir)[StrLen(DestDir)-1] = CHAR_NULL; } StrCat(DestPath, Node->FileName); } } // // Make sure the path exists // if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle); ShellStatus = SHELL_DEVICE_ERROR; break; } if ( !EFI_ERROR(ShellIsDirectory(Node->FullName)) && !EFI_ERROR(ShellIsDirectory(DestPath)) && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == NULL ){ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; break; } if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; break; } if ((TempLocation = StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName))) == 0 && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\') ) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; break; } PathCleanUpDirectories(DestPath); ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath); // // copy single file... // ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode); if (ShellStatus != SHELL_SUCCESS) { break; } } if (ShellStatus == SHELL_SUCCESS && Resp == NULL) { ShellPrintEx(-1, -1, L"%s", HiiResultOk); } SHELL_FREE_NON_NULL(DestPath); SHELL_FREE_NON_NULL(HiiOutput); SHELL_FREE_NON_NULL(HiiResultOk); if (Resp == NULL) { SHELL_FREE_NON_NULL(Response); } return (ShellStatus); }
/** Do a comparison between 2 things. @param[in] Compare1 The first item to compare. @param[in] Compare2 The second item to compare. @param[in] BinOp The type of comparison to perform. @param[in] CaseInsensitive TRUE to do non-case comparison, FALSE otherwise. @param[in] ForceStringCompare TRUE to force string comparison, FALSE otherwise. @return The result of the comparison. **/ BOOLEAN EFIAPI TestOperation ( IN CONST CHAR16 *Compare1, IN CONST CHAR16 *Compare2, IN CONST BIN_OPERATOR_TYPE BinOp, IN CONST BOOLEAN CaseInsensitive, IN CONST BOOLEAN ForceStringCompare ) { INTN Cmp1; INTN Cmp2; // // "Compare1 BinOp Compare2" // switch (BinOp) { case OperatorUnisgnedGreaterThan: case OperatorGreaterThan: if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { // // string compare // if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) > 0) || (StringCompare(&Compare1, &Compare2) > 0)) { return (TRUE); } } else { // // numeric compare // if (Compare1[0] == L'-') { Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); } else { Cmp1 = (INTN)ShellStrToUintn(Compare1); } if (Compare2[0] == L'-') { Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); } else { Cmp2 = (INTN)ShellStrToUintn(Compare2); } if (BinOp == OperatorGreaterThan) { if (Cmp1 > Cmp2) { return (TRUE); } } else { if ((UINTN)Cmp1 > (UINTN)Cmp2) { return (TRUE); } } } return (FALSE); break; case OperatorUnsignedLessThan: case OperatorLessThan: if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { // // string compare // if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) < 0) || (StringCompare(&Compare1, &Compare2) < 0)) { return (TRUE); } } else { // // numeric compare // if (Compare1[0] == L'-') { Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); } else { Cmp1 = (INTN)ShellStrToUintn(Compare1); } if (Compare2[0] == L'-') { Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); } else { Cmp2 = (INTN)ShellStrToUintn(Compare2); } if (BinOp == OperatorLessThan) { if (Cmp1 < Cmp2) { return (TRUE); } } else { if ((UINTN)Cmp1 < (UINTN)Cmp2) { return (TRUE); } } } return (FALSE); break; case OperatorEqual: if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { // // string compare // if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) == 0) || (StringCompare(&Compare1, &Compare2) == 0)) { return (TRUE); } } else { // // numeric compare // if (Compare1[0] == L'-') { Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); } else { Cmp1 = (INTN)ShellStrToUintn(Compare1); } if (Compare2[0] == L'-') { Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); } else { Cmp2 = (INTN)ShellStrToUintn(Compare2); } if (Cmp1 == Cmp2) { return (TRUE); } } return (FALSE); break; case OperatorNotEqual: if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { // // string compare // if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) != 0) || (StringCompare(&Compare1, &Compare2) != 0)) { return (TRUE); } } else { // // numeric compare // if (Compare1[0] == L'-') { Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); } else { Cmp1 = (INTN)ShellStrToUintn(Compare1); } if (Compare2[0] == L'-') { Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); } else { Cmp2 = (INTN)ShellStrToUintn(Compare2); } if (Cmp1 != Cmp2) { return (TRUE); } } return (FALSE); break; case OperatorUnsignedGreaterOrEqual: case OperatorGreatorOrEqual: if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { // // string compare // if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) >= 0) || (StringCompare(&Compare1, &Compare2) >= 0)) { return (TRUE); } } else { // // numeric compare // if (Compare1[0] == L'-') { Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); } else { Cmp1 = (INTN)ShellStrToUintn(Compare1); } if (Compare2[0] == L'-') { Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); } else { Cmp2 = (INTN)ShellStrToUintn(Compare2); } if (BinOp == OperatorGreatorOrEqual) { if (Cmp1 >= Cmp2) { return (TRUE); } } else { if ((UINTN)Cmp1 >= (UINTN)Cmp2) { return (TRUE); } } } return (FALSE); break; case OperatorLessOrEqual: case OperatorUnsignedLessOrEqual: if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { // // string compare // if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) <= 0) || (StringCompare(&Compare1, &Compare2) <= 0)) { return (TRUE); } } else { // // numeric compare // if (Compare1[0] == L'-') { Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); } else { Cmp1 = (INTN)ShellStrToUintn(Compare1); } if (Compare2[0] == L'-') { Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); } else { Cmp2 = (INTN)ShellStrToUintn(Compare2); } if (BinOp == OperatorLessOrEqual) { if (Cmp1 <= Cmp2) { return (TRUE); } } else { if ((UINTN)Cmp1 <= (UINTN)Cmp2) { return (TRUE); } } } return (FALSE); break; default: ASSERT(FALSE); return (FALSE); } }