微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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}

原文地址:https://www.jb51.cc/react/308384.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐