// Note: there could be up to 2^64 clusters ( http://technet.microsoft.com/en-us/library/cc938432.aspx ) private void Extend(ulong currentNumberOfClusters, ulong additionalNumberOfClusters) { // Each bit in the $Bitmap file represents a cluster. // The size of the $Bitmap file is always a multiple of 8 bytes, extra bits are always set to 1. // // Note: // 1TB of additional allocation will result in a bitmap of 32 MB (assuming 4KB clusters) // 128TB of additional allocation will result in a bitmap of 512 MB (assuming 8KB clusters) byte[] bitmap; ulong nextClusterIndexInBitmap = 0; // the next cluster that will be allocated ulong writeOffset = m_bitmap.Length; if (currentNumberOfClusters % 64 > 0) { ulong numberOfClustersToAllocate = additionalNumberOfClusters - (64 - (currentNumberOfClusters % 64)); ulong numberOfBytesToAllocate = (ulong)Math.Ceiling((double)numberOfClustersToAllocate / 8); numberOfBytesToAllocate = (ulong)Math.Ceiling((double)numberOfBytesToAllocate / 8) * 8; // The last 8 bytes may contain extra bits that were previously set as used, and now have to be free. // We extend the file before reading the last 8 bytes of the bitmap, because it's possible that during the extension, // clusters will be allocated from the last 8 bytes of the $bitmap file. for this reason, we must first extend the file, and then read the bitmap m_bitmap.ExtendFile(numberOfBytesToAllocate); bitmap = new byte[8 + numberOfBytesToAllocate]; // We have to modify the last 8 bytes in the current bitmap (which will be the first in 'bitmap') writeOffset = writeOffset - 8; byte[] temp = m_bitmap.ReadFromFile(writeOffset, 8); Array.Copy(temp, bitmap, 8); nextClusterIndexInBitmap = currentNumberOfClusters % 64; while (nextClusterIndexInBitmap < 64) { ClusterUsageBitmap.UpdateClusterStatus(bitmap, nextClusterIndexInBitmap, false); nextClusterIndexInBitmap++; } nextClusterIndexInBitmap += numberOfClustersToAllocate; } else { ulong additionalNumberOfBytes = (ulong)Math.Ceiling((double)additionalNumberOfClusters / 8); additionalNumberOfBytes = (ulong)Math.Ceiling((double)additionalNumberOfBytes / 8) * 8; bitmap = new byte[additionalNumberOfBytes]; nextClusterIndexInBitmap = additionalNumberOfClusters; } // mark extra bits as used: while (nextClusterIndexInBitmap < (ulong)bitmap.Length * 8) { ClusterUsageBitmap.UpdateClusterStatus(bitmap, nextClusterIndexInBitmap, true); nextClusterIndexInBitmap++; } m_bitmap.WriteToFile(writeOffset, bitmap); }
public NTFSVolume(Volume volume, bool useMftMirror) { m_volume = volume; byte[] bootSector = m_volume.ReadSector(0); m_bootRecord = NTFSBootRecord.ReadRecord(bootSector); if (m_bootRecord != null) { m_mft = new MasterFileTable(this, useMftMirror); m_bitmap = new ClusterUsageBitmap(this); } }