reactos操作系统实现(140)

 在创建文件成功后,然后就往文件里写入数据,而写入数据说明就需要文件系统给文件分配储存空间,以便保存这些数据到磁盘里,下面就来分析分配文件大小的函数,如下:

#001  NTSTATUS

#002  VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,

#003                  PVFATFCB Fcb,

#004                  PDEVICE_EXTENSION DeviceExt,

#005                  PLARGE_INTEGER AllocationSize)

#006  {

#007    ULONG OldSize;

#008    ULONG Cluster, FirstCluster;

#009    NTSTATUS Status;

#010 

 

获取每簇分配多少字节。

#011    ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster;

 

获取需要分配的大小字节。

#012    ULONG NewSize = AllocationSize->u.LowPart;

#013    ULONG NCluster;

#014    BOOLEAN AllocSizeChanged = FALSE;

#015 

#016    DPRINT("VfatSetAllocationSizeInformation(File <%wZ>, AllocationSize %d %d)/n", &Fcb->PathNameU,

#017        AllocationSize->HighPart, AllocationSize->LowPart);

#018 

 

获取原来文件的大小。

#019    if (Fcb->Flags & FCB_IS_FATX_ENTRY)

#020      OldSize = Fcb->entry.FatX.FileSize;

#021    else

#022      OldSize = Fcb->entry.Fat.FileSize;

 

如果请求分配超过32位大小,就返回出错,不支持这样的大小。

#023    if (AllocationSize->u.HighPart > 0)

#024    {

#025      return STATUS_INVALID_PARAMETER;

#026    }

 

如果文件的大小与新需求的大小一样,说明它已经分配成功了。

#027    if (OldSize == NewSize)

#028      {

#029        return(STATUS_SUCCESS);

#030      }

#031 

 

从目录项里获取文件的首簇开始位置。

#032    FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);

#033 

 

如果请求的大小大于已经分配的大小,说明需要重新分配更大的空间。

#034    if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart)

#035    {

 

标志分配文件大小发生了改变。

#036      AllocSizeChanged = TRUE;

 

如果首簇为0,说明从第一项开始。

#037      if (FirstCluster == 0)

#038      {

#039        Fcb->LastCluster = Fcb->LastOffset = 0;

 

获取下一簇的标识来判断磁盘是否满了。

#040        Status = NextCluster (DeviceExt, FirstCluster, &FirstCluster, TRUE);

#041        if (!NT_SUCCESS(Status))

#042        {

#043     DPRINT1("NextCluster failed. Status = %x/n", Status);

#044     return Status;

#045        }

 

如果下一簇就已经标记为已满标志,说明磁盘已经写满,不能再写入任何数据,直接返回出错。

#046        if (FirstCluster == 0xffffffff)

#047        {

#048           return STATUS_DISK_FULL;

#049        }

 

计算文件需要分配大小的最后簇号。

#050        Status = OffsetToCluster(DeviceExt, FirstCluster,

#051                                 ROUND_DOWN(NewSize - 1, ClusterSize),

#052                                 &NCluster, TRUE);

 

如果尝试分配不成功,说明磁盘已经满了,不能再保存数据。

#053        if (NCluster == 0xffffffff || !NT_SUCCESS(Status))

#054        {

#055           /* disk is full */

#056           NCluster = Cluster = FirstCluster;

#057           Status = STATUS_SUCCESS;

 

清空所有分配的簇。

#058           while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)

#059           {

#060              Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);

#061              WriteCluster (DeviceExt, Cluster, 0);

#062              Cluster = NCluster;

#063           }

#064           return STATUS_DISK_FULL;

#065        }

 

到这里已经分配文件需要的大小成功,设置文件控制块指向分配的首簇号。

#066        if (Fcb->Flags & FCB_IS_FATX_ENTRY)

#067        {

#068           Fcb->entry.FatX.FirstCluster = FirstCluster;

#069        }

#070        else

#071        {

#072          if (DeviceExt->FatInfo.FatType == FAT32)

#073          {

#074            Fcb->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);

#075            Fcb->entry.Fat.FirstClusterHigh = FirstCluster >> 16;

#076          }

#077          else

#078          {

#079              ASSERT((FirstCluster >> 16) == 0);

#080              Fcb->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);

#081          }

#082        }

#083      }

#084      else

#085      {

 

以下进行不首簇的文件分配。

#086         if (Fcb->LastCluster > 0)

#087         {

#088            if (Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize == Fcb->LastOffset)

#089            {

#090               Cluster = Fcb->LastCluster;

#091               Status = STATUS_SUCCESS;

#092            }

#093            else

#094            {

#095               Status = OffsetToCluster(DeviceExt, Fcb->LastCluster,

#096                                        Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize - Fcb->LastOffset,

#097                                        &Cluster, FALSE);

#098            }

#099         }

#100         else

#101         {

#102            Status = OffsetToCluster(DeviceExt, FirstCluster,

#103                                     Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize,

#104                                     &Cluster, FALSE);

#105         }

#106         if (!NT_SUCCESS(Status))

#107         {

#108            return Status;

#109         }

#110 

#111         Fcb->LastCluster = Cluster;

#112         Fcb->LastOffset = Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize;

#113 

#114         /* FIXME: Check status */

#115         /* Cluster points now to the last cluster within the chain */

#116         Status = OffsetToCluster(DeviceExt, Cluster,

#117                             ROUND_DOWN(NewSize - 1, ClusterSize) - Fcb->LastOffset,

#118                                  &NCluster, TRUE);

#119         if (NCluster == 0xffffffff || !NT_SUCCESS(Status))

#120         {

#121       /* disk is full */

#122       NCluster = Cluster;

#123            Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);

#124       WriteCluster(DeviceExt, Cluster, 0xffffffff);

#125       Cluster = NCluster;

#126            while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)

#127       {

#128         Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);

#129              WriteCluster (DeviceExt, Cluster, 0);

#130         Cluster = NCluster;

#131       }

#132       return STATUS_DISK_FULL;

#133         }

#134      }

#135      UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);

#136    }

#137    else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)

#138    {

 

下面进行文件减小的分配。

#139      AllocSizeChanged = TRUE;

#140      /* FIXME: Use the cached cluster/offset better way. */

#141      Fcb->LastCluster = Fcb->LastOffset = 0;

#142      UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);

#143      if (NewSize > 0)

#144      {

#145        Status = OffsetToCluster(DeviceExt, FirstCluster,

#146               ROUND_DOWN(NewSize - 1, ClusterSize),

#147           &Cluster, FALSE);

#148 

#149        NCluster = Cluster;

#150        Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);

#151        WriteCluster(DeviceExt, Cluster, 0xffffffff);

#152        Cluster = NCluster;

#153      }

#154      else

#155      {

#156        if (Fcb->Flags & FCB_IS_FATX_ENTRY)

#157        {

#158           Fcb->entry.FatX.FirstCluster = 0;

#159        }

#160        else

#161        {

#162          if (DeviceExt->FatInfo.FatType == FAT32)

#163          {

#164            Fcb->entry.Fat.FirstCluster = 0;

#165            Fcb->entry.Fat.FirstClusterHigh = 0;

#166          }

#167          else

#168          {

#169              Fcb->entry.Fat.FirstCluster = 0;

#170          }

#171        }

#172 

#173        NCluster = Cluster = FirstCluster;

#174        Status = STATUS_SUCCESS;

#175      }

#176      while (NT_SUCCESS(Status) && 0xffffffff != Cluster && Cluster > 1)

#177      {

#178         Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);

#179         WriteCluster (DeviceExt, Cluster, 0);

#180         Cluster = NCluster;

#181      }

#182    }

#183    else

#184    {

 

更新文件的大小。

#185       UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);

#186    }

 

更新文件的大小到目录项。

#187    /* Update the on-disk directory entry */

#188    Fcb->Flags |= FCB_IS_DIRTY;

#189    if (AllocSizeChanged)

#190      {

#191        VfatUpdateEntry(Fcb);

#192      }

#193    return STATUS_SUCCESS;

#194  }

你可能感兴趣的:(react)