Exemple #1
0
        /// <summary>
        /// Sets the data blocks. Also updates header for total number of data blocks.
        /// </summary>
        void CalculateDataBlockLayout()
        {
            // TODO: Consolidate of all this duplicate code
            if (properties.Sign)
            {
                // Include the header block in the total count
                hdr.Ndblock = 1;
                var inodesPerBlock = hdr.BlockSize / DinodeS32.SizeOf;
                hdr.DinodeCount                  = inodes.Count;
                hdr.DinodeBlockCount             = CeilDiv(inodes.Count, inodesPerBlock);
                hdr.InodeBlockSig.Blocks         = (uint)hdr.DinodeBlockCount;
                hdr.InodeBlockSig.Size           = hdr.DinodeBlockCount * hdr.BlockSize;
                hdr.InodeBlockSig.SizeCompressed = hdr.DinodeBlockCount * hdr.BlockSize;
                hdr.InodeBlockSig.SetTime(properties.FileTime);
                hdr.InodeBlockSig.Flags = 0;
                for (var i = 0; i < hdr.DinodeBlockCount; i++)
                {
                    hdr.InodeBlockSig.SetDirectBlock(i, 1 + i);
                    final_sigs.Push(new BlockSigInfo(1 + i, 0xB8 + (36 * i)));
                }
                hdr.Ndblock += hdr.DinodeBlockCount;
                super_root_ino.SetDirectBlock(0, (int)(hdr.DinodeBlockCount + 1));
                final_sigs.Push(new BlockSigInfo(super_root_ino.StartBlock, inoNumberToOffset(super_root_ino.Number)));
                hdr.Ndblock += super_root_ino.Blocks;

                // flat path table
                fpt_ino.SetDirectBlock(0, super_root_ino.StartBlock + 1);
                fpt_ino.Size           = fpt.Size;
                fpt_ino.SizeCompressed = fpt.Size;
                fpt_ino.Blocks         = (uint)CeilDiv(fpt.Size, hdr.BlockSize);
                final_sigs.Push(new BlockSigInfo(fpt_ino.StartBlock, inoNumberToOffset(fpt_ino.Number)));

                for (int i = 1; i < fpt_ino.Blocks && i < 12; i++)
                {
                    fpt_ino.SetDirectBlock(i, (int)hdr.Ndblock++);
                    final_sigs.Push(new BlockSigInfo(fpt_ino.StartBlock, inoNumberToOffset(fpt_ino.Number, i)));
                }

                // DATs I've found include an empty block after the FPT
                hdr.Ndblock++;
                // HACK: outer PFS has a block of zeroes that is not encrypted???
                emptyBlock = (int)hdr.Ndblock;
                hdr.Ndblock++;

                var ibStartBlock = hdr.Ndblock;
                hdr.Ndblock += allNodes.Select(s => calculateIndirectBlocks(s.Size)).Sum();

                var sigs_per_block = hdr.BlockSize / 36;
                // Fill in DB/IB pointers
                foreach (var n in allNodes)
                {
                    var blocks = CeilDiv(n.Size, hdr.BlockSize);
                    n.ino.SetDirectBlock(0, (int)hdr.Ndblock);
                    n.ino.Blocks = (uint)blocks;
                    n.ino.Size   = n is FSDir?roundUpSizeToBlock(n.Size) : n.Size;

                    if (n.ino.SizeCompressed == 0)
                    {
                        n.ino.SizeCompressed = n.ino.Size;
                    }

                    for (var i = 0; (blocks - i) > 0 && i < 12; i++)
                    {
                        data_sigs.Push(new BlockSigInfo((int)hdr.Ndblock++, inoNumberToOffset(n.ino.Number, i)));
                    }
                    if (blocks > 12)
                    {
                        // More than 12 blocks -> use 1 indirect block
                        // ib[0]
                        final_sigs.Push(new BlockSigInfo(ibStartBlock, inoNumberToOffset(n.ino.Number, 12)));
                        for (int i = 12, pointerOffset = 0; (blocks - i) > 0 && i < (12 + sigs_per_block); i++, pointerOffset += 36)
                        {
                            // ib[0][i]
                            data_sigs.Push(new BlockSigInfo((int)hdr.Ndblock++, ibStartBlock * hdr.BlockSize + pointerOffset));
                        }
                        ibStartBlock++;
                    }
                    if (blocks > 12 + sigs_per_block)
                    {
                        uint blockSigsDone = 12 + sigs_per_block;
                        // More than 12 + one block of pointers -> use 1 doubly-indirect block + any number of indirect blocks
                        // ib[1] = signature for block of signatures for block of signatures for data blocks
                        final_sigs.Push(new BlockSigInfo(ibStartBlock, inoNumberToOffset(n.ino.Number, 13)));
                        var ib_1_block = ibStartBlock;
                        for (var i = 0; i < sigs_per_block && blockSigsDone < blocks; i++)
                        {
                            // ib[1][i] = signature for block of signatures for data blocks
                            final_sigs.Push(new BlockSigInfo((int)++ibStartBlock, ib_1_block * hdr.BlockSize + i * 36));
                            for (int j = 0; j < sigs_per_block && blockSigsDone < blocks; j++, blockSigsDone++)
                            {
                                // ib[1][i][j] = signature for data block
                                data_sigs.Push(new BlockSigInfo((int)hdr.Ndblock++, ibStartBlock * hdr.BlockSize + (j * 36)));
                            }
                        }
                    }
                }
            }
            else
            {
                // Include the header block in the total count
                hdr.Ndblock = 1;
                var inodesPerBlock = hdr.BlockSize / DinodeD32.SizeOf;
                hdr.DinodeCount                  = inodes.Count;
                hdr.DinodeBlockCount             = CeilDiv(inodes.Count, inodesPerBlock);
                hdr.InodeBlockSig.Blocks         = (uint)hdr.DinodeBlockCount;
                hdr.InodeBlockSig.Size           = hdr.DinodeBlockCount * hdr.BlockSize;
                hdr.InodeBlockSig.SizeCompressed = hdr.DinodeBlockCount * hdr.BlockSize;
                hdr.InodeBlockSig.SetDirectBlock(0, (int)hdr.Ndblock++);
                hdr.InodeBlockSig.SetTime(properties.FileTime);
                for (var i = 1; i < hdr.DinodeBlockCount; i++)
                {
                    if (i < 12)
                    {
                        hdr.InodeBlockSig.SetDirectBlock(i, -1);
                    }
                    hdr.Ndblock++;
                }
                super_root_ino.SetDirectBlock(0, (int)hdr.Ndblock);
                hdr.Ndblock += super_root_ino.Blocks;

                // flat path table
                fpt_ino.SetDirectBlock(0, (int)hdr.Ndblock++);
                fpt_ino.Size           = fpt.Size;
                fpt_ino.SizeCompressed = fpt.Size;
                fpt_ino.Blocks         = (uint)CeilDiv(fpt.Size, hdr.BlockSize);

                for (int i = 1; i < fpt_ino.Blocks && i < 12; i++)
                {
                    fpt_ino.SetDirectBlock(i, (int)hdr.Ndblock++);
                }

                // DATs I've found include an empty block after the FPT if there's no collision resolver
                if (cr_ino == null)
                {
                    hdr.Ndblock++;
                }
                else
                {
                    // collision resolver
                    cr_ino.SetDirectBlock(0, (int)hdr.Ndblock++);
                    cr_ino.Size           = colResolver.Size;
                    cr_ino.SizeCompressed = colResolver.Size;
                    cr_ino.Blocks         = (uint)CeilDiv(colResolver.Size, hdr.BlockSize);

                    for (int i = 1; i < cr_ino.Blocks && i < 12; i++)
                    {
                        cr_ino.SetDirectBlock(i, (int)hdr.Ndblock++);
                    }
                }

                // Calculate length of all dirent blocks
                foreach (var n in allNodes)
                {
                    var blocks = CeilDiv(n.Size, hdr.BlockSize);
                    n.ino.SetDirectBlock(0, (int)hdr.Ndblock);
                    n.ino.Blocks = (uint)blocks;
                    n.ino.Size   = n is FSDir?roundUpSizeToBlock(n.Size) : n.Size;

                    if (n.ino.SizeCompressed == 0)
                    {
                        n.ino.SizeCompressed = n.ino.Size;
                    }
                    for (int i = 1; i < blocks && i < 12; i++)
                    {
                        n.ino.SetDirectBlock(i, -1);
                    }
                    hdr.Ndblock += blocks;
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Sets the data blocks. Also updates header for total number of data blocks.
        /// </summary>
        void CalculateDataBlockLayout()
        {
            long inoNumberToOffset(uint number, int db = 0)
            => hdr.BlockSize + (DinodeS32.SizeOf * number) + 0x64 + (36 * db);

            if (properties.Sign)
            {
                // Include the header block in the total count
                hdr.Ndblock = 1;
                var inodesPerBlock = hdr.BlockSize / DinodeS32.SizeOf;
                hdr.DinodeCount                  = inodes.Count;
                hdr.DinodeBlockCount             = CeilDiv(inodes.Count, inodesPerBlock);
                hdr.InodeBlockSig.Blocks         = (uint)hdr.DinodeBlockCount;
                hdr.InodeBlockSig.Size           = hdr.DinodeBlockCount * hdr.BlockSize;
                hdr.InodeBlockSig.SizeCompressed = hdr.DinodeBlockCount * hdr.BlockSize;
                hdr.InodeBlockSig.SetTime(properties.FileTime);
                hdr.InodeBlockSig.Flags = 0;
                for (var i = 0; i < hdr.DinodeBlockCount; i++)
                {
                    hdr.InodeBlockSig.SetDirectBlock(i, 1 + i);
                    sig_order.Push(new BlockSigInfo(1 + i, 0xB8 + (36 * i)));
                }
                hdr.Ndblock += hdr.DinodeBlockCount;
                super_root_ino.SetDirectBlock(0, (int)(hdr.DinodeBlockCount + 1));
                sig_order.Push(new BlockSigInfo(super_root_ino.StartBlock, inoNumberToOffset(super_root_ino.Number)));
                hdr.Ndblock += super_root_ino.Blocks;

                // flat path table
                fpt_ino.SetDirectBlock(0, super_root_ino.StartBlock + 1);
                fpt_ino.Size           = fpt.Size;
                fpt_ino.SizeCompressed = fpt.Size;
                fpt_ino.Blocks         = (uint)CeilDiv(fpt.Size, hdr.BlockSize);
                sig_order.Push(new BlockSigInfo(fpt_ino.StartBlock, inoNumberToOffset(fpt_ino.Number)));

                for (int i = 1; i < fpt_ino.Blocks && i < 12; i++)
                {
                    fpt_ino.SetDirectBlock(i, (int)hdr.Ndblock++);
                    sig_order.Push(new BlockSigInfo(fpt_ino.StartBlock, inoNumberToOffset(fpt_ino.Number, i)));
                }

                // DATs I've found include an empty block after the FPT
                hdr.Ndblock++;
                // HACK: outer PFS has a block of zeroes that is not encrypted???
                emptyBlock = (int)hdr.Ndblock;
                hdr.Ndblock++;

                var ibStartBlock = hdr.Ndblock;
                hdr.Ndblock += allNodes.Select(s => calculateIndirectBlocks(s.Size)).Sum();

                var sigs_per_block = hdr.BlockSize / 36;
                // Fill in DB/IB pointers
                foreach (var n in allNodes)
                {
                    var blocks = CeilDiv(n.Size, hdr.BlockSize);
                    n.ino.SetDirectBlock(0, (int)hdr.Ndblock);
                    n.ino.Blocks = (uint)blocks;
                    n.ino.Size   = n is FSDir?roundUpSizeToBlock(n.Size) : n.Size;

                    if (n.ino.SizeCompressed == 0)
                    {
                        n.ino.SizeCompressed = n.ino.Size;
                    }

                    for (var i = 0; (blocks - i) > 0 && i < 12; i++)
                    {
                        sig_order.Push(new BlockSigInfo((int)hdr.Ndblock++, inoNumberToOffset(n.ino.Number, i)));
                    }
                    if (blocks > 12)
                    {
                        // More than 12 blocks -> use 1 indirect block
                        sig_order.Push(new BlockSigInfo(ibStartBlock, inoNumberToOffset(n.ino.Number, 12)));
                        for (int i = 12, pointerOffset = 0; (blocks - i) > 0 && i < (12 + sigs_per_block); i++, pointerOffset += 36)
                        {
                            sig_order.Push(new BlockSigInfo((int)hdr.Ndblock++, ibStartBlock * hdr.BlockSize + pointerOffset));
                        }
                        ibStartBlock++;
                    }
                    if (blocks > 12 + sigs_per_block)
                    {
                        // More than 12 + one block of pointers -> use 1 doubly-indirect block + any number of indirect blocks
                        sig_order.Push(new BlockSigInfo(ibStartBlock, inoNumberToOffset(n.ino.Number, 13)));
                        for (var i = 12 + sigs_per_block; (blocks - i) > 0 && i < (12 + sigs_per_block + (sigs_per_block * sigs_per_block)); i += sigs_per_block)
                        {
                            sig_order.Push(new BlockSigInfo(ibStartBlock, inoNumberToOffset(n.ino.Number, 12)));
                            for (int j = 0, pointerOffset = 0; (blocks - i - j) > 0 && j < sigs_per_block; j++, pointerOffset += 36)
                            {
                                sig_order.Push(new BlockSigInfo((int)hdr.Ndblock++, ibStartBlock * hdr.BlockSize + pointerOffset));
                            }
                            ibStartBlock++;
                        }
                    }
                }
            }
            else
            {
                // Include the header block in the total count
                hdr.Ndblock = 1;
                var inodesPerBlock = hdr.BlockSize / DinodeD32.SizeOf;
                hdr.DinodeCount                  = inodes.Count;
                hdr.DinodeBlockCount             = CeilDiv(inodes.Count, inodesPerBlock);
                hdr.InodeBlockSig.Blocks         = (uint)hdr.DinodeBlockCount;
                hdr.InodeBlockSig.Size           = hdr.DinodeBlockCount * hdr.BlockSize;
                hdr.InodeBlockSig.SizeCompressed = hdr.DinodeBlockCount * hdr.BlockSize;
                hdr.InodeBlockSig.SetDirectBlock(0, (int)hdr.Ndblock++);
                hdr.InodeBlockSig.SetTime(properties.FileTime);
                for (var i = 1; i < hdr.DinodeBlockCount; i++)
                {
                    hdr.InodeBlockSig.SetDirectBlock(i, -1);
                    hdr.Ndblock++;
                }
                super_root_ino.SetDirectBlock(0, (int)hdr.Ndblock);
                hdr.Ndblock += super_root_ino.Blocks;

                // flat path table
                fpt_ino.SetDirectBlock(0, (int)hdr.Ndblock++);
                fpt_ino.Size           = fpt.Size;
                fpt_ino.SizeCompressed = fpt.Size;
                fpt_ino.Blocks         = (uint)CeilDiv(fpt.Size, hdr.BlockSize);

                for (int i = 1; i < fpt_ino.Blocks && i < 12; i++)
                {
                    fpt_ino.SetDirectBlock(i, (int)hdr.Ndblock++);
                }
                // DATs I've found include an empty block after the FPT
                hdr.Ndblock++;

                // Calculate length of all dirent blocks
                foreach (var n in allNodes)
                {
                    var blocks = CeilDiv(n.Size, hdr.BlockSize);
                    n.ino.SetDirectBlock(0, (int)hdr.Ndblock);
                    n.ino.Blocks = (uint)blocks;
                    n.ino.Size   = n is FSDir?roundUpSizeToBlock(n.Size) : n.Size;

                    if (n.ino.SizeCompressed == 0)
                    {
                        n.ino.SizeCompressed = n.ino.Size;
                    }
                    for (int i = 1; i < blocks && i < 12; i++)
                    {
                        n.ino.SetDirectBlock(i, -1);
                    }
                    hdr.Ndblock += blocks;
                }
            }
        }