/** @file | |
Function that deletes a file. | |
Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "Fat.h" | |
/** | |
Deletes the file & Closes the file handle. | |
@param FHand - Handle to the file to delete. | |
@retval EFI_SUCCESS - Delete the file successfully. | |
@retval EFI_WARN_DELETE_FAILURE - Fail to delete the file. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
FatDelete ( | |
IN EFI_FILE_PROTOCOL *FHand | |
) | |
{ | |
FAT_IFILE *IFile; | |
FAT_OFILE *OFile; | |
FAT_DIRENT *DirEnt; | |
EFI_STATUS Status; | |
UINTN Round; | |
IFile = IFILE_FROM_FHAND (FHand); | |
OFile = IFile->OFile; | |
FatWaitNonblockingTask (IFile); | |
// | |
// Lock the volume | |
// | |
FatAcquireLock (); | |
// | |
// If the file is read-only, then don't delete it | |
// | |
if (IFile->ReadOnly) { | |
Status = EFI_WRITE_PROTECTED; | |
goto Done; | |
} | |
// | |
// If the file is the root dir, then don't delete it | |
// | |
if (OFile->Parent == NULL) { | |
Status = EFI_ACCESS_DENIED; | |
goto Done; | |
} | |
// | |
// If the file has a permanent error, skip the delete | |
// | |
Status = OFile->Error; | |
if (!EFI_ERROR (Status)) { | |
// | |
// If this is a directory, make sure it's empty before | |
// allowing it to be deleted | |
// | |
if (OFile->ODir != NULL) { | |
// | |
// We do not allow to delete nonempty directory | |
// | |
FatResetODirCursor (OFile); | |
for (Round = 0; Round < 3; Round++) { | |
Status = FatGetNextDirEnt (OFile, &DirEnt); | |
if ((EFI_ERROR (Status)) || | |
((Round < 2) && ((DirEnt == NULL) || !FatIsDotDirEnt (DirEnt))) || | |
((Round == 2) && (DirEnt != NULL)) | |
) | |
{ | |
Status = EFI_ACCESS_DENIED; | |
goto Done; | |
} | |
} | |
} | |
// | |
// Return the file's space by setting its size to 0 | |
// | |
FatTruncateOFile (OFile, 0); | |
// | |
// Free the directory entry for this file | |
// | |
Status = FatRemoveDirEnt (OFile->Parent, OFile->DirEnt); | |
if (EFI_ERROR (Status)) { | |
goto Done; | |
} | |
// | |
// Set a permanent error for this OFile in case there | |
// are still opened IFiles attached | |
// | |
OFile->Error = EFI_NOT_FOUND; | |
} else if (OFile->Error == EFI_NOT_FOUND) { | |
Status = EFI_SUCCESS; | |
} | |
Done: | |
// | |
// Always close the handle | |
// | |
FatIFileClose (IFile); | |
// | |
// Done | |
// | |
Status = FatCleanupVolume (OFile->Volume, NULL, Status, NULL); | |
FatReleaseLock (); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_WARN_DELETE_FAILURE; | |
} | |
return Status; | |
} |