Example #1
0
File: Open.c Project: MattDevo/edk2
/**

  Open a file for a file name relative to an existing OFile.
  The IFile of the newly opened file is passed out.

  @param  OFile                 - The file that serves as a starting reference point.
  @param  NewIFile              - The newly generated IFile instance.
  @param  FileName              - The file name relative to the OFile.
  @param  OpenMode              - Open mode.
  @param  Attributes            - Attributes to set if the file is created.


  @retval EFI_SUCCESS           - Open the file successfully.
  @retval EFI_INVALID_PARAMETER - The open mode is conflict with the attributes
                          or the file name is not valid.
  @retval EFI_NOT_FOUND         - Conficts between dir intention and attribute.
  @retval EFI_WRITE_PROTECTED   - Can't open for write if the volume is read only.
  @retval EFI_ACCESS_DENIED     - If the file's attribute is read only, and the
                          open is for read-write fail it.
  @retval EFI_OUT_OF_RESOURCES  - Can not allocate the memory.

**/
EFI_STATUS
FatOFileOpen (
  IN  FAT_OFILE            *OFile,
  OUT FAT_IFILE            **NewIFile,
  IN  CHAR16               *FileName,
  IN  UINT64               OpenMode,
  IN  UINT8                Attributes
  )
{
  FAT_VOLUME  *Volume;
  EFI_STATUS  Status;
  CHAR16      NewFileName[EFI_PATH_STRING_LENGTH];
  FAT_DIRENT  *DirEnt;
  UINT8       FileAttributes;
  BOOLEAN     WriteMode;

  DirEnt = NULL;
  Volume = OFile->Volume;
  ASSERT_VOLUME_LOCKED (Volume);
  WriteMode = (BOOLEAN) (OpenMode & EFI_FILE_MODE_WRITE);
  if (Volume->ReadOnly && WriteMode) {
    return EFI_WRITE_PROTECTED;
  }
  //
  // Verify the source file handle isn't in an error state
  //
  Status = OFile->Error;
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Get new OFile for the file
  //
  Status = FatLocateOFile (&OFile, FileName, Attributes, NewFileName);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (*NewFileName != 0) {
    //
    // If there's a remaining part of the name, then we had
    // better be creating the file in the directory
    //
    if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) {
      return EFI_NOT_FOUND;
    }

    Status = FatCreateDirEnt (OFile, NewFileName, Attributes, &DirEnt);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    ASSERT (DirEnt != NULL);
    Status = FatOpenDirEnt (OFile, DirEnt);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    OFile = DirEnt->OFile;
    if (OFile->ODir != NULL) {
      //
      // If we just created a directory, we need to create "." and ".."
      //
      Status = FatCreateDotDirEnts (OFile);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }
  }
  //
  // If the file's attribute is read only, and the open is for
  // read-write, then the access is denied.
  //
  FileAttributes = OFile->DirEnt->Entry.Attributes;
  if ((FileAttributes & EFI_FILE_READ_ONLY) != 0 && (FileAttributes & FAT_ATTRIBUTE_DIRECTORY) == 0 && WriteMode) {
    return EFI_ACCESS_DENIED;
  }
  //
  // Create an open instance of the OFile
  //
  Status = FatAllocateIFile (OFile, NewIFile);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  (*NewIFile)->ReadOnly = (BOOLEAN)!WriteMode;

  DEBUG ((EFI_D_INFO, "FSOpen: Open '%S' %r\n", FileName, Status));
  return FatOFileFlush (OFile);
}
Example #2
0
EFI_STATUS
FatIFileAccess (
  IN     EFI_FILE_PROTOCOL     *FHand,
  IN     IO_MODE               IoMode,
  IN OUT UINTN                 *BufferSize,
  IN OUT VOID                  *Buffer,
  IN     EFI_FILE_IO_TOKEN     *Token
  )
/*++

Routine Description:

  Get the file info from the open file of the IFile into Buffer.

Arguments:

  FHand                 - The file handle to access.
  IoMode                - Indicate whether the access mode is reading or writing.
  BufferSize            - Size of Buffer.
  Buffer                - Buffer containing read data.
  Token                 - A pointer to the token associated with the transaction.

Returns:

  EFI_SUCCESS           - Get the file info successfully.
  EFI_DEVICE_ERROR      - Can not find the OFile for the file.
  EFI_VOLUME_CORRUPTED  - The file type of open file is error.
  EFI_WRITE_PROTECTED   - The disk is write protect.
  EFI_ACCESS_DENIED     - The file is read-only.
  other                 - An error occurred when operating on the disk.

--*/
{
  EFI_STATUS  Status;
  FAT_IFILE   *IFile;
  FAT_OFILE   *OFile;
  FAT_VOLUME  *Volume;
  UINT64      EndPosition;
  FAT_TASK    *Task;

  IFile  = IFILE_FROM_FHAND (FHand);
  OFile  = IFile->OFile;
  Volume = OFile->Volume;
  Task   = NULL;

  //
  // Write to a directory is unsupported
  //
  if ((OFile->ODir != NULL) && (IoMode == WRITE_DATA)) {
    return EFI_UNSUPPORTED;
  }

  if (OFile->Error == EFI_NOT_FOUND) {
    return EFI_DEVICE_ERROR;
  }

  if (IoMode == READ_DATA) {
    //
    // If position is at EOF, then return device error
    //
    if (IFile->Position > OFile->FileSize) {
      return EFI_DEVICE_ERROR;
    }
  } else {
    //
    // Check if the we can write data
    //
    if (Volume->ReadOnly) {
      return EFI_WRITE_PROTECTED;
    }

    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;
    }
  }

  FatAcquireLock ();

  Status = OFile->Error;
  if (!EFI_ERROR (Status)) {
    if (OFile->ODir != NULL) {
      //
      // Read a directory is supported
      //
      ASSERT (IoMode == READ_DATA);
      Status = FatIFileReadDir (IFile, BufferSize, Buffer);
      OFile = NULL;
    } else {
      //
      // Access a file
      //
      EndPosition = IFile->Position + *BufferSize;
      if (EndPosition > OFile->FileSize) {
        //
        // The position goes beyond the end of file
        //
        if (IoMode == READ_DATA) {
          //
          // Adjust the actual size read
          //
          *BufferSize -= (UINTN) EndPosition - OFile->FileSize;
        } else {
          //
          // We expand the file size of OFile
          //
          Status = FatGrowEof (OFile, EndPosition);
          if (EFI_ERROR (Status)) {
            //
            // Must update the file's info into the file's Directory Entry
            // and then flush the dirty cache info into disk.
            //
            *BufferSize = 0;
            FatOFileFlush (OFile);
            OFile = NULL;
            goto Done;
          }

          FatUpdateDirEntClusterSizeInfo (OFile);
        }
      }

      Status = FatAccessOFile (OFile, IoMode, (UINTN) IFile->Position, BufferSize, Buffer, Task);
      IFile->Position += *BufferSize;
    }
  }

  if (Token != NULL) {
    if (!EFI_ERROR (Status)) {
      Status = FatQueueTask (IFile, Task);
    } else {
      FatDestroyTask (Task);
    }
  }

Done:
  //
  // On EFI_SUCCESS case, not calling FatCleanupVolume():
  // 1) The Cache flush operation is avoided to enhance
  // performance. Caller is responsible to call Flush() when necessary.
  // 2) The volume dirty bit is probably set already, and is expected to be
  // cleaned in subsequent Flush() or other operations.
  // 3) Write operation doesn't affect OFile/IFile structure, so
  // Reference checking is not necessary.
  //
  if (EFI_ERROR (Status)) {
    Status = FatCleanupVolume (Volume, OFile, Status, NULL);
  }

  FatReleaseLock ();
  return Status;
}
Example #3
0
EFI_STATUS
FatOFileOpen (
  IN  FAT_OFILE            *OFile,
  OUT FAT_IFILE            **NewIFile,
  IN  CHAR16               *FileName,
  IN  UINT64               OpenMode,
  IN  UINT8                Attributes
  )
/*++

Routine Description:

  Open a file for a file name relative to an existing OFile.
  The IFile of the newly opened file is passed out.

Arguments:

  OFile                 - The file that serves as a starting reference point.
  NewIFile              - The newly generated IFile instance.
  FileName              - The file name relative to the OFile.
  OpenMode              - Open mode.
  Attributes            - Attributes to set if the file is created.

Returns:

  EFI_SUCCESS           - Open the file successfully.
  EFI_INVALID_PARAMETER - The open mode is conflict with the attributes
                          or the file name is not valid.
  EFI_NOT_FOUND         - Conficts between dir intention and attribute.
  EFI_WRITE_PROTECTED   - Can't open for write if the volume is read only.
  EFI_ACCESS_DENIED     - If the file's attribute is read only, and the
                          open is for read-write fail it.
  EFI_OUT_OF_RESOURCES  - Can not allocate the memory.

--*/
{
  FAT_VOLUME  *Volume;
  EFI_STATUS  Status;
  CHAR16      NewFileName[EFI_PATH_STRING_LENGTH];
  FAT_DIRENT  *DirEnt;
  UINT8       FileAttributes;
  BOOLEAN     WriteMode;

  DirEnt = NULL;
  Volume = OFile->Volume;
  ASSERT_VOLUME_LOCKED (Volume);
  WriteMode = (BOOLEAN) (OpenMode & EFI_FILE_MODE_WRITE);
  if (Volume->ReadOnly && WriteMode) {
    return EFI_WRITE_PROTECTED;
  }
  //
  // Verify the source file handle isn't in an error state
  //
  Status = OFile->Error;
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Get new OFile for the file
  //
  Status = FatLocateOFile (&OFile, FileName, Attributes, NewFileName);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (*NewFileName != 0) {
    //
    // If there's a remaining part of the name, then we had
    // better be creating the file in the directory
    //
    if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) {
      return EFI_NOT_FOUND;
    }

    Status = FatCreateDirEnt (OFile, NewFileName, Attributes, &DirEnt);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    ASSERT (DirEnt != NULL);
    Status = FatOpenDirEnt (OFile, DirEnt);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    OFile = DirEnt->OFile;
    if (OFile->ODir != NULL) {
      //
      // If we just created a directory, we need to create "." and ".."
      //
      Status = FatCreateDotDirEnts (OFile);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }
  }
  //
  // If the file's attribute is read only, and the open is for
  // read-write, then the access is denied.
  //
  FileAttributes = OFile->DirEnt->Entry.Attributes;
  if ((FileAttributes & EFI_FILE_READ_ONLY) != 0 && (FileAttributes & FAT_ATTRIBUTE_DIRECTORY) == 0 && WriteMode) {
    return EFI_ACCESS_DENIED;
  }
  //
  // Create an open instance of the OFile
  //
  Status = FatAllocateIFile (OFile, NewIFile);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  (*NewIFile)->ReadOnly = (BOOLEAN)!WriteMode;

  DEBUG ((EFI_D_INFO, "FSOpen: Open '%S' %r\n", FileName, Status));
  return FatOFileFlush (OFile);
}