<s> """<STR_LIT>""" <EOL> import struct <EOL> from constants import ContentTypes , STFSHashInfo <EOL> import hashlib <EOL> from cStringIO import StringIO <EOL> class BlockHashRecord ( object ) : <EOL> """<STR_LIT>""" <EOL> def __eq__ ( self , other ) : <EOL> if other . hash == self . hash : <EOL> return True <EOL> else : <EOL> return False <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . blocknum , "<STR_LIT:U+0020>" . join ( [ hex ( ord ( c ) ) for c in self . hash ] ) , self . nextblock ) <EOL> def __init__ ( self , blocknum , data , table = <NUM_LIT:0> , record = <NUM_LIT:0> ) : <EOL> assert len ( data ) == <NUM_LIT> , "<STR_LIT>" <EOL> self . record = record <EOL> self . table = table <EOL> self . blocknum = blocknum <EOL> self . hash = data [ : <NUM_LIT> ] <EOL> self . info = ord ( data [ <NUM_LIT> ] ) <EOL> self . nextblock = struct . unpack ( "<STR_LIT>" , '<STR_LIT:\x00>' + data [ <NUM_LIT> : <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> assert self . info in STFSHashInfo . types , "<STR_LIT>" <EOL> class FileListing ( object ) : <EOL> """<STR_LIT>""" <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % self . filename <EOL> def __init__ ( self , data ) : <EOL> self . filename = data [ : <NUM_LIT> ] . strip ( '<STR_LIT:\x00>' ) <EOL> assert self . filename != '<STR_LIT>' , "<STR_LIT>" <EOL> self . isdirectory = <NUM_LIT> & ord ( data [ <NUM_LIT> ] ) == <NUM_LIT> <EOL> self . numblocks = struct . unpack ( "<STR_LIT>" , "<STR_LIT>" % data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:3> ] ) [ <NUM_LIT:0> ] <EOL> self . firstblock = struct . unpack ( "<STR_LIT>" , "<STR_LIT>" % data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:3> ] ) [ <NUM_LIT:0> ] <EOL> self . pathindex = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . size = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . udate = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . utime = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . adate = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . atime = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> class STFS ( object ) : <EOL> """<STR_LIT>""" <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . magic , self . filename ) <EOL> def __init__ ( self , filename , fd = None ) : <EOL> """<STR_LIT>""" <EOL> self . filename = filename <EOL> if not fd : <EOL> self . fd = open ( filename , '<STR_LIT:r>' ) <EOL> else : <EOL> self . fd = fd <EOL> data = self . fd . read ( <NUM_LIT:4> ) <EOL> assert data in ( "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ) , "<STR_LIT>" <EOL> self . table_spacing = [ ( <NUM_LIT> , <NUM_LIT> , <NUM_LIT> ) , <EOL> ( <NUM_LIT> , <NUM_LIT> , <NUM_LIT> ) ] <EOL> self . magic = data <EOL> self . fd . seek ( <NUM_LIT:0> ) <EOL> self . data = self . fd . read ( <NUM_LIT> ) <EOL> self . parse_header ( self . data ) <EOL> self . parse_filetable ( ) <EOL> def read_filetable ( self , firstblock , numblocks ) : <EOL> """<STR_LIT>""" <EOL> buf = StringIO ( ) <EOL> info = <NUM_LIT> <EOL> block = firstblock <EOL> for i in xrange ( <NUM_LIT:0> , numblocks ) : <EOL> buf . write ( self . read_block ( self . fix_blocknum ( block ) , <NUM_LIT> ) ) <EOL> blockhash = self . get_blockhash ( block ) <EOL> if self . table_size_shift > <NUM_LIT:0> and blockhash . info < <NUM_LIT> : <EOL> blockhash = self . get_blockhash ( block , <NUM_LIT:1> ) <EOL> block = blockhash . nextblock <EOL> info = blockhash . info <EOL> return buf . getvalue ( ) <EOL> def parse_filetable ( self ) : <EOL> """<STR_LIT>""" <EOL> data = StringIO ( ) <EOL> self . filelistings = [ ] <EOL> self . allfiles = { } <EOL> data = self . read_filetable ( self . filetable_blocknumber , self . filetable_blockcount ) <EOL> for x in range ( <NUM_LIT:0> , len ( data ) , <NUM_LIT> ) : <EOL> try : <EOL> self . filelistings . append ( FileListing ( data [ x : x + <NUM_LIT> ] ) ) <EOL> except AssertionError : <EOL> pass <EOL> for fl in self . filelistings : <EOL> path_components = [ fl . filename ] <EOL> a = fl <EOL> while a . pathindex != - <NUM_LIT:1> and a . pathindex < len ( self . filelistings ) : <EOL> try : <EOL> a = self . filelistings [ a . pathindex ] <EOL> path_components . append ( a . filename ) <EOL> except IndexError : <EOL> raise AssertionError ( "<STR_LIT>" % ( self . filename , a . pathindex , len ( self . filelistings ) ) ) <EOL> path_components . append ( '<STR_LIT>' ) <EOL> path_components . reverse ( ) <EOL> self . allfiles [ "<STR_LIT:/>" . join ( path_components ) ] = fl <EOL> def read_file ( self , filelisting , size = - <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> buf = StringIO ( ) <EOL> if size == - <NUM_LIT:1> : <EOL> size = filelisting . size <EOL> block = filelisting . firstblock <EOL> info = <NUM_LIT> <EOL> while size > <NUM_LIT:0> and block > <NUM_LIT:0> and block < self . allocated_count and info >= <NUM_LIT> : <EOL> readlen = min ( <NUM_LIT> , size ) <EOL> buf . write ( self . read_block ( self . fix_blocknum ( block ) , readlen ) ) <EOL> size -= readlen <EOL> blockhash = self . get_blockhash ( block ) <EOL> if self . table_size_shift > <NUM_LIT:0> and blockhash . info < <NUM_LIT> : <EOL> blockhash = self . get_blockhash ( block , <NUM_LIT:1> ) <EOL> block = blockhash . nextblock <EOL> info = blockhash . info <EOL> return buf . getvalue ( ) <EOL> def get_blockhash ( self , blocknum , table_offset = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> record = blocknum % <NUM_LIT> <EOL> tablenum = blocknum // <NUM_LIT> * self . table_spacing [ self . table_size_shift ] [ <NUM_LIT:0> ] <EOL> if blocknum >= <NUM_LIT> : <EOL> tablenum += ( blocknum // <NUM_LIT> + <NUM_LIT:1> ) << self . table_size_shift <EOL> if blocknum >= <NUM_LIT> : <EOL> tablenum += <NUM_LIT:1> << self . table_size_shift <EOL> tablenum += table_offset - ( <NUM_LIT:1> << self . table_size_shift ) <EOL> hashdata = self . read_block ( tablenum ) <EOL> return BlockHashRecord ( blocknum , hashdata [ record * <NUM_LIT> : record * <NUM_LIT> + <NUM_LIT> ] , table = tablenum , record = record ) <EOL> def verify_block ( self , blockhash ) : <EOL> """<STR_LIT>""" <EOL> data = self . read_block ( self . fix_blocknum ( blockhash . blocknum ) ) <EOL> if blockhash . hash == hashlib . sha1 ( data ) . digest ( ) : <EOL> return True <EOL> else : <EOL> return False <EOL> def fix_blocknum ( self , block_num ) : <EOL> """<STR_LIT>""" <EOL> block_adjust = <NUM_LIT:0> <EOL> if block_num >= <NUM_LIT> : <EOL> block_adjust += ( ( block_num // <NUM_LIT> ) ) + <NUM_LIT:1> << self . table_size_shift <EOL> if block_num > <NUM_LIT> : <EOL> block_adjust += ( ( block_num // <NUM_LIT> ) + <NUM_LIT:1> ) << self . table_size_shift <EOL> return block_adjust + block_num <EOL> def read_block ( self , blocknum , length = <NUM_LIT> ) : <EOL> """<STR_LIT>""" <EOL> self . fd . seek ( <NUM_LIT> + blocknum * <NUM_LIT> ) <EOL> return self . fd . read ( length ) <EOL> def parse_header ( self , data ) : <EOL> """<STR_LIT>""" <EOL> assert len ( data ) >= <NUM_LIT> , "<STR_LIT>" <EOL> self . magic = data [ <NUM_LIT:0> : <NUM_LIT:4> ] <EOL> if self . magic == "<STR_LIT>" : <EOL> self . console_id = data [ <NUM_LIT:6> : <NUM_LIT:11> ] <EOL> self . console_part_number = data [ <NUM_LIT> : <NUM_LIT> ] <EOL> self . console_type = ord ( data [ <NUM_LIT> : <NUM_LIT> ] ) <EOL> self . certificate_date = data [ <NUM_LIT> : <NUM_LIT> ] <EOL> self . certificate_blob = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> else : <EOL> self . certificate_blob = data [ <NUM_LIT> : <NUM_LIT> ] <EOL> self . license_entries = data [ <NUM_LIT> : <NUM_LIT> : <NUM_LIT> ] <EOL> self . content_id = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . entry_id = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . content_type = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . metadata_version = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . content_size = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . media_id = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:4> ] ) [ <NUM_LIT:0> ] <EOL> self . version = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:4> ] ) [ <NUM_LIT:0> ] <EOL> self . base_version = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:4> ] ) [ <NUM_LIT:0> ] <EOL> self . title_id = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:4> ] ) [ <NUM_LIT:0> ] <EOL> self . platform = ord ( data [ <NUM_LIT> : <NUM_LIT> ] ) <EOL> self . executable_type = ord ( data [ <NUM_LIT> : <NUM_LIT> ] ) <EOL> self . disc_number = ord ( data [ <NUM_LIT> : <NUM_LIT> ] ) <EOL> self . disc_in_set = ord ( data [ <NUM_LIT> : <NUM_LIT> ] ) <EOL> self . save_game_id = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:4> ] ) [ <NUM_LIT:0> ] <EOL> if self . magic == "<STR_LIT>" : <EOL> pass <EOL> else : <EOL> self . console_id = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:5> ] <EOL> self . profile_id = data [ <NUM_LIT> : <NUM_LIT> ] <EOL> self . volume_descriptor_size = ord ( data [ <NUM_LIT> : <NUM_LIT> ] ) <EOL> self . block_seperation = ord ( data [ <NUM_LIT> ] ) <EOL> self . filetable_blockcount = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> + <NUM_LIT:2> : <NUM_LIT> + <NUM_LIT:4> ] ) [ <NUM_LIT:0> ] <EOL> self . filetable_blocknumber = struct . unpack ( "<STR_LIT>" , "<STR_LIT>" % data [ <NUM_LIT> + <NUM_LIT:4> : <NUM_LIT> + <NUM_LIT:7> ] ) [ <NUM_LIT:0> ] <EOL> self . tophashtable_hash = data [ <NUM_LIT> + <NUM_LIT:7> : <NUM_LIT> + <NUM_LIT:7> + <NUM_LIT> ] <EOL> self . allocated_count = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> + <NUM_LIT> : <NUM_LIT> + <NUM_LIT> + <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . unallocated_count = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> + <NUM_LIT> : <NUM_LIT> + <NUM_LIT> + <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . datafile_count = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] ) [ <NUM_LIT:0> ] <EOL> self . datafile_size = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:8> ] ) [ <NUM_LIT:0> ] <EOL> self . device_id = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . display_name = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . display_name_blob = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . display_description = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . display_description_blob = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . publisher_name = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . title_name = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . transfer_flags = data [ <NUM_LIT> : <NUM_LIT> ] <EOL> self . thumbnail_size = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:4> ] ) [ <NUM_LIT:0> ] <EOL> self . titleimage_size = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:4> ] ) [ <NUM_LIT:0> ] <EOL> self . thumbnail = data [ <NUM_LIT> : <NUM_LIT> + self . thumbnail_size ] <EOL> self . titleimage = data [ <NUM_LIT> : <NUM_LIT> + self . titleimage_size ] <EOL> if self . metadata_version == <NUM_LIT:2> : <EOL> self . series_id = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . season_id = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . season_number = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:2> ] ) [ <NUM_LIT:0> ] <EOL> self . episode_number = struct . unpack ( "<STR_LIT>" , data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT:2> ] ) [ <NUM_LIT:0> ] <EOL> self . additional_display_names = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> self . additional_display_descriptions = data [ <NUM_LIT> : <NUM_LIT> + <NUM_LIT> ] <EOL> if ( ( self . entry_id + <NUM_LIT> ) & <NUM_LIT> ) >> <NUM_LIT> == <NUM_LIT> : <EOL> self . table_size_shift = <NUM_LIT:0> <EOL> else : <EOL> self . table_size_shift = <NUM_LIT:1> <EOL> def extract_all ( argv ) : <EOL> if len ( argv ) < <NUM_LIT:3> : <EOL> print "<STR_LIT>" <EOL> print "<STR_LIT>" <EOL> return <EOL> s = STFS ( argv [ <NUM_LIT:1> ] ) <EOL> for filename in s . allfiles : <EOL> if s . allfiles [ filename ] . isdirectory : <EOL> print "<STR_LIT>" % filename <EOL> dirpath = filename [ <NUM_LIT:1> : ] <EOL> dircomponents = dirpath . split ( '<STR_LIT:/>' ) <EOL> for i in xrange ( len ( dircomponents ) ) : <EOL> try : <EOL> os . mkdir ( "<STR_LIT>" % ( argv [ <NUM_LIT:2> ] , "<STR_LIT:/>" . join ( dircomponents [ : i + <NUM_LIT:1> ] ) ) ) <EOL> except OSError : <EOL> pass <EOL> for filename in s . allfiles : <EOL> if not s . allfiles [ filename ] . isdirectory : <EOL> print "<STR_LIT>" % filename <EOL> try : <EOL> open ( "<STR_LIT>" % ( argv [ <NUM_LIT:2> ] , filename ) , '<STR_LIT:w>' ) . write ( s . read_file ( s . allfiles [ filename ] ) ) <EOL> except Exception as e : <EOL> print e <EOL> print argv [ <NUM_LIT:2> ] , filename <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> import sys <EOL> import os <EOL> extract_all ( sys . argv ) </s>
