当前位置: 代码迷 >> 综合 >> uefi mv a.txt b.txt 是如何做到的? 即同一个文件系统内如何实现重命名
  详细解决方案

uefi mv a.txt b.txt 是如何做到的? 即同一个文件系统内如何实现重命名

热度:87   发布时间:2023-12-14 22:31:32.0

uefi 下面没有单独的rename, 只有mv

一句话总结,同一个文件系统里面,改文件info 就行了。见代码中汉字注释部分

/**function to take a list of files to move and a destination location and dothe verification and moving of those files to that location.  This functionwill report any errors to the user and continue to move the rest of the files.@param[in] FileList           A LIST_ENTRY* based list of files to move@param[out] Resp              pointer to response from question.  Pass back on looped calling@param[in] DestParameter      the originally specified destination location@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
ValidateAndMoveFiles(IN EFI_SHELL_FILE_INFO        *FileList,OUT VOID                      **Resp,IN CONST CHAR16               *DestParameter)
{EFI_STATUS                Status;CHAR16                    *HiiOutput;CHAR16                    *HiiResultOk;CHAR16                    *DestPath;CHAR16                    *FullDestPath;CONST CHAR16              *Cwd;CHAR16                    *FullCwd;SHELL_STATUS              ShellStatus;EFI_SHELL_FILE_INFO       *Node;VOID                      *Response;UINT64                    Attr;CHAR16                    *CleanFilePathStr;ASSERT(FileList != NULL);ASSERT(DestParameter  != NULL);DestPath          = NULL;FullDestPath      = NULL;Cwd               = ShellGetCurrentDir(NULL);Response          = *Resp;Attr              = 0;CleanFilePathStr  = NULL;FullCwd           = NULL;if (Cwd != NULL) {
   
    FullCwd = AllocateZeroPool(StrSize(Cwd) + sizeof(CHAR16));  
给 FullCwd 分配内存if (FullCwd == NULL) {return SHELL_OUT_OF_RESOURCES;} else {StrCpyS(FullCwd, StrSize(Cwd)/sizeof(CHAR16)+1, Cwd);StrCatS(FullCwd, StrSize(Cwd)/sizeof(CHAR16)+1, L"\\");}} 此时, FullCwd 类似这个样子 F.S.0.:.\Status = ShellLevel2StripQuotes (DestParameter, &CleanFilePathStr);if (EFI_ERROR (Status)) {SHELL_FREE_NON_NULL(FullCwd);if (Status == EFI_OUT_OF_RESOURCES) {return SHELL_OUT_OF_RESOURCES;} else {return SHELL_INVALID_PARAMETER;}}ASSERT (CleanFilePathStr != NULL);//// Get and validate the destination location//
获得并且验证目标位置ShellStatus = GetDestinationLocation(CleanFilePathStr, &DestPath, FullCwd, (BOOLEAN)(FileList->Link.ForwardLink == FileList->Link.BackLink), &Attr);FreePool (CleanFilePathStr);if (ShellStatus != SHELL_SUCCESS) {SHELL_FREE_NON_NULL (FullCwd);return (ShellStatus);}DestPath = PathCleanUpDirectories(DestPath);
 目标path 取值类似这个样子: F.S.0.:.\.a...t.x.tif (DestPath == NULL) {FreePool (FullCwd);return (SHELL_OUT_OF_RESOURCES);}HiiOutput   = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MV_OUTPUT), NULL);HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);if (HiiOutput == NULL || HiiResultOk == NULL) {SHELL_FREE_NON_NULL(DestPath);SHELL_FREE_NON_NULL(HiiOutput);SHELL_FREE_NON_NULL(HiiResultOk);SHELL_FREE_NON_NULL(FullCwd);return (SHELL_OUT_OF_RESOURCES);}//// Go through the list of files and directories to move...//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;}//// These should never be NULL//ASSERT(Node->FileName != NULL);ASSERT(Node->FullName != NULL);ASSERT(Node->Info     != NULL);//// skip the directory traversing stuff...//if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {continue;}SHELL_FREE_NON_NULL(FullDestPath);FullDestPath = NULL;if (ShellIsDirectory(DestPath)==EFI_SUCCESS) {CreateFullDestPath((CONST CHAR16 **)&DestPath, &FullDestPath, Node->FileName);}//// Validate that the move is valid//if (!IsValidMove(Node->FullName, FullCwd, FullDestPath!=NULL? FullDestPath:DestPath, Node->Info->Attribute, Attr, Node->Status)) {ShellStatus = SHELL_INVALID_PARAMETER;continue;}ShellPrintEx(-1, -1, HiiOutput, Node->FullName, FullDestPath!=NULL? FullDestPath:DestPath);//// See if destination exists//if (!EFI_ERROR(ShellFileExists(FullDestPath!=NULL? FullDestPath:DestPath))) {if (Response == NULL) {ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response);}switch (*(SHELL_PROMPT_RESPONSE*)Response) {case ShellPromptResponseNo:FreePool(Response);Response = NULL;continue;case ShellPromptResponseCancel:*Resp = Response;//// indicate to stop everything//SHELL_FREE_NON_NULL(FullCwd);return (SHELL_ABORTED);case ShellPromptResponseAll:*Resp = Response;break;case ShellPromptResponseYes:FreePool(Response);Response = NULL;break;default:FreePool(Response);SHELL_FREE_NON_NULL(FullCwd);return SHELL_ABORTED;}Status = ShellDeleteFileByName(FullDestPath!=NULL? FullDestPath:DestPath);}if (IsBetweenFileSystem(Node->FullName, FullCwd, DestPath)) {while (FullDestPath == NULL && DestPath != NULL && DestPath[0] != CHAR_NULL && DestPath[StrLen(DestPath) - 1] == L'\\') {DestPath[StrLen(DestPath) - 1] = CHAR_NULL;}Status = MoveBetweenFileSystems(Node, FullDestPath!=NULL? FullDestPath:DestPath, &Response);} else {
   
重点就在这里,其实现在同名文件 mv.c Status = MoveWithinFileSystems(Node, DestPath, &Response);//// Display error status//if (EFI_ERROR(Status)) {ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"mv", Status);}}//// Check our result//if (EFI_ERROR(Status)) {ShellStatus = SHELL_INVALID_PARAMETER;if (Status == EFI_SECURITY_VIOLATION) {ShellStatus = SHELL_SECURITY_VIOLATION;} else if (Status == EFI_WRITE_PROTECTED) {ShellStatus = SHELL_WRITE_PROTECTED;} else if (Status == EFI_OUT_OF_RESOURCES) {ShellStatus = SHELL_OUT_OF_RESOURCES;} else if (Status == EFI_DEVICE_ERROR) {ShellStatus = SHELL_DEVICE_ERROR;} else if (Status == EFI_ACCESS_DENIED) {ShellStatus = SHELL_ACCESS_DENIED;}} else {ShellPrintEx(-1, -1, L"%s", HiiResultOk);}} // main for loopSHELL_FREE_NON_NULL(FullDestPath);SHELL_FREE_NON_NULL(DestPath);SHELL_FREE_NON_NULL(HiiOutput);SHELL_FREE_NON_NULL(HiiResultOk);SHELL_FREE_NON_NULL(FullCwd);return (ShellStatus);
}

 


/**Function to do a move within a file system.@param[in] Node               A pointer to the file to be removed.@param[in] DestPath           A pointer to the destination file path.@param[out] Resp              A pointer to response from question.  Pass back on looped calling.@retval SHELL_SUCCESS           The source file was moved to the destination.@retval SHELL_OUT_OF_RESOURCES  A memory allocation failed.
**/
EFI_STATUS
MoveWithinFileSystems(IN EFI_SHELL_FILE_INFO  *Node,IN CHAR16               *DestPath,OUT VOID                **Resp)
{EFI_FILE_INFO             *NewFileInfo;CHAR16                    *TempLocation;UINTN                     NewSize;UINTN                     Length;EFI_STATUS                Status;//// Chop off map info from DestPath//if ((TempLocation = StrStr(DestPath, L":")) != NULL) {CopyMem(DestPath, TempLocation+1, StrSize(TempLocation+1));}//// construct the new file info block//NewSize = StrSize(DestPath);NewSize += StrSize(Node->FileName) + SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);NewFileInfo = AllocateZeroPool(NewSize);if (NewFileInfo == NULL) {ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle);Status = EFI_OUT_OF_RESOURCES;} else {CopyMem(NewFileInfo, Node->Info, SIZE_OF_EFI_FILE_INFO);if (DestPath[0] != L'\\') {StrCpyS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), L"\\");StrCatS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), DestPath);} else {StrCpyS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), DestPath);
这句话给文件赋予了新的名字。
    }Length = StrLen(NewFileInfo->FileName);if (Length > 0) {Length--;}if (NewFileInfo->FileName[Length] == L'\\') {if (Node->FileName[0] == L'\\') {//// Don't allow for double slashes. Eliminate one of them.//NewFileInfo->FileName[Length] = CHAR_NULL;}StrCatS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), Node->FileName);}NewFileInfo->Size = SIZE_OF_EFI_FILE_INFO + StrSize(NewFileInfo->FileName);//// Perform the move operation//Status = ShellSetFileInfo(Node->Handle, NewFileInfo);//// Free the info object we used...//FreePool(NewFileInfo);}return (Status);
}



ps:

FileFunctionMap  所有函数实现在UefiFileHandleLib.c