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