def main(): print "=" * 40 print SCRIPT_NAME print "v%s" % VERSION print "By Robert Walls" print "Copyright 2014" print "=" * 40 parser = get_argparser() args = parser.parse_args() print args.imagefile, args.pagesize, args.oobsize, args.blocksize, args.tag_offset print "Script started: ", datetime.datetime.now() print "File size: ", os.path.getsize(args.imagefile) # read in and order all of the blocks, by reverse order of sequence number sorted_blocks = extract_ordered_blocks( args.imagefile, args.chunksize, args.oobsize, args.blocksize, args.tag_offset ) print "Found %d blocks." % len(sorted_blocks) print "Found %d good blocks." % len( [block for block in sorted_blocks if not (block.is_erased or block.possible_parse_error)] ) print "Found %d erased blocks." % len([block for block in sorted_blocks if block.is_erased]) # This can happen if the phone is turned off while writing. print "Found %d blocks with mismatched sequence numbers" % len( [block for block in sorted_blocks if block.possible_parse_error] ) missing_seq_nums = summarize_deleted_blocks.get_missing_block_numbers(sorted_blocks) objects = extract_objects(sorted_blocks) print "Found %d objects" % len(objects) print "Found %d deleted objects." % len([obj for obj in objects if obj.is_deleted]) print "Found %d objects with a header." % len([obj for obj in objects if 0 in obj.chunkDict]) for obj in objects: if len(obj.versions) == 0: continue oob, chunk = obj.versions[0][0] if oob.num_bytes == 0 and chunk.name == "deleted": obj.is_deleted = True for object in objects: if object.object_id == 692: # We need to look at the each version to see if any holes exist in # the block sequence numbers that might affect the chunks, # i.e., missing blocks that might have contained chunks # of the particular version. holey_versions = [] for version in object.versions: for chunk_id in version: if chunk_id == 0: version_seq_num = version[0][0].block_seq continue oob, chunk = version[chunk_id] if oob.is_most_recent: continue if oob.block_seq == version_seq_num: continue if oob.block_seq > version_seq_num: print "Wait! This chunk was written after the header. Error." break if oob.block_seq < version_seq_num: between = set(range(oob.block_seq + 1, version_seq_num)) & missing_seq_nums if len(between) > 0: # print "Chunk and version header are separated by %d holes." % len(between) holey_versions.append(version) break object.holey_versions = holey_versions # print 'Found %d versions with holes.' % len(holey_versions) for version in holey_versions: header_oob, header_chunk = version[0] if header_oob.is_shrink_header: pass size = 0 for id in version: if id == 0: continue else: size += version[id][0].num_bytes if size != header_oob.num_bytes: # TODO: Is this an indication that a certain version # of a file cannot be recovered due to missing chunks? # How will shrink headers impact this? print "Size mismatch." # estimateOldChunks(objects) # objects_deleted = [object for object in objects if object.isDeleted] # printObjectInfo(objects) # testVersionSplit(objects) # testWriteVersion(objects) # printAllObjectNames(objects) testExtractSpecificFile(objects) return
def main(): parser = YaffsParser.get_argparser() args = parser.parse_args() print args.imagefile, args.chunksize, args.oobsize, args.blocksize, args.tag_offset print "Script started: ", datetime.datetime.now() print 'File size: ', os.path.getsize(args.imagefile) #read in and order all of the blocks, by reverse order of sequence number sorted_blocks = YaffsParser.extract_ordered_blocks(args.imagefile, args.chunksize, args.oobsize, args.blocksize, args.tag_offset) nonerased_blocks = [b for b in sorted_blocks if not b.is_erased] print '%d blocks' % len(sorted_blocks) print 'Sequence number range: %d -- %d' \ % (nonerased_blocks[-1].sequence_num, nonerased_blocks[0].sequence_num) print 'Found %d erased blocks.' % (len(sorted_blocks) - len(nonerased_blocks)) #This can happen if the phone is turned off while writing. print 'Found %d blocks with mismatched sequence numbers' \ % len([block for block in sorted_blocks if block.possible_parse_error]) missing_seq_nums = summarize_deleted_blocks.get_missing_block_numbers(sorted_blocks) objects = YaffsParser.extract_objects(sorted_blocks) print 'Found %d objects' % len(objects) print 'Found %d objects with a header.' % len([obj for obj in objects if 0 in obj.chunkDict]) print 'Found %d deleted objects.' % len([obj for obj in objects if obj.is_deleted]) recent_pairs = [] total_pairs_count = 0 for block in sorted_blocks: recent_pairs.extend([(tag, chunk) for tag, chunk in block.chunk_pairs if tag.is_most_recent]) total_pairs_count += len(block.chunk_pairs) print 'Number of Recent chunks: %d' % len(recent_pairs) print 'Total number of chunks: %d' % total_pairs_count print 'Fraction recent: %0.2f' % (float(len(recent_pairs)) / total_pairs_count) last_time = None first_time = None for block in nonerased_blocks: for tag, chunk in block.chunk_pairs: if tag.isHeaderTag: print block.sequence_num last_time = time.ctime(YaffsHeader(chunk).mtime) break if last_time: break for x in xrange(len(nonerased_blocks)-1, 0, -1): block = nonerased_blocks[x] for y in xrange(len(block.chunk_pairs)-1, 0, -1): tag, chunk = block.chunk_pairs[y] if tag.isHeaderTag: print block.sequence_num first_time = time.ctime(YaffsHeader(chunk).mtime) break if first_time: break print 'Oldest object modification: %s' % first_time print 'Newest object modification: %s' % last_time