您的位置:首页 > 产品设计 > UI/UE

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

2018-01-30 20:23 666 查看
uefi 下面没有单独的rename, 只有mv

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

/**
function to take a list of files to move and a destination location and do
the verification and moving of those files to that location.  This function
will 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.t
if (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 loop

SHELL_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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: