info.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 693 行 · 第 1/2 页

C
693
字号

    //
    // File was not found.  We do not allow rename of the current directory if
    // there are open files below the current directory
    //
    
    Renamed = TRUE;

    if (!IsListEmpty(&OFile->ChildHead)) {
      Status = EFI_ACCESS_DENIED;
      goto Done;
    }

    if (OFile->Attributes & EFI_FILE_READ_ONLY) {
      Status = EFI_WRITE_PROTECTED;
      goto Done;
    }

    //
    // See if we can create the new filename
    // N.B. If this is a rename of a directory, we first create the
    // name as a file as to not allocate any space for it.
    //

    Status = FatOFileOpen(
          OFile->Parent, 
          &NewIFile, 
          NewInfo->FileName,
          EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
          OFile->Attributes & ~EFI_FILE_DIRECTORY
          );

    if (EFI_ERROR(Status)) {
      goto Done;
    }

    //
    // File was created. 
    // Move the data stream to the new file.  Update the attributes
    // to capture the directory attribute bit.
    //

    NewOFile = NewIFile->OFile;
    if (NewOFile->FileCluster != FAT_CLUSTER_FREE) {
      Status = EFI_VOLUME_CORRUPTED;
      goto Done;
    }    

    NewOFile->FileSize = OFile->FileSize;
    NewOFile->FileCluster = OFile->FileCluster;
    NewOFile->FileCurrentCluster = OFile->FileCluster;
    NewOFile->FileLastCluster = OFile->FileLastCluster;
    NewOFile->DirType = OFile->DirType;
    NewOFile->Attributes = OFile->Attributes;
    NewOFile->ChildHashTable = OFile->ChildHashTable;
    NewOFile->HashTopPosition = OFile->HashTopPosition;
    NewOFile->HashEntry1 = OFile->HashEntry1;
    NewOFile->HashEntry2 = OFile->HashEntry2;
    NewOFile->CurrentEntryPos = OFile->CurrentEntryPos;
    NewOFile->FreeEntryPos = OFile->FreeEntryPos;
    NewOFile->NameNotFound = OFile->NameNotFound;

    OFile->FileSize = 0;
    OFile->FileCluster = FAT_CLUSTER_FREE;
    OFile->FileCurrentCluster = FAT_CLUSTER_FREE;
    OFile->FileLastCluster = 0;
    OFile->Dirty = TRUE;
    OFile->DirType = IsEmpty;
    OFile->ChildHashTable = NULL;
    OFile->NameNotFound = NULL;

    //
    // Move all the open handles to the new entry
    // This version could pass /O1 and /Ow optimization switch
    //
    
    List = OFile->Opens.ForwardLink;
    while (List != &OFile->Opens) {
      Open = CR(List, FAT_IFILE, Link, FAT_IFILE_SIGNATURE);
      List = List->ForwardLink;
      RemoveEntryList (&Open->Link);
      Open->OFile = NewOFile;
      InsertTailList (&NewOFile->Opens, &Open->Link);
    }      
         
    //
    // Add the OFile to the check reference list
    //

    if (!OFile->CheckLink.ForwardLink) {
      InsertHeadList (&Vol->CheckRef, &OFile->CheckLink);
    }

    //
    // Apply the remaining SetInfo updates to the new ofile
    //

    OFile = NewOFile;
  }

  //
  // Set file info is dirty
  //

  OFile->Dirty = TRUE;

  //
  // If the file size has changed, apply it
  //

  if (NewInfo->FileSize < OFile->FileSize) {
    OFile->FileSize = NewInfo->FileSize;
    Status = FatShrinkEof (OFile);
    if (EFI_ERROR(Status)) {
      goto Done;
    }
  }

  if (NewInfo->FileSize > OFile->FileSize) {
    Status = FatGrowEof (OFile, NewInfo->FileSize);
    if (EFI_ERROR(Status)) {
      FatShrinkEof (OFile);
      goto Done;
    }
    *ZeroBufferSize = (UINTN)(NewInfo->FileSize - OFile->FileSize);       
    ZeroBuffer = EfiLibAllocateZeroPool (*ZeroBufferSize);
    if (!ZeroBuffer) {
      gBS->FreePool (ZeroBuffer);
      return EFI_OUT_OF_RESOURCES;
    }
    FatOFileWrite (OFile, OFile->FileSize, ZeroBufferSize, ZeroBuffer);
    if (ZeroBuffer) {
      gBS->FreePool (ZeroBuffer);
    }
    OFile->FileSize = NewInfo->FileSize;            
  }


  //
  // Set the time info
  //

  EfiCopyMem (&OFile->CreateTime, &NewInfo->CreateTime, sizeof(EFI_TIME));
  if (EfiCompareMem (&OFile->LastModification,
                     &NewInfo->ModificationTime,
                     sizeof(EFI_TIME))) {
    
    //
    // User wants to specify a modification time, don't update it when flush
    //
    OFile->PreserveLastMod = TRUE;
    EfiCopyMem (&OFile->LastModification,
                &NewInfo->ModificationTime,
                sizeof(EFI_TIME)
                );
  }  
  EfiCopyMem (&OFile->LastAccess, &NewInfo->LastAccessTime, sizeof(EFI_TIME));

    //
    // If this is a directory, synchronize it's  contained dot file's 
    // date and time field
    // Be noted that now Sync failure is simply ignored
    //
    
    if (OFile->DirType == IsDir &&(!FatIsDotEntry(OFile))) {
      Position = 0;
      for (; ;) {   
        SyncStatus = FatGetDirOFile (OFile, &Position, &Entry);
        //if some msg need to info user, we can use Sync_Status
        if (EFI_ERROR(SyncStatus)) {
        break;
        }

        if (Entry->DirType != IsEmpty  && FatIsDotEntry(Entry)) {   
          Entry->PreserveLastMod = TRUE;     
          Entry->Dirty = TRUE;
          EfiCopyMem (&Entry->CreateTime, 
                      &NewInfo->CreateTime, 
                      sizeof(EFI_TIME));                 
          EfiCopyMem (&Entry->LastAccess,
                      &NewInfo->LastAccessTime, 
                      sizeof(EFI_TIME));
          EfiCopyMem (&Entry->LastModification,
                      &NewInfo->ModificationTime,
                      sizeof(EFI_TIME));
         break; 
        }
      }
    }         

  //
  // Set the current attributes
  //

  OFile->Attributes = (UINT8)((OFile->Attributes & ~EFI_FILE_VALID_ATTR) |
                              (UINT8) NewInfo->Attribute);
  
  //
  // If the file is renamed, we should append the ARCHIVE attribute
  //
  
  if (Renamed) {
    OFile->Attributes = (UINT8)(OFile->Attributes | FAT_ATTRIBUTE_ARCHIVE);
  }
    
  //
  // Done
  //

Done:

  //
  // If we opened a handle, close it
  //

  if (NewIFile) {
    FatIFileClose (NewIFile);
  }

  //
  // Write the dirent changes for the new file
  //

  if (NewOFile) {
    FatOFileFlush(NewOFile);
  }

  return Status;
}


EFI_STATUS
EFIAPI
FatGetInfo (
  IN EFI_FILE   *FHand,
  IN EFI_GUID   *Type,
  IN OUT UINTN  *BufferSize,
  OUT VOID      *Buffer
  )
{
  FAT_IFILE               *IFile;
  FAT_OFILE               *OFile;
  FAT_VOLUME              *Vol;
  EFI_STATUS              Status;
  
  IFile =  IFILE_FROM_FHAND(FHand);
  OFile = IFile->OFile;
  Vol   = OFile->Vol;

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

  FatAcquireLock ();

  //
  // Verify the file handle isn't in an error state
  //


  if (!Status) {

    //
    // Get the proper information based on the request
    //

    Status = EFI_UNSUPPORTED;
    if (EfiCompareGuid (Type, &gEfiFileInfoGuid)) {
      Status = FatGetFileInfo (Vol, OFile, BufferSize, Buffer);
    }

    if (EfiCompareGuid (Type, &gEfiFileInfoIdGuid)) {
      Status = FatGetVolumeInfo (Vol, BufferSize, Buffer);
    }

    if (EfiCompareGuid (Type, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
      Status = FatGetVolumeLabelInfo (Vol, BufferSize, Buffer);
    }

  }

  Status = FatCleanupVolume (OFile->Vol, NULL, Status);
  
  FatReleaseLock();
  return Status;
}
  

EFI_STATUS
EFIAPI
FatSetInfo (
  IN EFI_FILE  *FHand,
  IN EFI_GUID  *Type,
  IN UINTN     BufferSize,
  IN VOID      *Buffer
  )
{
  FAT_IFILE               *IFile;
  FAT_OFILE               *OFile;
  FAT_VOLUME              *Vol;
  EFI_STATUS              Status;
  
  IFile =  IFILE_FROM_FHAND(FHand);
  OFile = IFile->OFile;
  Vol   = OFile->Vol;

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

  //
  // Verify the file handle isn't in an error state
  //


  if (!Status) {

    //
    // Get the proper information based on the request
    //

    Status = EFI_UNSUPPORTED;
    if (EfiCompareGuid (Type, &gEfiFileInfoGuid)) {
      Status = FatSetFileInfo (Vol, IFile, OFile, BufferSize, Buffer);
    }

    if (EfiCompareGuid (Type, &gEfiFileInfoIdGuid)) {
      Status = FatSetVolumeInfo (Vol, BufferSize, Buffer);
    }

    if (EfiCompareGuid (Type, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
      Status = FatSetVolumeLabelInfo (Vol, BufferSize, Buffer);
    }
  }

  Status = FatCleanupVolume (OFile->Vol, NULL, Status);
  
  FatReleaseLock();
  return Status;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?