/** @file
  Routines that check references and flush OFiles

Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent


**/

#include "Fat.h"

/**

  Flushes all data associated with the file handle.

  @param  FHand                 - Handle to file to flush.
  @param  Token                 - A pointer to the token associated with the transaction.

  @retval EFI_SUCCESS           - Flushed the file successfully.
  @retval EFI_WRITE_PROTECTED   - The volume is read only.
  @retval EFI_ACCESS_DENIED     - The file is read only.
  @return Others                - Flushing of the file failed.

**/
EFI_STATUS
EFIAPI
FatFlushEx (
  IN EFI_FILE_PROTOCOL  *FHand,
  IN EFI_FILE_IO_TOKEN  *Token
  )
{
  FAT_IFILE   *IFile;
  FAT_OFILE   *OFile;
  FAT_VOLUME  *Volume;
  EFI_STATUS  Status;
  FAT_TASK    *Task;

  IFile  = IFILE_FROM_FHAND (FHand);
  OFile  = IFile->OFile;
  Volume = OFile->Volume;
  Task   = NULL;

  //
  // If the file has a permanent error, return it
  //
  if (EFI_ERROR (OFile->Error)) {
    return OFile->Error;
  }

  if (Volume->ReadOnly) {
    return EFI_WRITE_PROTECTED;
  }

  //
  // If read only, return error
  //
  if (IFile->ReadOnly) {
    return EFI_ACCESS_DENIED;
  }

  if (Token == NULL) {
    FatWaitNonblockingTask (IFile);
  } else {
    //
    // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
    // But if it calls, the below check can avoid crash.
    //
    if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {
      return EFI_UNSUPPORTED;
    }

    Task = FatCreateTask (IFile, Token);
    if (Task == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
  }

  //
  // Flush the OFile
  //
  FatAcquireLock ();
  Status = FatOFileFlush (OFile);
  Status = FatCleanupVolume (OFile->Volume, OFile, Status, Task);
  FatReleaseLock ();

  if (Token != NULL) {
    if (!EFI_ERROR (Status)) {
      Status = FatQueueTask (IFile, Task);
    } else {
      FatDestroyTask (Task);
    }
  }

  return Status;
}

/**

  Flushes all data associated with the file handle.

  @param  FHand                 - Handle to file to flush.

  @retval EFI_SUCCESS           - Flushed the file successfully.
  @retval EFI_WRITE_PROTECTED   - The volume is read only.
  @retval EFI_ACCESS_DENIED     - The file is read only.
  @return Others                - Flushing of the file failed.

**/
EFI_STATUS
EFIAPI
FatFlush (
  IN EFI_FILE_PROTOCOL  *FHand
  )
{
  return FatFlushEx (FHand, NULL);
}

/**

  Flushes & Closes the file handle.

  @param  FHand                 - Handle to the file to delete.

  @retval EFI_SUCCESS           - Closed the file successfully.

**/
EFI_STATUS
EFIAPI
FatClose (
  IN EFI_FILE_PROTOCOL  *FHand
  )
{
  FAT_IFILE   *IFile;
  FAT_OFILE   *OFile;
  FAT_VOLUME  *Volume;

  IFile  = IFILE_FROM_FHAND (FHand);
  OFile  = IFile->OFile;
  Volume = OFile->Volume;

  //
  // Lock the volume
  //
  FatAcquireLock ();

  //
  // Close the file instance handle
  //
  FatIFileClose (IFile);

  //
  // Done. Unlock the volume
  //
  FatCleanupVolume (Volume, OFile, EFI_SUCCESS, NULL);
  FatReleaseLock ();

  //
  // Close always succeed
  //
  return EFI_SUCCESS;
}

/**

  Close the open file instance.

  @param  IFile                 - Open file instance.

  @retval EFI_SUCCESS           - Closed the file successfully.

**/
EFI_STATUS
FatIFileClose (
  FAT_IFILE  *IFile
  )
{
  FAT_OFILE   *OFile;
  FAT_VOLUME  *Volume;

  OFile  = IFile->OFile;
  Volume = OFile->Volume;

  ASSERT_VOLUME_LOCKED (Volume);

  FatWaitNonblockingTask (IFile);

  //
  // Remove the IFile struct
  //
  RemoveEntryList (&IFile->Link);

  //
  // Add the OFile to the check reference list
  //
  if (OFile->CheckLink.ForwardLink == NULL) {
    InsertHeadList (&Volume->CheckRef, &OFile->CheckLink);
  }

  //
  // Done. Free the open instance structure
  //
  FreePool (IFile);
  return EFI_SUCCESS;
}

/**

  Flush the data associated with an open file.
  In this implementation, only last Mod/Access time is updated.

  @param  OFile                 - The open file.

  @retval EFI_SUCCESS           - The OFile is flushed successfully.
  @return Others                - An error occurred when flushing this OFile.

**/
EFI_STATUS
FatOFileFlush (
  IN FAT_OFILE  *OFile
  )
{
  EFI_STATUS     Status;
  FAT_OFILE      *Parent;
  FAT_DIRENT     *DirEnt;
  FAT_DATE_TIME  FatNow;

  //
  // Flush each entry up the tree while dirty
  //
  do {
    //
    // If the file has a permanent error, then don't write any
    // of its data to the device (may be from different media)
    //
    if (EFI_ERROR (OFile->Error)) {
      return OFile->Error;
    }

    Parent = OFile->Parent;
    DirEnt = OFile->DirEnt;
    if (OFile->Dirty) {
      //
      // Update the last modification time
      //
      FatGetCurrentFatTime (&FatNow);
      CopyMem (&DirEnt->Entry.FileLastAccess, &FatNow.Date, sizeof (FAT_DATE));
      if (!OFile->PreserveLastModification) {
        FatGetCurrentFatTime (&DirEnt->Entry.FileModificationTime);
      }

      OFile->PreserveLastModification = FALSE;
      if (OFile->Archive) {
        DirEnt->Entry.Attributes |= FAT_ATTRIBUTE_ARCHIVE;
        OFile->Archive            = FALSE;
      }

      //
      // Write the directory entry
      //
      if ((Parent != NULL) && !DirEnt->Invalid) {
        //
        // Write the OFile's directory entry
        //
        Status = FatStoreDirEnt (Parent, DirEnt);
        if (EFI_ERROR (Status)) {
          return Status;
        }
      }

      OFile->Dirty = FALSE;
    }

    //
    // Check the parent
    //
    OFile = Parent;
  } while (OFile != NULL);

  return EFI_SUCCESS;
}

/**

  Check the references of the OFile.
  If the OFile (that is checked) is no longer
  referenced, then it is freed.

  @param  OFile                 - The OFile to be checked.

  @retval TRUE                  - The OFile is not referenced and freed.
  @retval FALSE                 - The OFile is kept.

**/
BOOLEAN
FatCheckOFileRef (
  IN FAT_OFILE  *OFile
  )
{
  //
  // If the OFile is on the check ref list, remove it
  //
  if (OFile->CheckLink.ForwardLink != NULL) {
    RemoveEntryList (&OFile->CheckLink);
    OFile->CheckLink.ForwardLink = NULL;
  }

  FatOFileFlush (OFile);
  //
  // Are there any references to this OFile?
  //
  if (!IsListEmpty (&OFile->Opens) || !IsListEmpty (&OFile->ChildHead)) {
    //
    // The OFile cannot be freed
    //
    return FALSE;
  }

  //
  // Free the Ofile
  //
  FatCloseDirEnt (OFile->DirEnt);
  return TRUE;
}

/**

  Check the references of all open files on the volume.
  Any open file (that is checked) that is no longer
  referenced, is freed - and its parent open file
  is then referenced checked.

  @param  Volume                - The volume to check the pending open file list.

**/
STATIC
VOID
FatCheckVolumeRef (
  IN FAT_VOLUME  *Volume
  )
{
  FAT_OFILE  *OFile;
  FAT_OFILE  *Parent;

  //
  // Check all files on the pending check list
  //
  while (!IsListEmpty (&Volume->CheckRef)) {
    //
    // Start with the first file listed
    //
    Parent = OFILE_FROM_CHECKLINK (Volume->CheckRef.ForwardLink);
    //
    // Go up the tree cleaning up any un-referenced OFiles
    //
    while (Parent != NULL) {
      OFile  = Parent;
      Parent = OFile->Parent;
      if (!FatCheckOFileRef (OFile)) {
        break;
      }
    }
  }
}

/**

  Set error status for a specific OFile, reference checking the volume.
  If volume is already marked as invalid, and all resources are freed
  after reference checking, the file system protocol is uninstalled and
  the volume structure is freed.

  @param  Volume                - the Volume that is to be reference checked and unlocked.
  @param  OFile                 - the OFile whose permanent error code is to be set.
  @param  EfiStatus             - error code to be set.
  @param  Task                    point to task instance.

  @retval EFI_SUCCESS           - Clean up the volume successfully.
  @return Others                - Cleaning up of the volume is failed.

**/
EFI_STATUS
FatCleanupVolume (
  IN FAT_VOLUME  *Volume,
  IN FAT_OFILE   *OFile,
  IN EFI_STATUS  EfiStatus,
  IN FAT_TASK    *Task
  )
{
  EFI_STATUS  Status;

  //
  // Flag the OFile
  //
  if (OFile != NULL) {
    FatSetVolumeError (OFile, EfiStatus);
  }

  //
  // Clean up any dangling OFiles that don't have IFiles
  // we don't check return status here because we want the
  // volume be cleaned up even the volume is invalid.
  //
  FatCheckVolumeRef (Volume);
  if (Volume->Valid) {
    //
    // Update the free hint info. Volume->FreeInfoPos != 0
    // indicates this a FAT32 volume
    //
    if (Volume->FreeInfoValid && Volume->FatDirty && Volume->FreeInfoPos) {
      Status = FatDiskIo (Volume, WriteDisk, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector, Task);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    //
    // Update that the volume is not dirty
    //
    if (Volume->FatDirty && (Volume->FatType != Fat12)) {
      Volume->FatDirty = FALSE;
      Status           = FatAccessVolumeDirty (Volume, WriteFat, &Volume->NotDirtyValue);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    //
    // Flush all dirty cache entries to disk
    //
    Status = FatVolumeFlushCache (Volume, Task);
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  //
  // If the volume is cleared , remove it.
  // The only time volume be invalidated is in DriverBindingStop.
  //
  if ((Volume->Root == NULL) && !Volume->Valid) {
    //
    // Free the volume structure
    //
    FatFreeVolume (Volume);
  }

  return EfiStatus;
}

/**

  Set the OFile and its child OFile with the error Status

  @param  OFile                 - The OFile whose permanent error code is to be set.
  @param  Status                - Error code to be set.

**/
VOID
FatSetVolumeError (
  IN FAT_OFILE   *OFile,
  IN EFI_STATUS  Status
  )
{
  LIST_ENTRY  *Link;
  FAT_OFILE   *ChildOFile;

  //
  // If this OFile doesn't already have an error, set one
  //
  if (!EFI_ERROR (OFile->Error)) {
    OFile->Error = Status;
  }

  //
  // Set the error on each child OFile
  //
  for (Link = OFile->ChildHead.ForwardLink; Link != &OFile->ChildHead; Link = Link->ForwardLink) {
    ChildOFile = OFILE_FROM_CHILDLINK (Link);
    FatSetVolumeError (ChildOFile, Status);
  }
}
