Exemple #1
0
        public static STF_VOLUME_DESCRIPTOR Default()
        {
            var descriptor = new STF_VOLUME_DESCRIPTOR();

            descriptor.DescriptorLength                   = 0x24;
            descriptor.Version                            = 0;
            descriptor.Flags                              = 0;
            descriptor.DirectoryAllocationBlocks          = 1;
            descriptor.DirectoryFirstBlockNumber0         =
                descriptor.DirectoryFirstBlockNumber1     =
                    descriptor.DirectoryFirstBlockNumber2 = 0;
            descriptor.RootHash                           = new byte[0x14];
            descriptor.NumberOfTotalBlocks                = 1;
            descriptor.NumberOfFreeBlocks                 = 0;
            return(descriptor);
        }
        public void StfsInit()
        {
            if (Position == 0)
            {
                Position = Stream.Position;
            }

            // Read in XContent/PEC header if the volume descriptor isn't already set:
            if (StfsVolumeDescriptor.DescriptorLength != 0x24)
            {
                Stream.Position = Position;
                PecHeader       = Stream.ReadStruct <PEC_HEADER>();
                PecHeader.EndianSwap();
                if (PecHeader.ConsoleSignature.IsStructureValid)
                {
                    IsXContent           = false;
                    IsConsoleSigned      = true;
                    ConsoleSignature     = PecHeader.ConsoleSignature;
                    StfsVolumeDescriptor = PecHeader.StfsVolumeDescriptor;
                }
                else
                {
                    IsXContent = true;
                    Stream.Seek(0, SeekOrigin.Begin);

                    Header = Stream.ReadStruct <XCONTENT_HEADER>();
                    Header.EndianSwap();

                    if (Header.SignatureType != XCONTENT_HEADER.kSignatureTypeConBE &&
                        Header.SignatureType != XCONTENT_HEADER.kSignatureTypeLiveBE &&
                        Header.SignatureType != XCONTENT_HEADER.kSignatureTypePirsBE)
                    {
                        throw new FileSystemParseException("File has invalid header magic");
                    }

                    if (Header.SizeOfHeaders == 0)
                    {
                        throw new FileSystemParseException("Package doesn't contain STFS filesystem");
                    }

                    if (Header.SignatureType == XCONTENT_HEADER.kSignatureTypeConBE)
                    {
                        IsConsoleSigned  = true;
                        ConsoleSignature = Header.ConsoleSignature;
                    }

                    byte[] headerRaw = new byte[0x118];
                    Stream.Position = 0x22C;
                    Stream.Read(headerRaw, 0, 0x118);
                    headerSha1 = Sha1.ComputeHash(headerRaw);

                    var metadataEnd = (int)(Utility.RoundToPages(Header.SizeOfHeaders, kSectorSize) * kSectorSize);

                    byte[] metadataRaw = new byte[metadataEnd - 0x344];
                    Stream.Position = 0x344;
                    Stream.Read(metadataRaw, 0, metadataEnd - 0x344);

                    contentIdValid = Sha1.ComputeHash(metadataRaw).BytesMatch(Header.ContentId);

                    Stream.Position = 0x344;
                    Metadata        = Stream.ReadStruct <XCONTENT_METADATA>();
                    Metadata.EndianSwap();

                    if (Header.SizeOfHeaders > 0x971A)
                    {
                        Stream.Position   = 0x971A;
                        InstallerMetadata = Stream.ReadStruct <XCONTENT_METADATA_INSTALLER>();
                        InstallerMetadata.EndianSwap();
                    }

                    if (Metadata.VolumeType != 0)
                    {
                        throw new FileSystemParseException("Package contains unsupported SVOD filesystem");
                    }

                    StfsVolumeDescriptor = Metadata.StfsVolumeDescriptor;
                }

                if (StfsVolumeDescriptor.DescriptorLength != 0x24)
                {
                    throw new FileSystemParseException("File has invalid descriptor length");
                }
            }
            StfsInitValues();

            // Read in our directory entries...

            int directoryBlock = StfsVolumeDescriptor.DirectoryFirstBlockNumber;
            var entries        = new List <FileEntry>();

            for (int i = 0; i < StfsVolumeDescriptor.DirectoryAllocationBlocks; i++)
            {
                if (directoryBlock == 0xFFFFFF)
                {
                    Console.WriteLine("Premature directory exit 1!!!");
                    break;
                }

                var directoryOffset = StfsDataBlockToOffset(directoryBlock);

                Stream.Position = directoryOffset;

                bool noMoreEntries = false;
                for (int ent = 0; ent < (0x1000 / 0x40); ent++)
                {
                    var entry = new FileEntry(this);
                    if (!entry.Read(Stream))
                    {
                        noMoreEntries = true;
                        break;
                    }

                    entry.DirectoryOffset = directoryOffset;

                    if (entry.CreationTime < CreationTime)
                    {
                        CreationTime = entry.CreationTime;
                    }

                    if (!entry.IsDirectory)
                    {
                        BytesInUse += entry.DirEntry.FileSize;
                    }

                    entries.Add(entry);
                }


                // Find next directory block...
                var blockHashEntry = StfsGetLevel0HashEntry(directoryBlock);
                directoryBlock = blockHashEntry.Level0NextBlock;

                if (noMoreEntries)
                {
                    if (i + 1 < StfsVolumeDescriptor.DirectoryAllocationBlocks)
                    {
                        Console.WriteLine("Premature directory exit 2!!!");
                    }
                    break;
                }
            }

            // Create metadata.ini/metadata_thumbnail/etc..
            MetadataString = InitMetadataFiles();

            // Connect entries up with their parents/children
            var rootEntries = new List <FileEntry>();

            for (int i = 0; i < entries.Count; i++)
            {
                var ent = entries[i];
                if (ent.DirEntry.DirectoryIndex == -1)
                {
                    rootEntries.Add(ent);
                }

                if (!ent.IsDirectory)
                {
                    continue;
                }

                var children = new List <FileEntry>();
                foreach (var ent2 in entries)
                {
                    if (ent2.DirEntry.DirectoryIndex == i)
                    {
                        children.Add(ent2);
                        ent2.Parent = ent;
                    }
                }

                children.Sort((x, y) => x.Name.CompareTo(y.Name));
                ent.Children = children;
            }

            // Make sure to sort so that ReadDirectoryEntry doesn't make windows loop forever...
            rootEntries.Sort((x, y) => x.Name.CompareTo(y.Name));

            Children = entries.ToArray();
        }