示例#1
0
        public override void Write(long pos, byte[] buffer, int offset, int count)
        {
            var record = _attribute.Record;

            if (!CanWrite)
            {
                throw new IOException("Attempt to write to file not opened for write");
            }

            if (record.Flags != AttributeFlags.None)
            {
                throw new NotImplementedException("Writing to compressed / sparse attributes");
            }

            if (count == 0)
            {
                return;
            }


            if (!record.IsNonResident)
            {
                record.GetDataBuffer(_file).Write(pos, buffer, offset, count);
                _file.MarkMftRecordDirty();
            }
            else
            {
                NonResidentAttributeRecord lastExtent = (NonResidentAttributeRecord)_attribute.LastExtent;
                IBuffer lastExtentBuffer = lastExtent.GetDataBuffer(_file);

                long bytesPerCluster = _file.Context.BiosParameterBlock.BytesPerCluster;

                if (pos + count > record.AllocatedLength)
                {
                    _file.MarkMftRecordDirty();

                    long clusterLength = Utilities.RoundUp(pos + count, bytesPerCluster);
                    lastExtentBuffer.SetCapacity(clusterLength - (lastExtent.StartVcn * bytesPerCluster));
                    record.AllocatedLength = clusterLength;
                }

                // Write zeros from end of current initialized data to the start of the new write
                if (pos > record.InitializedDataLength + 1)
                {
                    _file.MarkMftRecordDirty();

                    byte[] wipeBuffer = new byte[bytesPerCluster * 4];

                    long wipePos = record.InitializedDataLength;
                    while (wipePos < pos)
                    {
                        long    extentStartPos;
                        IBuffer extentBuffer = GetExtentBuffer(wipePos, out extentStartPos);

                        long writePos   = wipePos - extentStartPos;
                        int  numToWrite = (int)Math.Min(Math.Min(extentBuffer.Capacity - writePos, pos - wipePos), wipeBuffer.Length);
                        extentBuffer.Write(writePos, wipeBuffer, 0, numToWrite);
                        wipePos += numToWrite;
                    }
                }

                long focusPos     = pos;
                int  bytesWritten = 0;
                while (bytesWritten < count)
                {
                    long    extentStartPos;
                    IBuffer extentBuffer = GetExtentBuffer(focusPos, out extentStartPos);

                    long writePos   = focusPos - extentStartPos;
                    int  numToWrite = (int)Math.Min(extentBuffer.Capacity - writePos, count - bytesWritten);
                    extentBuffer.Write(writePos, buffer, offset + bytesWritten, numToWrite);
                    focusPos     += numToWrite;
                    bytesWritten += numToWrite;
                }

                if (pos + count > record.InitializedDataLength)
                {
                    _file.MarkMftRecordDirty();

                    record.InitializedDataLength = pos + count;
                }

                if (pos + count > record.DataLength)
                {
                    _file.MarkMftRecordDirty();

                    record.DataLength = pos + count;
                }
            }
        }