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, #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,&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, #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, #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,FALSE); #124 WriteCluster(DeviceExt,0xffffffff); #125 Cluster = NCluster; #126 while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1) #127 { #128 Status = NextCluster (DeviceExt,FALSE); #129 WriteCluster (DeviceExt,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,ClusterSize); #143 if (NewSize > 0) #144 { #145 Status = OffsetToCluster(DeviceExt, #146 ROUND_DOWN(NewSize - 1, #147 &Cluster,FALSE); #148 #149 NCluster = Cluster; #150 Status = NextCluster (DeviceExt,FALSE); #151 WriteCluster(DeviceExt,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,FALSE); #179 WriteCluster (DeviceExt,0); #180 Cluster = NCluster; #181 } #182 } #183 else #184 {
更新文件的大小。 #185 UpdateFileSize(FileObject,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} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |