Пример #1
0
        public void Extend()
        {
            ulong additionalDataLength   = (ulong)(m_volume.BytesPerFileRecordSegment * ExtendGranularity);
            ulong additionalBitmapLength = ExtendGranularity / 8;
            // We calculate the maximum possible number of free cluster required
            long numberOfClustersRequiredForData   = (long)Math.Ceiling((double)additionalDataLength / m_volume.BytesPerCluster);
            long numberOfClustersRequiredForBitmap = (long)Math.Ceiling((double)additionalBitmapLength / m_volume.BytesPerCluster);

            if (numberOfClustersRequiredForData + numberOfClustersRequiredForBitmap > m_volume.NumberOfFreeClusters)
            {
                throw new DiskFullException();
            }

            // We have to extend the bitmap first because one of the constructor parameters is the size of the data.
            // MFT Bitmap: ValidDataLength could be smaller than FileSize, however, we will later copy the value of ValidDataLength.
            // to the MFT mirror, we have to make sure that the copy will not become stale after writing beyond the current ValidDataLength.
            m_mftFile.Bitmap.ExtendBitmap(ExtendGranularity, true);

            // MFT Data: ValidDataLength must be equal to FileSize.
            // This will take care of the FileNameRecord and RootDirectory index as well.
            // Note: The NTFS v5.1 driver does not bother updating the FileNameRecord.
            m_mftFile.WriteData(m_mftFile.Data.Length, new byte[additionalDataLength]);

            // Update the MFT mirror
            MasterFileTable mftMirror = new MasterFileTable(m_volume, false, true);
            // When the MFT has an attribute list, CHKDSK expects the mirror to contain the segment references from the MFT as-is.
            FileRecordSegment mftRecordSegmentFromMirror = mftMirror.GetFileRecordSegment(MasterFileTableSegmentNumber);

            mftRecordSegmentFromMirror.ImmediateAttributes.Clear();
            mftRecordSegmentFromMirror.ImmediateAttributes.AddRange(m_mftFile.FileRecord.BaseSegment.ImmediateAttributes);
            // CHKDSK seems to expect the mirror's NextAttributeInstance to be the same as the MFT.
            mftRecordSegmentFromMirror.NextAttributeInstance = m_mftFile.FileRecord.BaseSegment.NextAttributeInstance;
            mftMirror.UpdateFileRecordSegment(mftRecordSegmentFromMirror);
        }
        public void Extend()
        {
            if (NumberOfClustersRequiredToExtend > m_volume.NumberOfFreeClusters)
            {
                throw new DiskFullException();
            }

            int additionalDataLength = m_volume.BytesPerFileRecordSegment * ExtendGranularity;

            // MFT Bitmap: ValidDataLength could be smaller than FileSize, however, we will later copy the value of ValidDataLength.
            // to the MFT mirror, we have to make sure that the copy will not become stale after writing beyond the current ValidDataLength.
            m_mftBitmap.ExtendBitmap(ExtendGranularity, true);

            // MFT Data: ValidDataLength must be equal to FileSize.
            // We are opting to skip updating the FileNameRecord and RootDirectory index.
            // Note: The NTFS v5.1 driver does not bother updating the FileNameRecord.
            while (additionalDataLength > 0)
            {
                int transferSize = Math.Min(Settings.MaximumTransferSizeLBA * m_volume.BytesPerSector, additionalDataLength);
                m_mftData.WriteBytes(m_mftData.Length, new byte[transferSize]);
                additionalDataLength -= transferSize;
            }

            // Update the MFT mirror
            MasterFileTable mftMirror = new MasterFileTable(m_volume, false, true);
            // When the MFT has an attribute list, CHKDSK expects the mirror to contain the segment references from the MFT as-is.
            FileRecordSegment mftRecordSegmentFromMirror = mftMirror.GetFileRecordSegment(MasterFileTableSegmentNumber);

            mftRecordSegmentFromMirror.ImmediateAttributes.Clear();
            mftRecordSegmentFromMirror.ImmediateAttributes.AddRange(m_mftRecord.BaseSegment.ImmediateAttributes);
            // CHKDSK seems to expect the mirror's NextAttributeInstance to be the same as the MFT.
            mftRecordSegmentFromMirror.NextAttributeInstance = m_mftRecord.BaseSegment.NextAttributeInstance;
            mftMirror.UpdateFileRecordSegment(mftRecordSegmentFromMirror);
        }