您的位置:首页 > Web前端 > React

reactos操作系统实现(140)

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

#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 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: