Пример #1
0
        public void WriteSectors(long firstSectorIndex, byte[] data)
        {
            if (m_attributeRecord is NonResidentAttributeRecord)
            {
                NonResidentAttributeData attributeData = new NonResidentAttributeData(m_volume, m_fileRecord, (NonResidentAttributeRecord)m_attributeRecord);
                attributeData.WriteSectors(firstSectorIndex, data);
            }
            else
            {
                byte[] recordData         = ((ResidentAttributeRecord)m_attributeRecord).Data;
                long   totalSectors       = (long)Math.Ceiling((double)recordData.Length / m_volume.BytesPerSector);
                long   highestSectorIndex = Math.Max(totalSectors - 1, 0);
                if (firstSectorIndex < 0 || firstSectorIndex > highestSectorIndex)
                {
                    throw new ArgumentOutOfRangeException("firstSectorIndex is not within the valid range");
                }

                int offset = (int)firstSectorIndex * m_volume.BytesPerSector;
                int bytesToWrite;
                if (offset + data.Length <= recordData.Length)
                {
                    bytesToWrite = data.Length;
                }
                else
                {
                    bytesToWrite = recordData.Length - offset;
                }
                ByteWriter.WriteBytes(recordData, offset, data, bytesToWrite);
                if (m_fileRecord != null)
                {
                    m_volume.UpdateFileRecord(m_fileRecord);
                }
            }
        }
Пример #2
0
        public override void SetAttributes(string path, bool?isHidden, bool?isReadonly, bool?isArchived)
        {
            FileRecord record = m_volume.GetFileRecord(path);

            if (record != null)
            {
                if (isHidden.HasValue)
                {
                    if (isHidden.Value)
                    {
                        record.StandardInformation.FileAttributes |= FileAttributes.Hidden;
                    }
                    else
                    {
                        record.StandardInformation.FileAttributes &= ~FileAttributes.Hidden;
                    }
                }

                if (isReadonly.HasValue)
                {
                    if (isReadonly.Value)
                    {
                        record.StandardInformation.FileAttributes |= FileAttributes.Readonly;
                    }
                    else
                    {
                        record.StandardInformation.FileAttributes &= ~FileAttributes.Readonly;
                    }
                }

                if (isArchived.HasValue)
                {
                    if (isArchived.Value)
                    {
                        record.StandardInformation.FileAttributes |= FileAttributes.Archive;
                    }
                    else
                    {
                        record.StandardInformation.FileAttributes &= ~FileAttributes.Archive;
                    }
                }

                record.StandardInformation.MftModificationTime = DateTime.Now;
                m_volume.UpdateFileRecord(record);
            }
        }
Пример #3
0
        private void UpdateFileNameRecords()
        {
            List <FileNameRecord> fileNameRecords = m_fileRecord.FileNameRecords;

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                fileNameRecord.AllocatedLength = this.Data.AllocatedLength;
                fileNameRecord.FileSize        = this.Data.Length;
            }
            m_volume.UpdateFileRecord(m_fileRecord);

            // Update directory index
            MftSegmentReference parentDirectory       = m_fileRecord.ParentDirectoryReference;
            FileRecord          parentDirectoryRecord = m_volume.GetFileRecord(parentDirectory);
            IndexData           parentDirectoryIndex  = new IndexData(m_volume, parentDirectoryRecord, AttributeType.FileName);

            foreach (FileNameRecord fileNameRecord in fileNameRecords)
            {
                parentDirectoryIndex.UpdateFileNameRecord(fileNameRecord);
            }
        }
Пример #4
0
        public void AddEntry(MftSegmentReference fileReference, byte[] key)
        {
            IndexEntry entry = new IndexEntry();

            entry.FileReference = fileReference;
            entry.Key           = key;
            if (!m_rootRecord.IsParentNode)
            {
                int insertIndex = CollationHelper.FindIndexForSortedInsert(m_rootRecord.IndexEntries, key, m_rootRecord.CollationRule);
                m_rootRecord.IndexEntries.Insert(insertIndex, entry);
                if (m_rootRecord.RecordLength >= m_volume.AttributeRecordLengthToMakeNonResident)
                {
                    if (m_indexAllocationRecord == null)
                    {
                        m_indexAllocationRecord = (IndexAllocationRecord)m_fileRecord.CreateAttributeRecord(AttributeType.IndexAllocation, m_indexName);
                        m_indexAllocationData   = new NonResidentAttributeData(m_volume, m_fileRecord, m_indexAllocationRecord);
                        m_bitmapRecord          = m_fileRecord.CreateAttributeRecord(AttributeType.Bitmap, m_indexName);
                        m_bitmapData            = new BitmapData(m_volume, m_fileRecord, m_bitmapRecord, 0);
                    }
                    SplitRootIndexRecord();
                }
                else
                {
                    m_volume.UpdateFileRecord(m_fileRecord);
                }
            }
            else
            {
                KeyValuePairList <int, IndexRecord> path = FindInsertPath(key);
                IndexRecord leafRecord    = path[path.Count - 1].Value;
                long        leafRecordVBN = leafRecord.RecordVBN;
                int         insertIndex   = CollationHelper.FindIndexForSortedInsert(leafRecord.IndexEntries, key, m_rootRecord.CollationRule);
                leafRecord.IndexEntries.Insert(insertIndex, entry);
                long leafRecordIndex = ConvertToRecordIndex(leafRecordVBN);
                if (leafRecord.DoesFit((int)m_rootRecord.BytesPerIndexRecord))
                {
                    WriteIndexRecord(leafRecordIndex, leafRecord);
                }
                else
                {
                    // Split index record
                    SplitIndexRecord(path);
                }
            }
        }
Пример #5
0
        public override FileSystemEntry CreateFile(string path)
        {
            string streamName = GetStreamName(path);

            path = GetFilePath(path);
            string     parentDirectoryName   = Path.GetDirectoryName(path);
            string     fileName              = Path.GetFileName(path);
            FileRecord parentDirectoryRecord = m_volume.GetFileRecord(parentDirectoryName);
            FileRecord fileRecord            = null;

            if (streamName == String.Empty)
            {
                fileRecord = m_volume.CreateFile(parentDirectoryRecord.BaseSegmentReference, fileName, false);
            }
            else
            {
                try
                {
                    fileRecord = m_volume.GetFileRecord(path);
                }
                catch (FileNotFoundException)
                {
                }

                if (fileRecord == null)
                {
                    fileRecord = m_volume.CreateFile(parentDirectoryRecord.BaseSegmentReference, fileName, false);
                }
                else
                {
                    // 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);
            }
            return(ToFileSystemEntry(path, fileRecord));
        }
        public void WriteSectors(long firstSectorIndex, byte[] data)
        {
            int   sectorCount;
            long  lastSectorIndexToWrite;
            long  lastClusterVCNToWrite;
            int   bytesPerSector    = m_volume.BytesPerSector;
            int   sectorsPerCluster = m_volume.SectorsPerCluster;
            ulong firstBytePosition = (ulong)firstSectorIndex * (uint)bytesPerSector;
            ulong nextBytePosition  = firstBytePosition + (uint)data.Length;

            if (data.Length % bytesPerSector > 0)
            {
                int paddedLength = (int)Math.Ceiling((double)data.Length / bytesPerSector) * bytesPerSector;
                // last sector could be partial, we must zero-fill it before write
                sectorCount            = paddedLength / bytesPerSector;
                lastSectorIndexToWrite = firstSectorIndex + sectorCount - 1;
                lastClusterVCNToWrite  = lastSectorIndexToWrite / sectorsPerCluster;
                if (lastClusterVCNToWrite == HighestVCN)
                {
                    byte[] paddedData = new byte[paddedLength];
                    Array.Copy(data, paddedData, data.Length);
                    data = paddedData;
                }
                else
                {
                    // only the last sector can be partial
                    throw new ArgumentException("Cannot write partial sector");
                }
            }
            else
            {
                sectorCount            = data.Length / bytesPerSector;
                lastSectorIndexToWrite = firstSectorIndex + sectorCount - 1;
                lastClusterVCNToWrite  = lastSectorIndexToWrite / sectorsPerCluster;
            }

            long firstClusterVCN = firstSectorIndex / sectorsPerCluster;

            if (firstClusterVCN < LowestVCN || lastClusterVCNToWrite > HighestVCN)
            {
                string message = String.Format("Cluster VCN {0}-{1} is not within the valid range ({2}-{3})", firstClusterVCN, lastClusterVCNToWrite, LowestVCN, HighestVCN);
                throw new ArgumentOutOfRangeException(message);
            }

            if (firstBytePosition > ValidDataLength)
            {
                // We need to zero-fill all the the bytes up to ValidDataLength
                long firstSectorIndexToFill = (long)(ValidDataLength / (uint)bytesPerSector);
                int  transferSizeInSectors  = Settings.MaximumTransferSizeLBA;
                for (long sectorIndexToFill = firstSectorIndexToFill; sectorIndexToFill < firstSectorIndex; sectorIndexToFill += transferSizeInSectors)
                {
                    int    sectorsToWrite = (int)Math.Min(transferSizeInSectors, firstSectorIndex - firstSectorIndexToFill);
                    byte[] fillData       = new byte[sectorsToWrite * bytesPerSector];
                    if (sectorIndexToFill == firstSectorIndexToFill)
                    {
                        int bytesToRetain = (int)(ValidDataLength % (uint)bytesPerSector);
                        if (bytesToRetain > 0)
                        {
                            byte[] dataToRetain = ReadSectors(firstSectorIndexToFill, 1);
                            Array.Copy(dataToRetain, 0, fillData, 0, bytesToRetain);
                        }
                    }
                    WriteSectors(sectorIndexToFill, fillData);
                }
            }

            KeyValuePairList <long, int> sequence = m_attributeRecord.DataRunSequence.TranslateToLBN(firstSectorIndex, sectorCount, sectorsPerCluster);
            long bytesWritten = 0;

            foreach (KeyValuePair <long, int> run in sequence)
            {
                byte[] sectors = new byte[run.Value * bytesPerSector];
                Array.Copy(data, bytesWritten, sectors, 0, sectors.Length);
                m_volume.WriteSectors(run.Key, sectors, m_contentType);
                bytesWritten += sectors.Length;
            }

            if (nextBytePosition > ValidDataLength)
            {
                m_attributeRecord.ValidDataLength = nextBytePosition;
                if (m_fileRecord != null)
                {
                    m_volume.UpdateFileRecord(m_fileRecord);
                }
            }
        }