private ExtentBlock LoadExtentBlock(ExtentIndex idxEntry)
        {
            uint blockSize = _context.SuperBlock.BlockSize;

            _context.RawStream.Position = idxEntry.LeafPhysicalBlock * blockSize;
            byte[]      buffer   = StreamUtilities.ReadFully(_context.RawStream, (int)blockSize);
            ExtentBlock subBlock = EndianUtilities.ToStruct <ExtentBlock>(buffer, 0);

            return(subBlock);
        }
        public override int Read(long pos, byte[] buffer, int offset, int count)
        {
            if (pos > _inode.FileSize)
            {
                return(0);
            }

            long blockSize = _context.SuperBlock.BlockSize;

            int totalRead           = 0;
            int totalBytesRemaining = (int)Math.Min(count, _inode.FileSize - pos);

            ExtentBlock extents = _inode.Extents;

            while (totalBytesRemaining > 0)
            {
                uint logicalBlock = (uint)((pos + totalRead) / blockSize);
                int  blockOffset  = (int)(pos + totalRead - logicalBlock * blockSize);

                int numRead = 0;

                Extent extent = FindExtent(extents, logicalBlock);
                if (extent == null)
                {
                    throw new IOException("Unable to find extent for block " + logicalBlock);
                }
                if (extent.FirstLogicalBlock > logicalBlock)
                {
                    numRead =
                        (int)
                        Math.Min(totalBytesRemaining,
                                 (extent.FirstLogicalBlock - logicalBlock) * blockSize - blockOffset);
                    Array.Clear(buffer, offset + totalRead, numRead);
                }
                else
                {
                    long physicalBlock = logicalBlock - extent.FirstLogicalBlock + (long)extent.FirstPhysicalBlock;
                    int  toRead        =
                        (int)
                        Math.Min(totalBytesRemaining,
                                 (extent.NumBlocks - (logicalBlock - extent.FirstLogicalBlock)) * blockSize - blockOffset);

                    _context.RawStream.Position = physicalBlock * blockSize + blockOffset;
                    numRead = _context.RawStream.Read(buffer, offset + totalRead, toRead);
                }

                totalBytesRemaining -= numRead;
                totalRead           += numRead;
            }

            return(totalRead);
        }
Example #3
0
        public int ReadFrom(byte[] buffer, int offset)
        {
            Mode             = Utilities.ToUInt16LittleEndian(buffer, offset + 0);
            UserIdLow        = Utilities.ToUInt16LittleEndian(buffer, offset + 2);
            FileSize         = Utilities.ToUInt32LittleEndian(buffer, offset + 4);
            AccessTime       = Utilities.ToUInt32LittleEndian(buffer, offset + 8);
            CreationTime     = Utilities.ToUInt32LittleEndian(buffer, offset + 12);
            ModificationTime = Utilities.ToUInt32LittleEndian(buffer, offset + 16);
            DeletionTime     = Utilities.ToUInt32LittleEndian(buffer, offset + 20);
            GroupIdLow       = Utilities.ToUInt16LittleEndian(buffer, offset + 24);
            LinksCount       = Utilities.ToUInt16LittleEndian(buffer, offset + 26);
            BlocksCount      = Utilities.ToUInt32LittleEndian(buffer, offset + 28);
            Flags            = (InodeFlags)Utilities.ToUInt32LittleEndian(buffer, offset + 32);

            FastSymlink  = null;
            Extents      = null;
            DirectBlocks = null;
            if (FileType == UnixFileType.Link && BlocksCount == 0)
            {
                FastSymlink = new byte[60];
                Array.Copy(buffer, offset + 40, FastSymlink, 0, 60);
            }
            else if ((Flags & InodeFlags.ExtentsUsed) != 0)
            {
                Extents = Utilities.ToStruct <ExtentBlock>(buffer, offset + 40);
            }
            else
            {
                DirectBlocks = new uint[12];
                for (int i = 0; i < 12; ++i)
                {
                    DirectBlocks[i] = Utilities.ToUInt32LittleEndian(buffer, offset + 40 + i * 4);
                }

                IndirectBlock       = Utilities.ToUInt32LittleEndian(buffer, offset + 88);
                DoubleIndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 92);
                TripleIndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 96);
            }

            FileVersion  = Utilities.ToUInt32LittleEndian(buffer, offset + 100);
            FileAcl      = Utilities.ToUInt32LittleEndian(buffer, offset + 104);
            DirAcl       = Utilities.ToUInt32LittleEndian(buffer, offset + 108);
            FragAddress  = Utilities.ToUInt32LittleEndian(buffer, offset + 112);
            Fragment     = buffer[offset + 116];
            FragmentSize = buffer[offset + 117];
            UserIdHigh   = Utilities.ToUInt16LittleEndian(buffer, offset + 120);
            GroupIdHigh  = Utilities.ToUInt16LittleEndian(buffer, offset + 122);

            return(128);
        }
        private Extent FindExtent(ExtentBlock node, uint logicalBlock)
        {
            if (node.Index != null)
            {
                ExtentIndex idxEntry = null;

                if (node.Index.Length == 0)
                {
                    return(null);
                }
                if (node.Index[0].FirstLogicalBlock >= logicalBlock)
                {
                    idxEntry = node.Index[0];
                }
                else
                {
                    for (int i = 0; i < node.Index.Length; ++i)
                    {
                        if (node.Index[i].FirstLogicalBlock > logicalBlock)
                        {
                            idxEntry = node.Index[i - 1];
                            break;
                        }
                    }
                }

                if (idxEntry == null)
                {
                    idxEntry = node.Index[node.Index.Length - 1];
                }

                ExtentBlock subBlock = LoadExtentBlock(idxEntry);
                return(FindExtent(subBlock, logicalBlock));
            }
            if (node.Extents != null)
            {
                Extent entry = null;

                if (node.Extents.Length == 0)
                {
                    return(null);
                }
                if (node.Extents[0].FirstLogicalBlock >= logicalBlock)
                {
                    return(node.Extents[0]);
                }
                for (int i = 0; i < node.Extents.Length; ++i)
                {
                    if (node.Extents[i].FirstLogicalBlock > logicalBlock)
                    {
                        entry = node.Extents[i - 1];
                        break;
                    }
                }

                if (entry == null)
                {
                    entry = node.Extents[node.Extents.Length - 1];
                }

                return(entry);
            }
            return(null);
        }
Example #5
0
        private Extent FindExtent(ExtentBlock node, uint logicalBlock)
        {
            if (node.Index != null)
            {
                ExtentIndex idxEntry = null;

                if (node.Index.Length == 0)
                {
                    return null;
                }
                else if (node.Index[0].FirstLogicalBlock >= logicalBlock)
                {
                    idxEntry = node.Index[0];
                }
                else
                {
                    for (int i = 0; i < node.Index.Length; ++i)
                    {
                        if (node.Index[i].FirstLogicalBlock > logicalBlock)
                        {
                            idxEntry = node.Index[i - 1];
                            break;
                        }
                    }
                }

                if (idxEntry == null)
                {
                    idxEntry = node.Index[node.Index.Length - 1];
                }

                ExtentBlock subBlock = LoadExtentBlock(idxEntry);
                return FindExtent(subBlock, logicalBlock);
            }
            else if (node.Extents != null)
            {
                Extent entry = null;

                if (node.Extents.Length == 0)
                {
                    return null;
                }
                else if (node.Extents[0].FirstLogicalBlock >= logicalBlock)
                {
                    return node.Extents[0];
                }
                else
                {
                    for (int i = 0; i < node.Extents.Length; ++i)
                    {
                        if (node.Extents[i].FirstLogicalBlock > logicalBlock)
                        {
                            entry = node.Extents[i - 1];
                            break;
                        }
                    }
                }

                if (entry == null)
                {
                    entry = node.Extents[node.Extents.Length - 1];
                }

                return entry;
            }
            else
            {
                return null;
            }
        }
Example #6
0
        public int ReadFrom(byte[] buffer, int offset)
        {
            Mode = Utilities.ToUInt16LittleEndian(buffer, offset + 0);
            UserIdLow = Utilities.ToUInt16LittleEndian(buffer, offset + 2);
            FileSize = Utilities.ToUInt32LittleEndian(buffer, offset + 4);
            AccessTime = Utilities.ToUInt32LittleEndian(buffer, offset + 8);
            CreationTime = Utilities.ToUInt32LittleEndian(buffer, offset + 12);
            ModificationTime = Utilities.ToUInt32LittleEndian(buffer, offset + 16);
            DeletionTime = Utilities.ToUInt32LittleEndian(buffer, offset + 20);
            GroupIdLow = Utilities.ToUInt16LittleEndian(buffer, offset + 24);
            LinksCount = Utilities.ToUInt16LittleEndian(buffer, offset + 26);
            BlocksCount = Utilities.ToUInt32LittleEndian(buffer, offset + 28);
            Flags = (InodeFlags)Utilities.ToUInt32LittleEndian(buffer, offset + 32);

            FastSymlink = null;
            Extents = null;
            DirectBlocks = null;
            if (FileType == UnixFileType.Link && BlocksCount == 0)
            {
                FastSymlink = new byte[60];
                Array.Copy(buffer, offset + 40, FastSymlink, 0, 60);
            }
            else if ((Flags & InodeFlags.ExtentsUsed) != 0)
            {
                Extents = Utilities.ToStruct<ExtentBlock>(buffer, offset + 40);
            }
            else
            {
                DirectBlocks = new uint[12];
                for (int i = 0; i < 12; ++i)
                {
                    DirectBlocks[i] = Utilities.ToUInt32LittleEndian(buffer, offset + 40 + (i * 4));
                }

                IndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 88);
                DoubleIndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 92);
                TripleIndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 96);
            }

            FileVersion = Utilities.ToUInt32LittleEndian(buffer, offset + 100);
            FileAcl = Utilities.ToUInt32LittleEndian(buffer, offset + 104);
            DirAcl = Utilities.ToUInt32LittleEndian(buffer, offset + 108);
            FragAddress = Utilities.ToUInt32LittleEndian(buffer, offset + 112);
            Fragment = buffer[offset + 116];
            FragmentSize = buffer[offset + 117];
            UserIdHigh = Utilities.ToUInt16LittleEndian(buffer, offset + 120);
            GroupIdHigh = Utilities.ToUInt16LittleEndian(buffer, offset + 122);

            return 128;
        }