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

reactos操作系统实现(140)

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

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