Beispiel #1
0
        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);
                        }
                    }
                }
            }
        }
Beispiel #2
0
        internal void RemoveAttributeExtents(NtfsAttribute attr)
        {
            attr.GetDataBuffer().SetCapacity(0);

            foreach (AttributeReference extentRef in attr.Extents.Keys)
            {
                RemoveAttributeExtent(extentRef);
            }
        }
Beispiel #3
0
        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 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];
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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();
        }
Beispiel #7
0
        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 + "  ");
            }
        }
Beispiel #8
0
        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();
        }
Beispiel #9
0
        /// <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);
        }
Beispiel #10
0
        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());
        }
Beispiel #11
0
        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");
        }
Beispiel #12
0
        /// <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);
        }
Beispiel #14
0
        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();
            }
        }
Beispiel #15
0
        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);
                    }
                }
            }
        }
Beispiel #16
0
        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 + "'");
            }
        }
        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 + "'");
            }
        }
Beispiel #19
0
        internal void RemoveAttributeExtents(NtfsAttribute attr)
        {
            attr.GetDataBuffer().SetCapacity(0);

            foreach (var extentRef in attr.Extents.Keys)
            {
                RemoveAttributeExtent(extentRef);
            }
        }
Beispiel #20
0
 public FileStream(File file, NtfsAttribute attr, FileAccess access)
 {
     _file = file;
     _attr = attr;
     _wrapped = attr.Open(access);
 }
Beispiel #21
0
        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();
            }
        }
Beispiel #22
0
 public NtfsStream(File file, NtfsAttribute attr)
 {
     _file = file;
     _attr = attr;
 }
Beispiel #23
0
 public FileStream(File file, NtfsAttribute attr, FileAccess access)
 {
     _file    = file;
     _attr    = attr;
     _wrapped = attr.Open(access);
 }
 public NtfsAttributeBuffer(File file, NtfsAttribute attribute)
 {
     _file = file;
     _attribute = attribute;
 }
 public SparseClusterStream(NtfsAttribute attr, RawClusterStream rawStream)
 {
     _attr = attr;
     _rawStream = rawStream;
 }
 public NtfsAttributeBuffer(File file, NtfsAttribute attribute)
 {
     _file      = file;
     _attribute = attribute;
 }
        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;
        }
Beispiel #28
0
        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));
                }
            }
        }
Beispiel #29
0
 public SparseClusterStream(NtfsAttribute attr, RawClusterStream rawStream)
 {
     _attr      = attr;
     _rawStream = rawStream;
 }