public void WriteSectors(long firstSectorIndex, byte[] data) { if (m_attributeRecord is NonResidentAttributeRecord) { NonResidentAttributeData attributeData = new NonResidentAttributeData(m_volume, m_fileRecord, (NonResidentAttributeRecord)m_attributeRecord); attributeData.WriteSectors(firstSectorIndex, data); } else { byte[] recordData = ((ResidentAttributeRecord)m_attributeRecord).Data; long totalSectors = (long)Math.Ceiling((double)recordData.Length / m_volume.BytesPerSector); long highestSectorIndex = Math.Max(totalSectors - 1, 0); if (firstSectorIndex < 0 || firstSectorIndex > highestSectorIndex) { throw new ArgumentOutOfRangeException("firstSectorIndex is not within the valid range"); } int offset = (int)firstSectorIndex * m_volume.BytesPerSector; int bytesToWrite; if (offset + data.Length <= recordData.Length) { bytesToWrite = data.Length; } else { bytesToWrite = recordData.Length - offset; } ByteWriter.WriteBytes(recordData, offset, data, bytesToWrite); if (m_fileRecord != null) { m_volume.UpdateFileRecord(m_fileRecord); } } }
public override void SetAttributes(string path, bool?isHidden, bool?isReadonly, bool?isArchived) { FileRecord record = m_volume.GetFileRecord(path); if (record != null) { if (isHidden.HasValue) { if (isHidden.Value) { record.StandardInformation.FileAttributes |= FileAttributes.Hidden; } else { record.StandardInformation.FileAttributes &= ~FileAttributes.Hidden; } } if (isReadonly.HasValue) { if (isReadonly.Value) { record.StandardInformation.FileAttributes |= FileAttributes.Readonly; } else { record.StandardInformation.FileAttributes &= ~FileAttributes.Readonly; } } if (isArchived.HasValue) { if (isArchived.Value) { record.StandardInformation.FileAttributes |= FileAttributes.Archive; } else { record.StandardInformation.FileAttributes &= ~FileAttributes.Archive; } } record.StandardInformation.MftModificationTime = DateTime.Now; m_volume.UpdateFileRecord(record); } }
private void UpdateFileNameRecords() { List <FileNameRecord> fileNameRecords = m_fileRecord.FileNameRecords; foreach (FileNameRecord fileNameRecord in fileNameRecords) { fileNameRecord.AllocatedLength = this.Data.AllocatedLength; fileNameRecord.FileSize = this.Data.Length; } m_volume.UpdateFileRecord(m_fileRecord); // Update directory index MftSegmentReference parentDirectory = m_fileRecord.ParentDirectoryReference; FileRecord parentDirectoryRecord = m_volume.GetFileRecord(parentDirectory); IndexData parentDirectoryIndex = new IndexData(m_volume, parentDirectoryRecord, AttributeType.FileName); foreach (FileNameRecord fileNameRecord in fileNameRecords) { parentDirectoryIndex.UpdateFileNameRecord(fileNameRecord); } }
public void AddEntry(MftSegmentReference fileReference, byte[] key) { IndexEntry entry = new IndexEntry(); entry.FileReference = fileReference; entry.Key = key; if (!m_rootRecord.IsParentNode) { int insertIndex = CollationHelper.FindIndexForSortedInsert(m_rootRecord.IndexEntries, key, m_rootRecord.CollationRule); m_rootRecord.IndexEntries.Insert(insertIndex, entry); if (m_rootRecord.RecordLength >= m_volume.AttributeRecordLengthToMakeNonResident) { if (m_indexAllocationRecord == null) { m_indexAllocationRecord = (IndexAllocationRecord)m_fileRecord.CreateAttributeRecord(AttributeType.IndexAllocation, m_indexName); m_indexAllocationData = new NonResidentAttributeData(m_volume, m_fileRecord, m_indexAllocationRecord); m_bitmapRecord = m_fileRecord.CreateAttributeRecord(AttributeType.Bitmap, m_indexName); m_bitmapData = new BitmapData(m_volume, m_fileRecord, m_bitmapRecord, 0); } SplitRootIndexRecord(); } else { m_volume.UpdateFileRecord(m_fileRecord); } } else { KeyValuePairList <int, IndexRecord> path = FindInsertPath(key); IndexRecord leafRecord = path[path.Count - 1].Value; long leafRecordVBN = leafRecord.RecordVBN; int insertIndex = CollationHelper.FindIndexForSortedInsert(leafRecord.IndexEntries, key, m_rootRecord.CollationRule); leafRecord.IndexEntries.Insert(insertIndex, entry); long leafRecordIndex = ConvertToRecordIndex(leafRecordVBN); if (leafRecord.DoesFit((int)m_rootRecord.BytesPerIndexRecord)) { WriteIndexRecord(leafRecordIndex, leafRecord); } else { // Split index record SplitIndexRecord(path); } } }
public override FileSystemEntry CreateFile(string path) { string streamName = GetStreamName(path); path = GetFilePath(path); string parentDirectoryName = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); FileRecord parentDirectoryRecord = m_volume.GetFileRecord(parentDirectoryName); FileRecord fileRecord = null; if (streamName == String.Empty) { fileRecord = m_volume.CreateFile(parentDirectoryRecord.BaseSegmentReference, fileName, false); } else { try { fileRecord = m_volume.GetFileRecord(path); } catch (FileNotFoundException) { } if (fileRecord == null) { fileRecord = m_volume.CreateFile(parentDirectoryRecord.BaseSegmentReference, fileName, false); } else { // We might need to allocate an additional FileRecordSegment so we have to make sure we can extend the MFT if it is full if (m_volume.NumberOfFreeClusters < m_volume.NumberOfClustersRequiredToExtendMft) { throw new DiskFullException(); } } fileRecord.CreateAttributeRecord(AttributeType.Data, streamName); m_volume.UpdateFileRecord(fileRecord); } return(ToFileSystemEntry(path, fileRecord)); }
public void WriteSectors(long firstSectorIndex, byte[] data) { int sectorCount; long lastSectorIndexToWrite; long lastClusterVCNToWrite; int bytesPerSector = m_volume.BytesPerSector; int sectorsPerCluster = m_volume.SectorsPerCluster; ulong firstBytePosition = (ulong)firstSectorIndex * (uint)bytesPerSector; ulong nextBytePosition = firstBytePosition + (uint)data.Length; if (data.Length % bytesPerSector > 0) { int paddedLength = (int)Math.Ceiling((double)data.Length / bytesPerSector) * bytesPerSector; // last sector could be partial, we must zero-fill it before write sectorCount = paddedLength / bytesPerSector; lastSectorIndexToWrite = firstSectorIndex + sectorCount - 1; lastClusterVCNToWrite = lastSectorIndexToWrite / sectorsPerCluster; if (lastClusterVCNToWrite == HighestVCN) { byte[] paddedData = new byte[paddedLength]; Array.Copy(data, paddedData, data.Length); data = paddedData; } else { // only the last sector can be partial throw new ArgumentException("Cannot write partial sector"); } } else { sectorCount = data.Length / bytesPerSector; lastSectorIndexToWrite = firstSectorIndex + sectorCount - 1; lastClusterVCNToWrite = lastSectorIndexToWrite / sectorsPerCluster; } long firstClusterVCN = firstSectorIndex / sectorsPerCluster; if (firstClusterVCN < LowestVCN || lastClusterVCNToWrite > HighestVCN) { string message = String.Format("Cluster VCN {0}-{1} is not within the valid range ({2}-{3})", firstClusterVCN, lastClusterVCNToWrite, LowestVCN, HighestVCN); throw new ArgumentOutOfRangeException(message); } if (firstBytePosition > ValidDataLength) { // We need to zero-fill all the the bytes up to ValidDataLength long firstSectorIndexToFill = (long)(ValidDataLength / (uint)bytesPerSector); int transferSizeInSectors = Settings.MaximumTransferSizeLBA; for (long sectorIndexToFill = firstSectorIndexToFill; sectorIndexToFill < firstSectorIndex; sectorIndexToFill += transferSizeInSectors) { int sectorsToWrite = (int)Math.Min(transferSizeInSectors, firstSectorIndex - firstSectorIndexToFill); byte[] fillData = new byte[sectorsToWrite * bytesPerSector]; if (sectorIndexToFill == firstSectorIndexToFill) { int bytesToRetain = (int)(ValidDataLength % (uint)bytesPerSector); if (bytesToRetain > 0) { byte[] dataToRetain = ReadSectors(firstSectorIndexToFill, 1); Array.Copy(dataToRetain, 0, fillData, 0, bytesToRetain); } } WriteSectors(sectorIndexToFill, fillData); } } KeyValuePairList <long, int> sequence = m_attributeRecord.DataRunSequence.TranslateToLBN(firstSectorIndex, sectorCount, sectorsPerCluster); long bytesWritten = 0; foreach (KeyValuePair <long, int> run in sequence) { byte[] sectors = new byte[run.Value * bytesPerSector]; Array.Copy(data, bytesWritten, sectors, 0, sectors.Length); m_volume.WriteSectors(run.Key, sectors, m_contentType); bytesWritten += sectors.Length; } if (nextBytePosition > ValidDataLength) { m_attributeRecord.ValidDataLength = nextBytePosition; if (m_fileRecord != null) { m_volume.UpdateFileRecord(m_fileRecord); } } }