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