private void Truncate(long value)
        {
            long endVcn = Utilities.Ceil(value, _bytesPerCluster);

            // Release the clusters
            _activeStream.TruncateToClusters(endVcn);

            // First, remove any extents that are now redundant.
            Dictionary <AttributeReference, AttributeRecord> extentCache = new Dictionary <AttributeReference, AttributeRecord>(_attribute.Extents);

            foreach (var extent in extentCache)
            {
                if (extent.Value.StartVcn >= endVcn)
                {
                    NonResidentAttributeRecord record = (NonResidentAttributeRecord)extent.Value;
                    _file.RemoveAttributeExtent(extent.Key);
                    _attribute.RemoveExtentCacheSafe(extent.Key);
                }
            }

            PrimaryAttributeRecord.LastVcn               = Math.Max(0, endVcn - 1);
            PrimaryAttributeRecord.AllocatedLength       = endVcn * _bytesPerCluster;
            PrimaryAttributeRecord.DataLength            = value;
            PrimaryAttributeRecord.InitializedDataLength = Math.Min(PrimaryAttributeRecord.InitializedDataLength, value);

            _file.MarkMftRecordDirty();
        }
Example #2
0
        public void Append(IEnumerable <DataRun> rawRuns, NonResidentAttributeRecord attributeExtent)
        {
            long vcn = NextVirtualCluster;
            long lcn = 0;

            foreach (var run in rawRuns)
            {
                _runs.Add(new CookedDataRun(run, vcn, lcn, attributeExtent));
                vcn += run.RunLength;
                lcn += run.RunOffset;
            }
        }
Example #3
0
        public CookedDataRun(DataRun raw, long startVcn, long prevLcn, NonResidentAttributeRecord attributeExtent)
        {
            _raw             = raw;
            _startVcn        = startVcn;
            _startLcn        = prevLcn + raw.RunOffset;
            _attributeExtent = attributeExtent;

            if (startVcn < 0)
            {
                throw new ArgumentOutOfRangeException("startVcn", startVcn, "VCN must be >= 0");
            }

            if (_startLcn < 0)
            {
                throw new ArgumentOutOfRangeException("prevLcn", prevLcn, "LCN must be >= 0");
            }
        }
        public CookedDataRun(DataRun raw, long startVcn, long prevLcn, NonResidentAttributeRecord attributeExtent)
        {
            _raw = raw;
            _startVcn = startVcn;
            _startLcn = prevLcn + raw.RunOffset;
            _attributeExtent = attributeExtent;

            if (startVcn < 0)
            {
                throw new ArgumentOutOfRangeException("startVcn", startVcn, "VCN must be >= 0");
            }

            if (_startLcn < 0)
            {
                throw new ArgumentOutOfRangeException("prevLcn", prevLcn, "LCN must be >= 0");
            }
        }
Example #5
0
        public override void ExpandToClusters(long numVirtualClusters, NonResidentAttributeRecord extent, bool allocate)
        {
            long totalVirtualClusters = _cookedRuns.NextVirtualCluster;

            if (totalVirtualClusters < numVirtualClusters)
            {
                NonResidentAttributeRecord realExtent = extent;
                if (realExtent == null)
                {
                    realExtent = _cookedRuns.Last.AttributeExtent;
                }

                DataRun newRun = new DataRun(0, numVirtualClusters - totalVirtualClusters, true);
                realExtent.DataRuns.Add(newRun);
                _cookedRuns.Append(newRun, extent);
                realExtent.LastVcn = numVirtualClusters - 1;
            }

            if (allocate)
            {
                AllocateClusters(totalVirtualClusters, (int)(numVirtualClusters - totalVirtualClusters));
            }
        }
Example #6
0
 public CookedDataRuns(IEnumerable <DataRun> rawRuns, NonResidentAttributeRecord attributeExtent)
 {
     _runs = new List <CookedDataRun>();
     Append(rawRuns, attributeExtent);
 }
Example #7
0
        public void Append(DataRun rawRun, NonResidentAttributeRecord attributeExtent)
        {
            CookedDataRun last = Last;

            _runs.Add(new CookedDataRun(rawRun, NextVirtualCluster, last == null ? 0 : last.StartLcn, attributeExtent));
        }
 public abstract void ExpandToClusters(long numVirtualClusters, NonResidentAttributeRecord extent, bool allocate);
        public override void ExpandToClusters(long numVirtualClusters, NonResidentAttributeRecord extent, bool allocate)
        {
            long totalVirtualClusters = _cookedRuns.NextVirtualCluster;
            if (totalVirtualClusters < numVirtualClusters)
            {
                NonResidentAttributeRecord realExtent = extent;
                if (realExtent == null)
                {
                    realExtent = _cookedRuns.Last.AttributeExtent;
                }

                DataRun newRun = new DataRun(0, numVirtualClusters - totalVirtualClusters, true);
                realExtent.DataRuns.Add(newRun);
                _cookedRuns.Append(newRun, extent);
                realExtent.LastVcn = numVirtualClusters - 1;
            }

            if (allocate)
            {
                AllocateClusters(totalVirtualClusters, (int)(numVirtualClusters - totalVirtualClusters));
            }
        }
Example #10
0
 public override void ExpandToClusters(long numVirtualClusters, NonResidentAttributeRecord extent, bool allocate)
 {
     _rawStream.ExpandToClusters(Utilities.RoundUp(numVirtualClusters, _attr.CompressionUnitSize), extent, false);
 }
        private bool VerifyMftRecord(byte[] recordData, bool presentInBitmap, int bytesPerSector)
        {
            bool ok = true;

            //
            // Verify the attributes seem OK...
            //
            byte[] tempBuffer = new byte[recordData.Length];
            Array.Copy(recordData, tempBuffer, tempBuffer.Length);
            GenericFixupRecord genericRecord = new GenericFixupRecord(bytesPerSector);

            genericRecord.FromBytes(tempBuffer, 0);

            int pos = Utilities.ToUInt16LittleEndian(genericRecord.Content, 0x14);

            while (Utilities.ToUInt32LittleEndian(genericRecord.Content, pos) != 0xFFFFFFFF)
            {
                int attrLen;
                try
                {
                    AttributeRecord ar = AttributeRecord.FromBytes(genericRecord.Content, pos, out attrLen);
                    if (attrLen != ar.Size)
                    {
                        ReportError("Attribute size is different to calculated size.  AttrId={0}", ar.AttributeId);
                        ok = false;
                    }

                    if (ar.IsNonResident)
                    {
                        NonResidentAttributeRecord nrr = (NonResidentAttributeRecord)ar;
                        if (nrr.DataRuns.Count > 0)
                        {
                            long totalVcn = 0;
                            foreach (var run in nrr.DataRuns)
                            {
                                totalVcn += run.RunLength;
                            }

                            if (totalVcn != nrr.LastVcn - nrr.StartVcn + 1)
                            {
                                ReportError("Declared VCNs doesn't match data runs.  AttrId={0}", ar.AttributeId);
                                ok = false;
                            }
                        }
                    }
                }
                catch
                {
                    ReportError("Failure parsing attribute at pos={0}", pos);
                    return(false);
                }

                pos += attrLen;
            }

            //
            // Now consider record as a whole
            //
            FileRecord record = new FileRecord(bytesPerSector);

            record.FromBytes(recordData, 0);

            bool inUse = (record.Flags & FileRecordFlags.InUse) != 0;

            if (inUse != presentInBitmap)
            {
                ReportError("MFT bitmap and record in-use flag don't agree.  Mft={0}, Record={1}", presentInBitmap ? "InUse" : "Free", inUse ? "InUse" : "Free");
                ok = false;
            }

            if (record.Size != record.RealSize)
            {
                ReportError("MFT record real size is different to calculated size.  Stored in MFT={0}, Calculated={1}", record.RealSize, record.Size);
                ok = false;
            }

            if (Utilities.ToUInt32LittleEndian(recordData, (int)record.RealSize - 8) != uint.MaxValue)
            {
                ReportError("MFT record is not correctly terminated with 0xFFFFFFFF");
                ok = false;
            }

            return(ok);
        }
Example #12
0
 public abstract void ExpandToClusters(long numVirtualClusters, NonResidentAttributeRecord extent, bool allocate);
 public NonResidentDataBuffer(INtfsContext context, NonResidentAttributeRecord record)
     : this(context, new CookedDataRuns(record.DataRuns, record), false)
 {
 }
 public CookedDataRuns(IEnumerable<DataRun> rawRuns, NonResidentAttributeRecord attributeExtent)
 {
     _runs = new List<CookedDataRun>();
     Append(rawRuns, attributeExtent);
 }
 public void Append(IEnumerable<DataRun> rawRuns, NonResidentAttributeRecord attributeExtent)
 {
     long vcn = NextVirtualCluster;
     long lcn = 0;
     foreach (var run in rawRuns)
     {
         _runs.Add(new CookedDataRun(run, vcn, lcn, attributeExtent));
         vcn += run.RunLength;
         lcn += run.RunOffset;
     }
 }
 public void Append(DataRun rawRun, NonResidentAttributeRecord attributeExtent)
 {
     CookedDataRun last = Last;
     _runs.Add(new CookedDataRun(rawRun, NextVirtualCluster, last == null ? 0 : last.StartLcn, attributeExtent));
 }
Example #17
0
 public NonResidentDataBuffer(INtfsContext context, NonResidentAttributeRecord record)
     : this(context, new CookedDataRuns(record.DataRuns, record), false)
 {
 }
 public override void ExpandToClusters(long numVirtualClusters, NonResidentAttributeRecord extent, bool allocate)
 {
     _rawStream.ExpandToClusters(CompressionStart(numVirtualClusters), extent, false);
 }
 public override void ExpandToClusters(long numVirtualClusters, NonResidentAttributeRecord extent, bool allocate)
 {
     _rawStream.ExpandToClusters(CompressionStart(numVirtualClusters), extent, false);
 }
Example #20
0
        private bool SplitAttribute(FileRecord record, NonResidentAttributeRecord targetAttr, bool atStart)
        {
            if (targetAttr.DataRuns.Count <= 1)
            {
                return false;
            }

            int splitIndex = 1;
            if (!atStart)
            {
                List<DataRun> runs = targetAttr.DataRuns;

                splitIndex = runs.Count - 1;
                int saved = runs[splitIndex].Size;
                while (splitIndex > 1 && record.Size - saved > record.AllocatedSize)
                {
                    --splitIndex;
                    saved += runs[splitIndex].Size;
                }
            }

            AttributeRecord newAttr = targetAttr.Split(splitIndex);

            // Find a home for the new attribute record
            FileRecord newAttrHome = null;
            foreach (var targetRecord in _records)
            {
                if (!targetRecord.IsMftRecord && _mft.RecordSize - targetRecord.Size >= newAttr.Size)
                {
                    targetRecord.AddAttribute(newAttr);
                    newAttrHome = targetRecord;
                }
            }

            if (newAttrHome == null)
            {
                newAttrHome = _mft.AllocateRecord(_records[0].Flags & (~FileRecordFlags.InUse), record.IsMftRecord);
                newAttrHome.BaseFile = record.BaseFile.IsNull ? record.Reference : record.BaseFile;
                _records.Add(newAttrHome);
                newAttrHome.AddAttribute(newAttr);
            }

            // Add the new attribute record as an extent on the attribute it split from
            bool added = false;
            foreach (var attr in _attributes)
            {
                foreach (var existingRecord in attr.Extents)
                {
                    if (existingRecord.Key.File == record.Reference && existingRecord.Key.AttributeId == targetAttr.AttributeId)
                    {
                        attr.AddExtent(newAttrHome.Reference, newAttr);
                        added = true;
                        break;
                    }
                }

                if (added)
                {
                    break;
                }
            }

            UpdateAttributeList();

            return true;
        }
 public override void ExpandToClusters(long numVirtualClusters, NonResidentAttributeRecord extent, bool allocate)
 {
     _rawStream.ExpandToClusters(Utilities.RoundUp(numVirtualClusters, _attr.CompressionUnitSize), extent, false);
 }
Example #22
0
        private bool SplitAttribute(FileRecord record, NonResidentAttributeRecord targetAttr, bool atStart)
        {
            if (targetAttr.DataRuns.Count <= 1)
            {
                return(false);
            }

            int splitIndex = 1;

            if (!atStart)
            {
                List <DataRun> runs = targetAttr.DataRuns;

                splitIndex = runs.Count - 1;
                int saved = runs[splitIndex].Size;
                while (splitIndex > 1 && record.Size - saved > record.AllocatedSize)
                {
                    --splitIndex;
                    saved += runs[splitIndex].Size;
                }
            }

            AttributeRecord newAttr = targetAttr.Split(splitIndex);

            // Find a home for the new attribute record
            FileRecord newAttrHome = null;

            foreach (var targetRecord in _records)
            {
                if (!targetRecord.IsMftRecord && _mft.RecordSize - targetRecord.Size >= newAttr.Size)
                {
                    targetRecord.AddAttribute(newAttr);
                    newAttrHome = targetRecord;
                }
            }

            if (newAttrHome == null)
            {
                newAttrHome          = _mft.AllocateRecord(_records[0].Flags & (~FileRecordFlags.InUse), record.IsMftRecord);
                newAttrHome.BaseFile = record.BaseFile.IsNull ? record.Reference : record.BaseFile;
                _records.Add(newAttrHome);
                newAttrHome.AddAttribute(newAttr);
            }

            // Add the new attribute record as an extent on the attribute it split from
            bool added = false;

            foreach (var attr in _attributes)
            {
                foreach (var existingRecord in attr.Extents)
                {
                    if (existingRecord.Key.File == record.Reference && existingRecord.Key.AttributeId == targetAttr.AttributeId)
                    {
                        attr.AddExtent(newAttrHome.Reference, newAttr);
                        added = true;
                        break;
                    }
                }

                if (added)
                {
                    break;
                }
            }

            UpdateAttributeList();

            return(true);
        }