public virtual FileRecord CreateFile(MftSegmentReference parentDirectory, string fileName, bool isDirectory) { // Worst case scenrario: the MFT might be full and the parent directory index requires multiple splits if (NumberOfFreeClusters < 24) { throw new DiskFullException(); } FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory); IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName); if (parentDirectoryIndex.ContainsFileName(fileName)) { throw new AlreadyExistsException(); } List <FileNameRecord> fileNameRecords = IndexHelper.GenerateFileNameRecords(parentDirectory, fileName, isDirectory, m_generateDosNames, parentDirectoryIndex); FileRecord fileRecord = m_mft.CreateFile(fileNameRecords); // Update parent directory index foreach (FileNameRecord fileNameRecord in fileNameRecords) { parentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes()); } return(fileRecord); }
public virtual FileRecord CreateFile(MftSegmentReference parentDirectory, string fileName, bool isDirectory) { // Worst case scenrario: the MFT might be full and the parent directory index requires multiple splits if (NumberOfFreeClusters < 24) { throw new DiskFullException(); } FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory); m_mftLock.AcquireWriterLock(Timeout.Infinite); IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName); if (parentDirectoryIndex.ContainsFileName(fileName)) { m_mftLock.ReleaseWriterLock(); throw new AlreadyExistsException(); } List <FileNameRecord> fileNameRecords = IndexHelper.GenerateFileNameRecords(parentDirectory, fileName, isDirectory, m_generateDosNames, parentDirectoryIndex); uint transactionID = m_logClient.AllocateTransactionID(); FileRecord fileRecord = m_mft.CreateFile(fileNameRecords, transactionID); // Update parent directory index foreach (FileNameRecord fileNameRecord in fileNameRecords) { parentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes()); } m_logClient.WriteForgetTransactionRecord(transactionID); m_logClient.WriteRestartRecord(this.MajorVersion, true); m_mftLock.ReleaseWriterLock(); return(fileRecord); }
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 static string GenerateDosName(IndexData parentDirectoryIndex, string fileName) { string nameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); string extension = Path.GetExtension(fileName); nameWithoutExtension = ConvertToDosCharacters(nameWithoutExtension).ToUpper(); if (extension.Length > 0) { extension = "." + ConvertToDosCharacters(extension.Substring(1)).ToUpper(); } if (nameWithoutExtension.Length > 8) { nameWithoutExtension = nameWithoutExtension.Substring(0, 6) + "~1"; } if (extension.Length > 4) { extension = extension.Substring(0, 4); } int index = 1; string shortNameWithoutExtension; while (index <= 0xFFFFFF) { string suffix = "~" + index.ToString("X"); int nameCharsToKeep = Math.Min(nameWithoutExtension.Length, 8 - suffix.Length); shortNameWithoutExtension = nameWithoutExtension.Substring(0, nameCharsToKeep) + suffix; string dosFileName = shortNameWithoutExtension + extension; if (!parentDirectoryIndex.ContainsFileName(dosFileName)) { return(dosFileName); } index++; } // Extremely unlikely that we will ever get here throw new NotSupportedException(String.Format("Could not find an available DOS name for '{0}'", fileName)); }
public virtual FileRecord CreateFile(MftSegmentReference parentDirectory, string fileName, bool isDirectory) { if (fileName.Length > FileNameRecord.MaxFileNameLength) { throw new InvalidNameException(); } // Worst case scenrario: the MFT might be full and the parent directory index requires multiple splits. // We assume IndexData.ExtendGranularity is bigger than or equal to the number of splits. if (NumberOfFreeClusters < m_mft.NumberOfClustersRequiredToExtend + NumberOfClustersRequiredToExtendIndex) { throw new DiskFullException(); } lock (m_mftLock) { FileRecord parentDirectoryRecord = GetFileRecord(parentDirectory); IndexData parentDirectoryIndex = new IndexData(this, parentDirectoryRecord, AttributeType.FileName); if (parentDirectoryIndex.ContainsFileName(fileName)) { throw new AlreadyExistsException(); } List <FileNameRecord> fileNameRecords = IndexHelper.GenerateFileNameRecords(parentDirectory, fileName, isDirectory, GenerateDosNames, parentDirectoryIndex); uint transactionID = m_logClient.AllocateTransactionID(); FileRecord fileRecord = m_mft.CreateFile(fileNameRecords, transactionID); // Update parent directory index foreach (FileNameRecord fileNameRecord in fileNameRecords) { parentDirectoryIndex.AddEntry(fileRecord.BaseSegmentReference, fileNameRecord.GetBytes()); } m_logClient.WriteForgetTransactionRecord(transactionID); m_logClient.WriteRestartRecord(true); return(fileRecord); } }