/// <param name="useMftMirror">Strap the MFT using the MFT mirror</param> public MasterFileTable(NTFSVolume volume, bool useMftMirror, bool manageMftMirror) { m_volume = volume; m_mftRecord = ReadMftRecord(useMftMirror, manageMftMirror); m_mftFile = new NTFSFile(m_volume, m_mftRecord); AttributeRecordLengthToMakeNonResident = m_volume.BytesPerFileRecordSegment * 5 / 16; // We immitate the NTFS v5.1 driver }
public override Stream OpenFile(string path, FileMode mode, FileAccess access, FileShare share, FileOptions options) { FileRecord record; if (mode == FileMode.CreateNew) { record = m_volume.GetFileRecord(path); if (record != null) { throw new AlreadyExistsException(); } } if (mode == FileMode.CreateNew || mode == FileMode.Create || mode == FileMode.OpenOrCreate) { record = m_volume.GetFileRecord(path); if (record == null) { string directoryPath = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); FileRecord directoryRecord = m_volume.GetFileRecord(directoryPath); if (directoryRecord == null) { throw new DirectoryNotFoundException(); } record = m_volume.CreateFile(directoryRecord.BaseSegmentReference, fileName, false); } else if (mode == FileMode.Create) { mode = FileMode.Truncate; } } else // Open, Truncate or Append { record = m_volume.GetFileRecord(path); if (record == null) { throw new FileNotFoundException(); } } if (record.IsDirectory) { throw new UnauthorizedAccessException(); } NTFSFile file = new NTFSFile(m_volume, record); NTFSFileStream stream = new NTFSFileStream(file); if (mode == FileMode.Truncate) { stream.SetLength(0); } else if (mode == FileMode.Append) { stream.Seek((long)file.Length, SeekOrigin.Begin); } return(stream); }
public override Stream OpenFile(string path, FileMode mode, FileAccess access, FileShare share) { if (mode == FileMode.Open || mode == FileMode.Truncate) { FileRecord record = m_volume.GetFileRecord(path); if (record != null && !record.IsDirectory) { NTFSFile file = new NTFSFile(m_volume, record); NTFSFileStream stream = new NTFSFileStream(file); if (mode == FileMode.Truncate) { stream.SetLength(0); } return(stream); } else { throw new FileNotFoundException(); } } throw new Exception("The method or operation is not implemented."); }
public NTFSFileStream(NTFSFile file) { m_file = file; }
public override Stream OpenFile(string path, FileMode mode, FileAccess access, FileShare share, FileOptions options) { string streamName = GetStreamName(path); path = GetFilePath(path); FileRecord fileRecord = null; AttributeRecord dataRecord = null; if (mode == FileMode.CreateNew || mode == FileMode.Create || mode == FileMode.OpenOrCreate) { bool fileExists = false; try { fileRecord = m_volume.GetFileRecord(path); fileExists = true; } catch (FileNotFoundException) { } catch (DirectoryNotFoundException) { } if (fileExists) { if (mode == FileMode.CreateNew) { if (streamName == String.Empty) { throw new AlreadyExistsException(); } else { dataRecord = fileRecord.GetAttributeRecord(AttributeType.Data, streamName); if (dataRecord != null) { throw new AlreadyExistsException(); } } } if (streamName != String.Empty && dataRecord == null) { // 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); } if (mode == FileMode.Create) { mode = FileMode.Truncate; } } else { string directoryPath = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); FileRecord directoryRecord = m_volume.GetFileRecord(directoryPath); fileRecord = m_volume.CreateFile(directoryRecord.BaseSegmentReference, fileName, false); if (streamName != String.Empty) { fileRecord.CreateAttributeRecord(AttributeType.Data, streamName); m_volume.UpdateFileRecord(fileRecord); } } } else // Open, Truncate or Append { fileRecord = m_volume.GetFileRecord(path); dataRecord = fileRecord.GetAttributeRecord(AttributeType.Data, streamName); if (streamName != String.Empty && dataRecord == null) { throw new FileNotFoundException(String.Format("The file '{0}' does not contain a stream named '{1}'", path, streamName)); } } if (fileRecord.IsDirectory) { throw new UnauthorizedAccessException(); } List <NTFSFileStream> openStreams; lock (m_openStreams) { if (m_openStreams.TryGetValue(fileRecord.BaseSegmentNumber, out openStreams)) { if ((access & FileAccess.Write) != 0) { // Currently we only support opening a file stream for write access if no other stream is opened for that file throw new SharingViolationException(); } else if ((access & FileAccess.Read) != 0) { foreach (NTFSFileStream openStream in openStreams) { if (openStream.CanWrite && ((share & FileShare.Write) == 0)) { throw new SharingViolationException(); } } } } else { openStreams = new List <NTFSFileStream>(); m_openStreams.Add(fileRecord.BaseSegmentNumber, openStreams); } } NTFSFile file = new NTFSFile(m_volume, fileRecord, streamName); NTFSFileStream stream = new NTFSFileStream(file, access); openStreams.Add(stream); stream.Closed += delegate(object sender, EventArgs e) { openStreams.Remove(stream); if (openStreams.Count == 0) { lock (m_openStreams) { m_openStreams.Remove(fileRecord.BaseSegmentNumber); } } }; if (mode == FileMode.Truncate) { stream.SetLength(0); } else if (mode == FileMode.Append) { stream.Seek((long)file.Length, SeekOrigin.Begin); } return(stream); }
public NTFSFileStream(NTFSFile file, FileAccess access) { m_file = file; m_canRead = (access & FileAccess.Read) != 0; m_canWrite = (access & FileAccess.Write) != 0; }