예제 #1
0
        public int ReadFrom(byte[] buffer, int offset)
        {
            Magic = EndianUtilities.ToUInt32LittleEndian(buffer, offset + 0);
            if (Magic != SquashFsMagic)
            {
                return(Size);
            }

            InodesCount             = EndianUtilities.ToUInt32LittleEndian(buffer, offset + 4);
            CreationTime            = ((long)EndianUtilities.ToUInt32LittleEndian(buffer, offset + 8)).FromUnixTimeSeconds().DateTime;
            BlockSize               = EndianUtilities.ToUInt32LittleEndian(buffer, offset + 12);
            FragmentsCount          = EndianUtilities.ToUInt32LittleEndian(buffer, offset + 16);
            Compression             = EndianUtilities.ToUInt16LittleEndian(buffer, offset + 20);
            BlockSizeLog2           = EndianUtilities.ToUInt16LittleEndian(buffer, offset + 22);
            Flags                   = EndianUtilities.ToUInt16LittleEndian(buffer, offset + 24);
            UidGidCount             = EndianUtilities.ToUInt16LittleEndian(buffer, offset + 26);
            MajorVersion            = EndianUtilities.ToUInt16LittleEndian(buffer, offset + 28);
            MinorVersion            = EndianUtilities.ToUInt16LittleEndian(buffer, offset + 30);
            RootInode               = new MetadataRef(EndianUtilities.ToInt64LittleEndian(buffer, offset + 32));
            BytesUsed               = EndianUtilities.ToInt64LittleEndian(buffer, offset + 40);
            UidGidTableStart        = EndianUtilities.ToInt64LittleEndian(buffer, offset + 48);
            ExtendedAttrsTableStart = EndianUtilities.ToInt64LittleEndian(buffer, offset + 56);
            InodeTableStart         = EndianUtilities.ToInt64LittleEndian(buffer, offset + 64);
            DirectoryTableStart     = EndianUtilities.ToInt64LittleEndian(buffer, offset + 72);
            FragmentTableStart      = EndianUtilities.ToInt64LittleEndian(buffer, offset + 80);
            LookupTableStart        = EndianUtilities.ToInt64LittleEndian(buffer, offset + 88);

            return(Size);
        }
예제 #2
0
 public Directory(Context context, Inode inode, MetadataRef inodeRef)
     : base(context, inode, inodeRef)
 {
     _dirInode = inode as IDirectoryInode;
     if (_dirInode == null)
     {
         throw new ArgumentException("Inode is not a directory", nameof(inode));
     }
 }
예제 #3
0
        protected override File ConvertDirEntryToFile(DirectoryEntry dirEntry)
        {
            MetadataRef inodeRef = dirEntry.InodeReference;

            _context.InodeReader.SetPosition(inodeRef);
            Inode inode = Inode.Read(_context.InodeReader);

            if (dirEntry.IsSymlink)
            {
                return(new Symlink(_context, inode, inodeRef));
            }
            if (dirEntry.IsDirectory)
            {
                return(new Directory(_context, inode, inodeRef));
            }
            return(new File(_context, inode, inodeRef));
        }
예제 #4
0
        public FileContentBuffer(Context context, RegularInode inode, MetadataRef inodeRef)
        {
            _context = context;
            _inode = inode;

            context.InodeReader.SetPosition(inodeRef);
            context.InodeReader.Skip(_inode.Size);

            int numBlocks = (int)(_inode.FileSize / _context.SuperBlock.BlockSize);
            if (_inode.FileSize % _context.SuperBlock.BlockSize != 0 && _inode.FragmentKey == InvalidFragmentKey)
            {
                ++numBlocks;
            }

            byte[] lengthData = new byte[numBlocks * 4];
            context.InodeReader.Read(lengthData, 0, lengthData.Length);

            _blockLengths = new int[numBlocks];
            for (int i = 0; i < numBlocks; ++i)
            {
                _blockLengths[i] = Utilities.ToInt32LittleEndian(lengthData, i * 4);
            }
        }
예제 #5
0
        public int ReadFrom(byte[] buffer, int offset)
        {
            Magic = Utilities.ToUInt32LittleEndian(buffer, offset + 0);
            InodesCount = Utilities.ToUInt32LittleEndian(buffer, offset + 4);
            CreationTime = Utilities.DateTimeFromUnix(Utilities.ToUInt32LittleEndian(buffer, offset + 8));
            BlockSize = Utilities.ToUInt32LittleEndian(buffer, offset + 12);
            FragmentsCount = Utilities.ToUInt32LittleEndian(buffer, offset + 16);
            Compression = Utilities.ToUInt16LittleEndian(buffer, offset + 20);
            BlockSizeLog2 = Utilities.ToUInt16LittleEndian(buffer, offset + 22);
            Flags = Utilities.ToUInt16LittleEndian(buffer, offset + 24);
            UidGidCount = Utilities.ToUInt16LittleEndian(buffer, offset + 26);
            MajorVersion = Utilities.ToUInt16LittleEndian(buffer, offset + 28);
            MinorVersion = Utilities.ToUInt16LittleEndian(buffer, offset + 30);
            RootInode = new MetadataRef(Utilities.ToInt64LittleEndian(buffer, offset + 32));
            BytesUsed = Utilities.ToInt64LittleEndian(buffer, offset + 40);
            UidGidTableStart = Utilities.ToInt64LittleEndian(buffer, offset + 48);
            ExtendedAttrsTableStart = Utilities.ToInt64LittleEndian(buffer, offset + 56);
            InodeTableStart = Utilities.ToInt64LittleEndian(buffer, offset + 64);
            DirectoryTableStart = Utilities.ToInt64LittleEndian(buffer, offset + 72);
            FragmentTableStart = Utilities.ToInt64LittleEndian(buffer, offset + 80);
            LookupTableStart = Utilities.ToInt64LittleEndian(buffer, offset + 88);

            return Size;
        }
예제 #6
0
        public FileContentBuffer(Context context, RegularInode inode, MetadataRef inodeRef)
        {
            _context = context;
            _inode   = inode;

            context.InodeReader.SetPosition(inodeRef);
            context.InodeReader.Skip(_inode.Size);

            int numBlocks = (int)(_inode.FileSize / _context.SuperBlock.BlockSize);

            if (_inode.FileSize % _context.SuperBlock.BlockSize != 0 && _inode.FragmentKey == InvalidFragmentKey)
            {
                ++numBlocks;
            }

            byte[] lengthData = new byte[numBlocks * 4];
            context.InodeReader.Read(lengthData, 0, lengthData.Length);

            _blockLengths = new int[numBlocks];
            for (int i = 0; i < numBlocks; ++i)
            {
                _blockLengths[i] = Utilities.ToInt32LittleEndian(lengthData, i * 4);
            }
        }
예제 #7
0
 public void SetPosition(MetadataRef position)
 {
     SetPosition(position.Block, position.Offset);
 }
예제 #8
0
 internal long DistanceFrom(MetadataRef startPos)
 {
     return((_currentBlockNum - startPos.Block) * VfsSquashFileSystemReader.MetadataBufferSize
            + (_currentOffset - startPos.Offset));
 }
예제 #9
0
 public File(Context context, Inode inode, MetadataRef inodeRef)
 {
     Context   = context;
     Inode     = inode;
     _inodeRef = inodeRef;
 }
예제 #10
0
 public Symlink(Context context, Inode inode, MetadataRef inodeRef)
     : base(context, inode, inodeRef)
 {
 }
예제 #11
0
 public void SetPosition(MetadataRef position)
 {
     SetPosition(position.Block, position.Offset);
 }
예제 #12
0
 internal long DistanceFrom(MetadataRef startPos)
 {
     return ((_currentBlockNum - startPos.Block) * VfsSquashFileSystemReader.MetadataBufferSize)
         + (_currentOffset - startPos.Offset);
 }
        private void WriteDirectory(BuilderContext context)
        {
            MetadataRef startPos = context.DirectoryWriter.Position;

            int currentChild = 0;
            int numDirs      = 0;

            while (currentChild < _children.Count)
            {
                long thisBlock  = _children[currentChild].Node.InodeRef.Block;
                int  firstInode = _children[currentChild].Node.InodeNumber;

                int count = 1;
                while (currentChild + count < _children.Count &&
                       _children[currentChild + count].Node.InodeRef.Block == thisBlock &&
                       _children[currentChild + count].Node.InodeNumber - firstInode < 0x7FFF)
                {
                    ++count;
                }

                DirectoryHeader hdr = new DirectoryHeader()
                {
                    Count       = count - 1,
                    InodeNumber = firstInode,
                    StartBlock  = (int)thisBlock
                };

                hdr.WriteTo(context.IoBuffer, 0);
                context.DirectoryWriter.Write(context.IoBuffer, 0, hdr.Size);

                for (int i = 0; i < count; ++i)
                {
                    Entry           child  = _children[currentChild + i];
                    DirectoryRecord record = new DirectoryRecord()
                    {
                        Offset      = (ushort)child.Node.InodeRef.Offset,
                        InodeNumber = (short)(child.Node.InodeNumber - firstInode),
                        Type        = child.Node.Inode.Type,
                        Name        = child.Name
                    };

                    record.WriteTo(context.IoBuffer, 0);
                    context.DirectoryWriter.Write(context.IoBuffer, 0, record.Size);

                    if (child.Node.Inode.Type == InodeType.Directory ||
                        child.Node.Inode.Type == InodeType.ExtendedDirectory)
                    {
                        ++numDirs;
                    }
                }

                currentChild += count;
            }

            long size = context.DirectoryWriter.DistanceFrom(startPos);

            if (size > uint.MaxValue)
            {
                throw new NotImplementedException("Writing large directories");
            }

            NumLinks = numDirs + 2; // +1 for self, +1 for parent

            _inode.StartBlock = (uint)startPos.Block;
            _inode.Offset     = (ushort)startPos.Offset;
            _inode.FileSize   = (uint)size + 3; // For some reason, always +3
        }
예제 #14
0
파일: File.cs 프로젝트: alexcmd/DiscUtils
 public File(Context context, Inode inode, MetadataRef inodeRef)
 {
     _context = context;
     _inode = inode;
     _inodeRef = inodeRef;
 }