Exemple #1
0
 def _get_tot_size(self):
     tot = cur_lvl_size = align_to(self.size,
                                   self.section_header.lvls[-1].block_size)
     for n in reversed(range(IVFCSuperblock.IVFC_MAX_LEVEL - 1)):
         cur_lvl_size = align_to(
             cur_lvl_size // self.section_header.lvls[n].block_size * 0x20,
             self.section_header.lvls[n - 1].block_size)
         tot += cur_lvl_size
     return tot
Exemple #2
0
    def _gen_dir_metadata(self, dir_entry):
        if self.prev_dir is not None:
            self.prev_dir.next = dir_entry
        dir_entry.prev, self.prev_dir = self.prev_dir, dir_entry

        dir_entry.hash = self._calc_path_hash(dir_entry.offsets['Parent'],
                                              dir_entry.name.encode())

        for child in dir_entry.childs:
            self.dir_nb += 1
            if dir_entry.offsets['Child'] == ROMFS_ENTRY_EMPTY:
                dir_entry.offsets['Child'] = self.dir_table_size
            child.offsets['Parent'] = dir_entry.offsets['Self']
            child.offsets['Self'] = self.dir_table_size
            self.dir_table_size += DirEntry.ROMFS_DIRENTRY_LENGTH + align_to(
                len(child.name), 4)
            self._gen_dir_metadata(child)
            if child != dir_entry.childs[-1]:
                child.offsets['Sibling'] = self.dir_table_size
            else:
                child.offsets['Sibling'] = ROMFS_ENTRY_EMPTY
        for file_entry in dir_entry.files:
            self.file_nb += 1
            if self.prev_file is not None:
                self.prev_file.next = file_entry
            file_entry.prev, self.prev_file = self.prev_file, file_entry

            if dir_entry.offsets['File'] == ROMFS_ENTRY_EMPTY:
                dir_entry.offsets['File'] = self.file_table_size
            file_entry.offsets['Parent'] = dir_entry.offsets['Self']
            file_entry.offsets['Self'] = self.file_table_size
            self.file_table_size += FileEntry.ROMFS_FILEENTRY_LENGTH + align_to(
                len(file_entry.name), 4)
            if file_entry != dir_entry.files[-1]:
                file_entry.offsets['Sibling'] = self.file_table_size
            else:
                file_entry.offsets['Sibling'] = ROMFS_ENTRY_EMPTY

            file_entry.hash = self._calc_path_hash(
                file_entry.offsets['Parent'], file_entry.name.encode())

            file_entry.offsets['Size'] = file_entry.size
            file_entry.offsets['Data'] = self.data_size
            self.data_size += align_to(file_entry.size, 0x10)
Exemple #3
0
    def _buffered_repack(self, block_size=0x4000, disp=True):
        lvl_1, lvl_2, lvl_3, lvl_4, lvl_5 = self._gen_hash_tree(
            block_size=block_size, disp=disp)

        if disp:
            print('Writing IVFC levels...')
        yield lvl_1
        yield (align_to(self.lvl_1_size, block_size) - self.lvl_1_size) * b'\0'
        yield lvl_2
        yield (align_to(self.lvl_2_size, block_size) - self.lvl_2_size) * b'\0'
        yield lvl_3
        yield (align_to(self.lvl_3_size, block_size) - self.lvl_3_size) * b'\0'
        yield lvl_4
        yield (align_to(self.lvl_4_size, block_size) - self.lvl_4_size) * b'\0'
        yield lvl_5
        yield (align_to(self.lvl_5_size, block_size) - self.lvl_5_size) * b'\0'

        if disp:
            print('Writing RomFS...')
        written = 0
        for buf in super(HashTreeWrappedRomFS,
                         self)._buffered_repack(disp=disp):
            written += len(buf)
            yield buf
        yield (align_to(written, block_size) - written) * b'\0'
 def read(self, length=None):
     if self.crypto == 'None' or self.crypto == 'BTKR' or self.crypto == 'XTS':
         data = super(NCA3.SectionInNCA3, self).read(length)
         return data
     elif self.crypto == 'CTR':
         aligned_length = align_to(length + self.sector_offset, 0x10)
         dec_data = self.cipher.decrypt(
             super(NCA3.SectionInNCA3, self).read(aligned_length))
         if aligned_length != length:
             try:
                 return dec_data[self.sector_offset:length +
                                 self.sector_offset]
             finally:  # Seek to what the offset should be if not for the crypto
                 self.seek(self.ifo + self.tell() - aligned_length +
                           length)
         else:
             return dec_data[:length]