public static MasterRecord CreateNewVolume([NotNull] IDirectDiskAccess access, ulong size) { Validate.ArgumentNotNull(access, "access"); if (size % Constants.BlockSizeBytes != 0) { throw new ArgumentOutOfRangeException("Volume size should be on block size boundary."); } if (size <= BlockGroup.ReservedBlocks * Constants.BlockSizeBytes) { throw new ArgumentOutOfRangeException(string.Format("Min volume size is {0}", Constants.BlockSizeBytes * (BlockGroup.ReservedBlocks + 1))); } var totalBlocks = (uint)(size / Constants.BlockSizeBytes); uint numberOfFullGroups = totalBlocks / Constants.BlocksPerGroup; uint remainingBlocks = totalBlocks % Constants.BlocksPerGroup; if (remainingBlocks > BlockGroup.ReservedBlocks) { numberOfFullGroups++; } var rec = new MasterRecord(access); rec._groupsReserved = new BlockGroup[numberOfFullGroups]; var offset = new Address(32 + (BlockGroupDescriptor.RawSizeBytes * numberOfFullGroups)); offset = offset.AlignOnBlockBoundary; uint totalFreeBlocks = 0; for (uint i = 0; i < numberOfFullGroups; ++i) { bool last = (i == numberOfFullGroups - 1 && remainingBlocks > 0); var groupSize = last ? remainingBlocks : Constants.BlocksPerGroup; var newGroup = new BlockGroup(offset, groupSize); offset = offset.AddBlocks(groupSize); totalFreeBlocks += newGroup.Descriptor.NumFreeBlocksInGroup; rec._groupsReserved[i] = newGroup; } rec._freeSpaceBlocks = totalFreeBlocks; rec.VolumeSize = offset.Value; rec.RootNode = rec.CreateDirectoryNode("\\", null); return rec; }