def _integrate_attribute_list(parsed, part, image): """Integrate missing attributes in the parsed MTF entry.""" base_record = parsed['record_n'] attrs = parsed['attributes'] attr = attrs['$ATTRIBUTE_LIST'] spc = part.sec_per_clus if 'runlist' in attr: clusters_pos = 0 entries = [] size = attr['real_size'] for entry in attr['runlist']: clusters_pos += entry['offset'] length = min(entry['length'] * spc * sector_size, size) size -= length real_pos = clusters_pos * spc + part.offset dump = sectors(image, real_pos, length, 1) entries += attribute_list_parser(dump) attr['content'] = {'entries': entries} else: entries = attr['content']['entries'] # Divide entries by type types = set(e['type'] for e in entries) entries_by_type = { t: set( e['file_ref'] for e in entries if e['type'] == t and e['file_ref'] is not None ) for t in types } # Remove completely "local" types or empty lists for num in list(entries_by_type): files = entries_by_type[num] if ( len(files) == 0 or (len(files) == 1 and iter(files).next() == base_record) ): del entries_by_type[num] mft_pos = part.mft_pos for num in entries_by_type: # Read contents of child entries for index in entries_by_type[num]: real_pos = mft_pos + index * FILE_size dump = sectors(image, real_pos, FILE_size) child_parsed = parse_file_record(dump) if 'attributes' not in child_parsed: continue # Update the main entry (parsed) if child_parsed['base_record'] == base_record: child_attrs = child_parsed['attributes'] for name in child_attrs: if name in multiple_attributes: try: attrs[name] += child_attrs[name] except KeyError: attrs[name] = child_attrs[name] else: attrs[name] = child_attrs[name]