Example #1
0
        public void Extend(ulong additionalLengthInBytes)
        {
            ulong currentSize = this.Length;

            if (m_attributeRecord is NonResidentAttributeRecord)
            {
                NonResidentAttributeData attributeData = new NonResidentAttributeData(m_volume, m_fileRecord, (NonResidentAttributeRecord)m_attributeRecord);
                attributeData.Extend(additionalLengthInBytes);
            }
            else
            {
                byte[] data              = ((ResidentAttributeRecord)m_attributeRecord).Data;
                ulong  finalDataLength   = (uint)data.Length + additionalLengthInBytes;
                ulong  finalRecordLength = (uint)m_attributeRecord.RecordLength + additionalLengthInBytes;
                if (finalRecordLength >= (ulong)m_volume.AttributeRecordLengthToMakeNonResident &&
                    m_attributeRecord.AttributeType != AttributeType.AttributeList) // We will create an attribute list with the right attribute form in advance.
                {
                    // Convert the attribute to non-resident
                    long clustersToAllocate = (long)Math.Ceiling((double)finalDataLength / m_volume.BytesPerCluster);
                    if (clustersToAllocate > m_volume.NumberOfFreeClusters)
                    {
                        throw new DiskFullException();
                    }
                    NonResidentAttributeRecord attributeRecord = NonResidentAttributeRecord.Create(m_attributeRecord.AttributeType, m_attributeRecord.Name);
                    NonResidentAttributeData   attributeData   = new NonResidentAttributeData(m_volume, null, attributeRecord);
                    attributeData.Extend(finalDataLength);
                    if (data.Length % m_volume.BytesPerCluster > 0)
                    {
                        int fillDataLength = m_volume.BytesPerCluster - (data.Length % m_volume.BytesPerCluster);
                        if ((uint)data.Length + (uint)fillDataLength < finalDataLength)
                        {
                            // Only the last cluster can be partially used, if this is not the last cluster, zero-fill it
                            data = ByteUtils.Concatenate(data, new byte[fillDataLength]);
                        }
                    }
                    attributeData.WriteClusters(0, data);
                    // Note that we overwrite the old attribute only after writing the non-resident data
                    if (m_fileRecord != null)
                    {
                        m_fileRecord.RemoveAttributeRecord(m_attributeRecord.AttributeType, m_attributeRecord.Name);
                        FileRecordHelper.InsertSorted(m_fileRecord.Attributes, attributeRecord);
                    }
                    m_attributeRecord = attributeRecord;
                }
                else
                {
                    int    currentLength = data.Length;
                    byte[] temp          = new byte[currentLength + (int)additionalLengthInBytes];
                    Array.Copy(data, temp, data.Length);
                    ((ResidentAttributeRecord)m_attributeRecord).Data = temp;
                }

                if (m_fileRecord != null)
                {
                    m_volume.UpdateFileRecord(m_fileRecord);
                }
            }
        }
Example #2
0
 public static AttributeRecord Create(AttributeType type, string name, bool isResident)
 {
     if (isResident)
     {
         return(ResidentAttributeRecord.Create(type, name));
     }
     else
     {
         return(NonResidentAttributeRecord.Create(type, name));
     }
 }
        public AttributeRecord CreateAttributeListRecord(bool isResident)
        {
            AttributeRecord attribute;

            if (isResident)
            {
                attribute = AttributeRecord.Create(AttributeType.AttributeList, String.Empty, NextAttributeInstance);
            }
            else
            {
                attribute = NonResidentAttributeRecord.Create(AttributeType.AttributeList, String.Empty, NextAttributeInstance);
            }
            NextAttributeInstance++;
            FileRecordHelper.InsertSorted(m_immediateAttributes, attribute);
            return(attribute);
        }
Example #4
0
        private static NonResidentAttributeRecord AssembleFragments(List <NonResidentAttributeRecord> attributeFragments, ushort nextAttributeInstance)
        {
            // Attribute fragments are written to disk sorted by LowestVCN
            NonResidentAttributeRecord firstFragment = attributeFragments[0];

            if (firstFragment.LowestVCN != 0)
            {
                string message = String.Format("Attribute fragments must be sorted. Attribute type: {0}", firstFragment.AttributeType);
                throw new InvalidDataException(message);
            }

            NonResidentAttributeRecord attribute = NonResidentAttributeRecord.Create(firstFragment.AttributeType, firstFragment.Name, nextAttributeInstance);

            attribute.Flags           = firstFragment.Flags;
            attribute.LowestVCN       = 0;
            attribute.HighestVCN      = -1;
            attribute.CompressionUnit = firstFragment.CompressionUnit;
            attribute.AllocatedLength = firstFragment.AllocatedLength;
            attribute.FileSize        = firstFragment.FileSize;
            attribute.ValidDataLength = firstFragment.ValidDataLength;

            foreach (NonResidentAttributeRecord attributeFragment in attributeFragments)
            {
                if (attributeFragment.LowestVCN == attribute.HighestVCN + 1)
                {
                    // The DataRunSequence of each NonResidentDataRecord fragment starts at absolute LCN,
                    // We need to convert it to relative offset before adding it to the base DataRunSequence
                    long runLength      = attributeFragment.DataRunSequence[0].RunLength;
                    long absoluteOffset = attributeFragment.DataRunSequence[0].RunOffset;
                    long previousLCN    = attribute.DataRunSequence.LastDataRunStartLCN;
                    long relativeOffset = absoluteOffset - previousLCN;

                    int runIndex = attribute.DataRunSequence.Count;
                    attribute.DataRunSequence.AddRange(attributeFragment.DataRunSequence);
                    attribute.DataRunSequence[runIndex] = new DataRun(runLength, relativeOffset);
                    attribute.HighestVCN = attributeFragment.HighestVCN;
                }
                else
                {
                    throw new InvalidDataException("Invalid attribute fragments order");
                }
            }

            return(attribute);
        }