private void RemoveFileRecord(FileRecordReference fileReference) { for (int i = 0; i < _records.Count; ++i) { if (_records[i].MasterFileTableIndex == fileReference.MftIndex) { FileRecord record = _records[i]; if (record.Attributes.Count > 0) { throw new IOException("Attempting to remove non-empty MFT record"); } _context.Mft.RemoveRecord(fileReference); _records.Remove(record); if (_records.Count == 1) { NtfsAttribute attrListAttr = GetAttribute(AttributeType.AttributeList, null); if (attrListAttr != null) { RemoveAttribute(attrListAttr); } } } } }
internal void RemoveAttributeExtents(NtfsAttribute attr) { attr.GetDataBuffer().SetCapacity(0); foreach (AttributeReference extentRef in attr.Extents.Keys) { RemoveAttributeExtent(extentRef); } }
public CompressedClusterStream(INtfsContext context, NtfsAttribute attr, RawClusterStream rawStream) { _context = context; _attr = attr; _rawStream = rawStream; _bytesPerCluster = _context.BiosParameterBlock.BytesPerCluster; _cacheBuffer = new byte[_attr.CompressionUnitSize * context.BiosParameterBlock.BytesPerCluster]; _ioBuffer = new byte[_attr.CompressionUnitSize * context.BiosParameterBlock.BytesPerCluster]; }
public SparseStream OpenStream(AttributeType attrType, string name, FileAccess access) { NtfsAttribute attr = GetAttribute(attrType, name); if (attr != null) { return(new FileStream(this, attr, access)); } return(null); }
private void CreateAttributeList() { ushort id = _records[0].CreateAttribute(AttributeType.AttributeList, null, false, AttributeFlags.None); StructuredNtfsAttribute <AttributeList> newAttr = (StructuredNtfsAttribute <AttributeList>) NtfsAttribute.FromRecord(this, MftReference, _records[0].GetAttribute(id)); _attributes.Add(newAttr); UpdateAttributeList(); }
public virtual void Dump(TextWriter writer, string indent) { writer.WriteLine(indent + "FILE (" + ToString() + ")"); writer.WriteLine(indent + " File Number: " + _records[0].MasterFileTableIndex); _records[0].Dump(writer, indent + " "); foreach (AttributeRecord attrRec in _records[0].Attributes) { NtfsAttribute.FromRecord(this, MftReference, attrRec).Dump(writer, indent + " "); } }
public void Delete() { if (_records[0].HardLinkCount != 0) { throw new InvalidOperationException("Attempt to delete in-use file: " + ToString()); } _context.ForgetFile(this); NtfsStream objIdStream = GetStream(AttributeType.ObjectId, null); if (objIdStream != null) { ObjectId objId = objIdStream.GetContent <ObjectId>(); Context.ObjectIds.Remove(objId.Id); } // Truncate attributes, allowing for truncation silently removing the AttributeList attribute // in some cases (large file with all attributes first extent in the first MFT record). This // releases all allocated clusters in most cases. List <NtfsAttribute> truncateAttrs = new List <NtfsAttribute>(_attributes.Count); foreach (NtfsAttribute attr in _attributes) { if (attr.Type != AttributeType.AttributeList) { truncateAttrs.Add(attr); } } foreach (NtfsAttribute attr in truncateAttrs) { attr.GetDataBuffer().SetCapacity(0); } // If the attribute list record remains, free any possible clusters it owns. We've now freed // all clusters. NtfsAttribute attrList = GetAttribute(AttributeType.AttributeList, null); if (attrList != null) { attrList.GetDataBuffer().SetCapacity(0); } // Now go through the MFT records, freeing them up foreach (FileRecord mftRecord in _records) { _context.Mft.RemoveRecord(mftRecord.Reference); } _attributes.Clear(); _records.Clear(); }
/// <summary> /// Creates a new attribute at a fixed cluster. /// </summary> /// <param name="type">The type of the new attribute.</param> /// <param name="name">The name of the new attribute.</param> /// <param name="flags">The flags of the new attribute.</param> /// <param name="firstCluster">The first cluster to assign to the attribute.</param> /// <param name="numClusters">The number of sequential clusters to assign to the attribute.</param> /// <param name="bytesPerCluster">The number of bytes in each cluster.</param> /// <returns>The new attribute.</returns> private NtfsAttribute CreateAttribute(AttributeType type, string name, AttributeFlags flags, long firstCluster, ulong numClusters, uint bytesPerCluster) { bool indexed = _context.AttributeDefinitions.IsIndexed(type); ushort id = _records[0].CreateNonResidentAttribute(type, name, flags, firstCluster, numClusters, bytesPerCluster); AttributeRecord newAttrRecord = _records[0].GetAttribute(id); NtfsAttribute newAttr = NtfsAttribute.FromRecord(this, MftReference, newAttrRecord); _attributes.Add(newAttr); UpdateAttributeList(); MarkMftRecordDirty(); return(newAttr); }
private bool ShrinkIndexRoot(string indexName) { NtfsAttribute attr = GetAttribute(AttributeType.IndexRoot, indexName); // Nothing to win, can't make IndexRoot smaller than this // 8 = min size of entry that points to IndexAllocation... if (attr.Length <= IndexRoot.HeaderOffset + IndexHeader.Size + 8) { return(false); } Index idx = GetIndex(indexName); return(idx.ShrinkRoot()); }
public override string ToString() { foreach (AttributeRecord attr in Attributes) { if (attr.AttributeType == AttributeType.FileName) { StructuredNtfsAttribute <FileNameRecord> fnAttr = (StructuredNtfsAttribute <FileNameRecord>) NtfsAttribute.FromRecord(null, new FileRecordReference(0), attr); return(fnAttr.Content.FileName); } } return("No Name"); }
/// <summary> /// Creates a new attribute. /// </summary> /// <param name="type">The type of the new attribute.</param> /// <param name="name">The name of the new attribute.</param> /// <param name="flags">The flags of the new attribute.</param> /// <returns>The new attribute.</returns> private NtfsAttribute CreateAttribute(AttributeType type, string name, AttributeFlags flags) { bool indexed = _context.AttributeDefinitions.IsIndexed(type); ushort id = _records[0].CreateAttribute(type, name, indexed, flags); AttributeRecord newAttrRecord = _records[0].GetAttribute(id); NtfsAttribute newAttr = NtfsAttribute.FromRecord(this, MftReference, newAttrRecord); _attributes.Add(newAttr); UpdateAttributeList(); MarkMftRecordDirty(); return(newAttr); }
private static CookedDataRuns CookRuns(NtfsAttribute attribute) { CookedDataRuns result = new CookedDataRuns(); foreach (NonResidentAttributeRecord record in attribute.Records) { if (record.StartVcn != result.NextVirtualCluster) { throw new IOException("Invalid NTFS attribute - non-contiguous data runs"); } result.Append(record.DataRuns, record); } return(result); }
private void RemoveAttribute(NtfsAttribute attr) { if (attr != null) { if (attr.PrimaryRecord.AttributeType == AttributeType.IndexRoot) { _indexCache.Remove(attr.PrimaryRecord.Name); } RemoveAttributeExtents(attr); _attributes.Remove(attr); UpdateAttributeList(); } }
internal void FreshenFileName(FileNameRecord fileName, bool updateMftRecord) { // // Freshen the record from the definitive info in the other attributes // StandardInformation si = StandardInformation; NtfsAttribute anonDataAttr = GetAttribute(AttributeType.Data, null); fileName.CreationTime = si.CreationTime; fileName.ModificationTime = si.ModificationTime; fileName.MftChangedTime = si.MftChangedTime; fileName.LastAccessTime = si.LastAccessTime; fileName.Flags = si.FileAttributes; if (MftRecordIsDirty && NtfsTransaction.Current != null) { fileName.MftChangedTime = NtfsTransaction.Current.Timestamp; } // Directories don't have directory flag set in StandardInformation, so set from MFT record if ((_records[0].Flags & FileRecordFlags.IsDirectory) != 0) { fileName.Flags |= FileAttributeFlags.Directory; } if (anonDataAttr != null) { fileName.RealSize = (ulong)anonDataAttr.PrimaryRecord.DataLength; fileName.AllocatedSize = (ulong)anonDataAttr.PrimaryRecord.AllocatedLength; } if (updateMftRecord) { foreach (NtfsStream stream in GetStreams(AttributeType.FileName, null)) { FileNameRecord fnr = stream.GetContent <FileNameRecord>(); if (fnr.Equals(fileName)) { fnr = new FileNameRecord(fileName); fnr.Flags &= ~FileAttributeFlags.ReparsePoint; stream.SetContent(fnr); } } } }
internal void MakeAttributeNonResident(AttributeReference attrRef, int maxData) { NtfsAttribute attr = GetAttribute(attrRef); if (attr.IsNonResident) { throw new InvalidOperationException("Attribute is already non-resident"); } ushort id = _records[0].CreateNonResidentAttribute(attr.Type, attr.Name, attr.Flags); AttributeRecord newAttrRecord = _records[0].GetAttribute(id); IBuffer attrBuffer = attr.GetDataBuffer(); byte[] tempData = StreamUtilities.ReadFully(attrBuffer, 0, (int)Math.Min(maxData, attrBuffer.Capacity)); RemoveAttributeExtents(attr); attr.SetExtent(_records[0].Reference, newAttrRecord); attr.GetDataBuffer().Write(0, tempData, 0, tempData.Length); UpdateAttributeList(); }
public NonResidentAttributeBuffer(File file, NtfsAttribute attribute) : base(file.Context, CookRuns(attribute), file.IndexInMft == MasterFileTable.MftIndex) { _file = file; _attribute = attribute; switch (attribute.Flags & (AttributeFlags.Compressed | AttributeFlags.Sparse)) { case AttributeFlags.Sparse: _activeStream = new SparseClusterStream(_attribute, _rawStream); break; case AttributeFlags.Compressed: _activeStream = new CompressedClusterStream(_context, _attribute, _rawStream); break; case AttributeFlags.None: _activeStream = _rawStream; break; default: throw new NotImplementedException("Unhandled attribute type '" + attribute.Flags + "'"); } }
internal void RemoveAttributeExtents(NtfsAttribute attr) { attr.GetDataBuffer().SetCapacity(0); foreach (var extentRef in attr.Extents.Keys) { RemoveAttributeExtent(extentRef); } }
public FileStream(File file, NtfsAttribute attr, FileAccess access) { _file = file; _attr = attr; _wrapped = attr.Open(access); }
public NtfsStream(File file, NtfsAttribute attr) { _file = file; _attr = attr; }
public NtfsAttributeBuffer(File file, NtfsAttribute attribute) { _file = file; _attribute = attribute; }
public SparseClusterStream(NtfsAttribute attr, RawClusterStream rawStream) { _attr = attr; _rawStream = rawStream; }
private static CookedDataRuns CookRuns(NtfsAttribute attribute) { CookedDataRuns result = new CookedDataRuns(); foreach (NonResidentAttributeRecord record in attribute.Records) { if (record.StartVcn != result.NextVirtualCluster) { throw new IOException("Invalid NTFS attribute - non-contiguous data runs"); } result.Append(record.DataRuns, record); } return result; }
private void LoadAttributes() { Dictionary <long, FileRecord> extraFileRecords = new Dictionary <long, FileRecord>(); AttributeRecord attrListRec = _records[0].GetAttribute(AttributeType.AttributeList); if (attrListRec != null) { NtfsAttribute lastAttr = null; StructuredNtfsAttribute <AttributeList> attrListAttr = (StructuredNtfsAttribute <AttributeList>)NtfsAttribute.FromRecord(this, MftReference, attrListRec); AttributeList attrList = attrListAttr.Content; _attributes.Add(attrListAttr); foreach (AttributeListRecord record in attrList) { FileRecord attrFileRecord = _records[0]; if (record.BaseFileReference.MftIndex != _records[0].MasterFileTableIndex) { if (!extraFileRecords.TryGetValue(record.BaseFileReference.MftIndex, out attrFileRecord)) { attrFileRecord = _context.Mft.GetRecord(record.BaseFileReference); if (attrFileRecord != null) { extraFileRecords[attrFileRecord.MasterFileTableIndex] = attrFileRecord; } } } if (attrFileRecord != null) { AttributeRecord attrRec = attrFileRecord.GetAttribute(record.AttributeId); if (attrRec != null) { if (record.StartVcn == 0) { lastAttr = NtfsAttribute.FromRecord(this, record.BaseFileReference, attrRec); _attributes.Add(lastAttr); } else { lastAttr.AddExtent(record.BaseFileReference, attrRec); } } } } foreach (KeyValuePair <long, FileRecord> extraFileRecord in extraFileRecords) { _records.Add(extraFileRecord.Value); } } else { foreach (AttributeRecord record in _records[0].Attributes) { _attributes.Add(NtfsAttribute.FromRecord(this, MftReference, record)); } } }