public virtual void DeleteFile(FileRecord fileRecord) { MftSegmentReference parentDirectory = fileRecord.ParentDirectoryReference; FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory); IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName); // Update parent directory index List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords; foreach (FileNameRecord fileNameRecord in fileNameRecords) { parentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes()); } // Deallocate all data clusters foreach (AttributeRecord atttributeRecord in fileRecord.Attributes) { if (atttributeRecord is NonResidentAttributeRecord) { NonResidentAttributeData attributeData = new NonResidentAttributeData(this, fileRecord, (NonResidentAttributeRecord)atttributeRecord); attributeData.Truncate(0); } } m_mft.DeleteFile(fileRecord); }
public virtual void DeleteFile(FileRecord fileRecord) { MftSegmentReference parentDirectory = fileRecord.ParentDirectoryReference; FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory); m_mftLock.AcquireWriterLock(Timeout.Infinite); IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName); uint transactionID = m_logClient.AllocateTransactionID(); // Update parent directory index List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords; foreach (FileNameRecord fileNameRecord in fileNameRecords) { parentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes()); } // Deallocate all data clusters foreach (AttributeRecord atttributeRecord in fileRecord.Attributes) { if (atttributeRecord is NonResidentAttributeRecord) { NonResidentAttributeData attributeData = new NonResidentAttributeData(this, fileRecord, (NonResidentAttributeRecord)atttributeRecord); attributeData.Truncate(0); } } m_mft.DeleteFile(fileRecord, transactionID); m_logClient.WriteForgetTransactionRecord(transactionID); m_logClient.WriteRestartRecord(this.MajorVersion, true); m_mftLock.ReleaseWriterLock(); }
public virtual void MoveFile(FileRecord fileRecord, MftSegmentReference newParentDirectory, string newFileName) { // Worst case scenrario: the new parent directory index requires multiple splits if (NumberOfFreeClusters < 4) { throw new DiskFullException(); } FileRecord oldParentDirectoryRecord = GetFileRecord(fileRecord.ParentDirectoryReference); IndexData oldParentDirectoryIndex = new IndexData(this, oldParentDirectoryRecord, AttributeType.FileName); IndexData newParentDirectoryIndex; if (fileRecord.ParentDirectoryReference == newParentDirectory) { newParentDirectoryIndex = oldParentDirectoryIndex; } else { FileRecord newParentDirectoryRecord = GetFileRecord(newParentDirectory); newParentDirectoryIndex = new IndexData(this, newParentDirectoryRecord, AttributeType.FileName); if (newParentDirectoryIndex.ContainsFileName(newFileName)) { throw new AlreadyExistsException(); } } List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords; foreach (FileNameRecord fileNameRecord in fileNameRecords) { oldParentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes()); } DateTime creationTime = fileRecord.FileNameRecord.CreationTime; DateTime modificationTime = fileRecord.FileNameRecord.ModificationTime; DateTime mftModificationTime = fileRecord.FileNameRecord.MftModificationTime; DateTime lastAccessTime = fileRecord.FileNameRecord.LastAccessTime; ulong allocatedLength = fileRecord.FileNameRecord.AllocatedLength; ulong fileSize = fileRecord.FileNameRecord.FileSize; FileAttributes fileAttributes = fileRecord.FileNameRecord.FileAttributes; ushort packedEASize = fileRecord.FileNameRecord.PackedEASize; fileNameRecords = IndexHelper.GenerateFileNameRecords(newParentDirectory, newFileName, fileRecord.IsDirectory, m_generateDosNames, newParentDirectoryIndex, creationTime, modificationTime, mftModificationTime, lastAccessTime, allocatedLength, fileSize, fileAttributes, packedEASize); fileRecord.RemoveAttributeRecords(AttributeType.FileName, String.Empty); foreach (FileNameRecord fileNameRecord in fileNameRecords) { FileNameAttributeRecord fileNameAttribute = (FileNameAttributeRecord)fileRecord.CreateAttributeRecord(AttributeType.FileName, String.Empty); fileNameAttribute.IsIndexed = true; fileNameAttribute.Record = fileNameRecord; } UpdateFileRecord(fileRecord); foreach (FileNameRecord fileNameRecord in fileNameRecords) { newParentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes()); } }
public virtual void DeleteFile(FileRecord fileRecord) { lock (m_mftLock) { MftSegmentReference parentDirectory = fileRecord.ParentDirectoryReference; FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory); IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName); if (fileRecord.IsDirectory) { IndexData directoryIndex = new IndexData(this, fileRecord, AttributeType.FileName); if (!directoryIndex.IsEmpty) { throw new DirectoryNotEmptyException(); } } uint transactionID = m_logClient.AllocateTransactionID(); // Update parent directory index List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords; foreach (FileNameRecord fileNameRecord in fileNameRecords) { parentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes()); } // Deallocate all data clusters foreach (AttributeRecord atttributeRecord in fileRecord.Attributes) { if (atttributeRecord is NonResidentAttributeRecord) { NonResidentAttributeData attributeData = new NonResidentAttributeData(this, fileRecord, (NonResidentAttributeRecord)atttributeRecord); attributeData.Truncate(0); } } m_mft.DeleteFile(fileRecord, transactionID); m_logClient.WriteForgetTransactionRecord(transactionID); m_logClient.WriteRestartRecord(true); } }
public virtual void MoveFile(FileRecord fileRecord, MftSegmentReference newParentDirectory, string newFileName) { // Worst case scenrario: the new parent directory index requires multiple splits. // We assume IndexData.ExtendGranularity is bigger than or equal to the number of splits. if (NumberOfFreeClusters < NumberOfClustersRequiredToExtendIndex) { throw new DiskFullException(); } lock (m_mftLock) { FileRecord oldParentDirectoryRecord = GetFileRecord(fileRecord.ParentDirectoryReference); IndexData oldParentDirectoryIndex = new IndexData(this, oldParentDirectoryRecord, AttributeType.FileName); IndexData newParentDirectoryIndex; if (fileRecord.ParentDirectoryReference == newParentDirectory) { newParentDirectoryIndex = oldParentDirectoryIndex; } else { FileRecord newParentDirectoryRecord = GetFileRecord(newParentDirectory); newParentDirectoryIndex = new IndexData(this, newParentDirectoryRecord, AttributeType.FileName); } if (newParentDirectoryIndex.ContainsFileName(newFileName)) { throw new AlreadyExistsException(); } List <FileNameRecord> fileNameRecords = fileRecord.FileNameRecords; uint transactionID = m_logClient.AllocateTransactionID(); foreach (FileNameRecord fileNameRecord in fileNameRecords) { oldParentDirectoryIndex.RemoveEntry(fileNameRecord.GetBytes()); } // Windows will not update the dates and FileAttributes in $File_Name as often as their counterparts in $STANDARD_INFORMATION. DateTime creationTime = fileRecord.StandardInformation.CreationTime; DateTime modificationTime = fileRecord.StandardInformation.ModificationTime; DateTime mftModificationTime = fileRecord.StandardInformation.MftModificationTime; DateTime lastAccessTime = fileRecord.StandardInformation.LastAccessTime; ulong allocatedLength = fileRecord.FileNameRecord.AllocatedLength; FileAttributes fileAttributes = fileRecord.StandardInformation.FileAttributes; ushort packedEASize = fileRecord.FileNameRecord.PackedEASize; // Windows NTFS v5.1 driver does not usually update the value of the FileSize field belonging to the FileNameRecords that are stored in the FileRecord. // The driver does update the value during a rename, which is inconsistent file creation and is likely to be incidental rather than intentional. // We will set the value to 0 to be consistent with file creation. fileNameRecords = IndexHelper.GenerateFileNameRecords(newParentDirectory, newFileName, fileRecord.IsDirectory, GenerateDosNames, newParentDirectoryIndex, creationTime, modificationTime, mftModificationTime, lastAccessTime, allocatedLength, 0, fileAttributes, packedEASize); fileRecord.RemoveAttributeRecords(AttributeType.FileName, String.Empty); foreach (FileNameRecord fileNameRecord in fileNameRecords) { FileNameAttributeRecord fileNameAttribute = (FileNameAttributeRecord)fileRecord.CreateAttributeRecord(AttributeType.FileName, String.Empty); fileNameAttribute.IsIndexed = true; fileNameAttribute.Record = fileNameRecord; } UpdateFileRecord(fileRecord, transactionID); foreach (FileNameRecord fileNameRecord in fileNameRecords) { if (!fileRecord.IsDirectory) { fileNameRecord.FileSize = fileRecord.DataRecord.DataLength; } newParentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes()); } m_logClient.WriteForgetTransactionRecord(transactionID); m_logClient.WriteRestartRecord(true); } }