270 lines
5.7 KiB
C
270 lines
5.7 KiB
C
/*++
|
|
|
|
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);
|
|
}
|
|
}
|