windows-nt/Source/XPSP1/NT/base/efiutil/sdk/shell/rm/rm.c

270 lines
5.7 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1998 Intel Corporation
Module Name:
rm.c
Abstract:
Shell app "rm"
Revision History
--*/
#include "shell.h"
/*
*
*/
#define FILE_INFO_SIZE (SIZE_OF_EFI_FILE_INFO + 1024)
EFI_FILE_INFO *RmInfo;
/*
*
*/
EFI_STATUS
InitializeRM (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
VOID
RemoveRM (
IN SHELL_FILE_ARG *Arg,
IN BOOLEAN Quite
);
/*
*
*/
EFI_DRIVER_ENTRY_POINT(InitializeRM)
EFI_STATUS
InitializeRM (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
CHAR16 **Argv;
UINTN Argc;
UINTN Index;
LIST_ENTRY FileList;
LIST_ENTRY *Link;
SHELL_FILE_ARG *Arg;
/*
* Check to see if the app is to install as a "internal command"
* to the shell
*/
InstallInternalShellCommand (
ImageHandle, SystemTable, InitializeRM,
L"rm", /* command */
L"rm file/dir [file/dir]", /* command syntax */
L"Remove file/directories", /* 1 line descriptor */
NULL /* command help page */
);
/*
* We are no being installed as an internal command driver, initialize
* as an nshell app and run
*/
InitializeShellApplication (ImageHandle, SystemTable);
Argv = SI->Argv;
Argc = SI->Argc;
InitializeListHead (&FileList);
RmInfo = AllocatePool (FILE_INFO_SIZE);
if (!RmInfo) {
Print (L"rm: out of memory\n");
goto Done;
}
/*
* Expand each arg
*/
for (Index = 1; Index < Argc; Index += 1) {
ShellFileMetaArg (Argv[Index], &FileList);
}
if (IsListEmpty(&FileList)) {
Print (L"rm: no file specified\n");
goto Done;
}
/*
* Remove each file
*/
for (Link=FileList.Flink; Link!=&FileList; Link=Link->Flink) {
Arg = CR(Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
RemoveRM (Arg, 0);
}
Done:
ShellFreeFileList (&FileList);
if (RmInfo) {
FreePool (RmInfo);
RmInfo = NULL;
}
return EFI_SUCCESS;
}
SHELL_FILE_ARG *
RmCreateChild (
IN SHELL_FILE_ARG *Parent,
IN CHAR16 *FileName,
IN OUT LIST_ENTRY *ListHead
)
{
SHELL_FILE_ARG *Arg;
UINTN Len;
Arg = AllocateZeroPool (sizeof(SHELL_FILE_ARG));
if (!Arg) {
return NULL;
}
Arg->Signature = SHELL_FILE_ARG_SIGNATURE;
Parent->Parent->Open (Parent->Handle, &Arg->Parent, L".", EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
Arg->ParentName = StrDuplicate(Parent->FullName);
Arg->FileName = StrDuplicate(FileName);
/* append filename to parent's name to get the file's full name */
Len = StrLen(Arg->ParentName);
if (Len && Arg->ParentName[Len-1] == '\\') {
Len -= 1;
}
Arg->FullName = PoolPrint(L"%.*s\\%s", Len, Arg->ParentName, FileName);
/* open it */
Arg->Status = Parent->Handle->Open (
Parent->Handle,
&Arg->Handle,
Arg->FileName,
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
0
);
InsertTailList (ListHead, &Arg->Link);
return Arg;
}
VOID
RemoveRM (
IN SHELL_FILE_ARG *Arg,
IN BOOLEAN Quite
)
{
EFI_STATUS Status;
SHELL_FILE_ARG *Child;
LIST_ENTRY Cleanup;
UINTN Size;
CHAR16 Str[2];
Status = Arg->Status;
InitializeListHead (&Cleanup);
if (EFI_ERROR(Status)) {
goto Done;
}
/*
* If the file is a directory check it
*/
Size = FILE_INFO_SIZE;
Status = Arg->Handle->GetInfo(Arg->Handle, &GenericFileInfo, &Size, RmInfo);
if (EFI_ERROR(Status)) {
Print(L"rm: can not get info of %hs\n", Arg->FullName);
goto Done;
}
if (RmInfo->Attribute & EFI_FILE_DIRECTORY) {
/*
* Remove all child entries from the directory
*/
Arg->Handle->SetPosition (Arg->Handle, 0);
for (; ;) {
Size = FILE_INFO_SIZE;
Status = Arg->Handle->Read (Arg->Handle, &Size, RmInfo);
if (EFI_ERROR(Status) || Size == 0) {
break;
}
/*
* Skip "." and ".."
*/
if (StriCmp(RmInfo->FileName, L".") == 0 ||
StriCmp(RmInfo->FileName, L"..") == 0) {
continue;
}
/*
* Build a shell_file_arg for the sub-entry
*/
Child = RmCreateChild (Arg, RmInfo->FileName, &Cleanup);
/*
* Remove it
*/
if (!Quite) {
Print (L"rm: remove subtree '%hs' [y/n]? ", Arg->FullName);
Input (NULL, Str, 2);
Print (L"\n");
Status = (Str[0] == 'y' || Str[0] == 'Y') ? EFI_SUCCESS : EFI_ACCESS_DENIED;
if (EFI_ERROR(Status)) {
goto Done;
}
}
Quite = TRUE;
RemoveRM (Child, TRUE);
/*
* Close the handles
*/
ShellFreeFileList (&Cleanup);
}
}
/*
* Remove the file
*/
Status = Arg->Handle->Delete(Arg->Handle);
Arg->Handle = NULL;
Done:
if (EFI_ERROR(Status)) {
Print (L"rm %s : %hr\n", Arg->FullName, Status);
} else {
Print (L"rm %s [ok]\n", Arg->FullName);
}
}