Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package ubi_reader for openSUSE:Factory checked in at 2022-01-04 19:37:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ubi_reader (Old) and /work/SRC/openSUSE:Factory/.ubi_reader.new.1896 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ubi_reader" Tue Jan 4 19:37:59 2022 rev:3 rq:943725 version:0.7.1 Changes: -------- --- /work/SRC/openSUSE:Factory/ubi_reader/ubi_reader.changes 2021-04-08 22:13:08.085536490 +0200 +++ /work/SRC/openSUSE:Factory/.ubi_reader.new.1896/ubi_reader.changes 2022-01-04 19:38:24.274001880 +0100 @@ -1,0 +2,6 @@ +Mon Jan 3 22:11:10 UTC 2022 - Martin Hauke <[email protected]> + +- Update to version 0.7.1 + * Bug fixes and minor updates. + +------------------------------------------------------------------- Old: ---- ubi_reader-0.6.3.tar.gz New: ---- ubi_reader-0.7.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ubi_reader.spec ++++++ --- /var/tmp/diff_new_pack.fxcUgx/_old 2022-01-04 19:38:24.734002481 +0100 +++ /var/tmp/diff_new_pack.fxcUgx/_new 2022-01-04 19:38:24.738002487 +0100 @@ -1,8 +1,8 @@ # # spec file for package ubi_reader # -# Copyright (c) 2021 SUSE LLC -# Copyright (c) 2018-2021, Martin Hauke <[email protected]> +# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2018-2022, Martin Hauke <[email protected]> # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ Name: ubi_reader -Version: 0.6.3 +Version: 0.7.1 Release: 0 Summary: Extract files from UBI and UBIFS images License: LGPL-3.0-or-later @@ -62,6 +62,7 @@ %files %license LICENSE %doc README.md +%{_bindir}/ubireader_display_blocks %{_bindir}/ubireader_display_info %{_bindir}/ubireader_extract_files %{_bindir}/ubireader_extract_images ++++++ ubi_reader-0.6.3.tar.gz -> ubi_reader-0.7.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/.github/FUNDING.yml new/ubi_reader-0.7.1-master/.github/FUNDING.yml --- old/ubi_reader-0.6.3-master/.github/FUNDING.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ubi_reader-0.7.1-master/.github/FUNDING.yml 2021-05-22 12:29:19.000000000 +0200 @@ -0,0 +1,2 @@ +github: jrspruitt +patreon: jrspruitt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/README.md new/ubi_reader-0.7.1-master/README.md --- old/ubi_reader-0.6.3-master/README.md 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/README.md 2021-05-22 12:29:19.000000000 +0200 @@ -3,6 +3,17 @@ the contents of UBI and UBIFS images, along with analyzing these images to determine the parameter settings to recreate them using the mtd-utils tools. + +### Known Issues +These are some known issues, that prevent an exact data dump from occuring. + +* This does not replay the journal, so uncommited data will not be retrieved. Data can be in the journal with both clean and unclean shutdowns. + +* Depending on how the NAND was dumped, the data bits may not be error corrected. + +* Socket files will be ignored, you can change ubireader/settings.py to have it create dummy files in their place. + + ## Testing Branch The testing branch includes a tools/ directory, that has scripts to help when trying to extract data from broken images. These also serve as examples of how to use parts of ubi_reader in custom scripts. @@ -10,6 +21,7 @@ This branch will probably remain seperate, as it is meant to be customized to aid in extracting data from problematic images. You can install it with 'python setup.py develop' to make it easier to modify ubi_reader as needed. + ## Dependencies: Python 2.7 or 3. @@ -81,6 +93,15 @@ image, the Super Node, and both Master Nodes are displayed. Using the (-u, --ubifs-info) option, it will get the UBIFS info from inside a UBI file instead. +## Display Block Information: + ubireader_display_blocks [options] "{'block.attr':?, ...}" path/to/file + +Search for and display block information. This can be used for debugging failed image +and file extractions. The blocks are searched for using a double quoted Python Dict of +search paramaters, example. "{'peb_num':[0, 1] + range(100, 102), 'ec_hdr.ec': 1, 'is_valid': True}" +This will find PEBs 0, 1, 100, 101, 102, with an erase count of 1 that is a valid block. +Can use any of the parameters in ubireader.ubi.block.description. + ## Options: Some general option flags are * -l, --log: This prints to screen actions being taken while running. @@ -92,20 +113,5 @@ * -g, --guess-offset: Specify offset to start guessing where UBI data is in file. Useful for NAND dumps with false positives before image. * -w, --warn-only-block-read-errors: Attempts to continue extracting files even with bad block reads. Some data will be missing or corrupted! * -i, --ignore-block-header-errors: Forces unused and error containing blocks to be included and also displayed with log/verbose. +* -f, --u-boot-fix: Assume blocks with image_seq 0 are because of older U-boot implementations and include them. *This may cause issues with multiple UBI image files. * -o, --output-dir path: Specify where files should be written to, instead of ubi_reader/output - -### Known Issues - -* Socket files will be ignored, you can change modules/settings.py to have it create dummy files in their place. - -* For NAND dumps and the like, this will not fix anything ECC would take care of, so some bad data -may be extracted, this can also cause erratic behavior. - -* This does not replay the journal, so uncommited data will not be retrieved. - -* Assumes things are in good condition and where it thinks they should be... - -### TODO - -* Arbitrary block analyzer script. - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/scripts/ubireader_display_blocks new/ubi_reader-0.7.1-master/scripts/ubireader_display_blocks --- old/ubi_reader-0.6.3-master/scripts/ubireader_display_blocks 1970-01-01 01:00:00.000000000 +0100 +++ new/ubi_reader-0.7.1-master/scripts/ubireader_display_blocks 2021-05-22 12:29:19.000000000 +0200 @@ -0,0 +1,190 @@ +#!/usr/bin/env python +############################################################# +# ubi_reader/scripts/ubireader_display_blocks +# (c) 2019 Jason Pruitt ([email protected]) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +############################################################# + +############################################################# +# Search by block parameters and display information about +# matching blocks. +############################################################# + +import os +import sys +import argparse +from ubireader.ubi import ubi_base +from ubireader.ubi_io import ubi_file +from ubireader import settings +from ubireader.ubi.defines import UBI_EC_HDR_MAGIC +from ubireader.ubifs.defines import UBIFS_NODE_MAGIC +from ubireader.utils import guess_filetype, guess_start_offset, guess_leb_size, guess_peb_size + +if __name__=='__main__': + + description = 'Search for specified blocks and display information.' + usage = """ + ubireader_display_blocks "{'block.attr': value,...}" path/to/image + Search for blocks by given parameters and display information about them. + This is block only, no volume or image information is created, which can + be used to debug file and image extraction. + Example: + "{'peb_num':[0, 1] + range(100, 102), 'ec_hdr.ec': 1, 'is_valid': True}" + This matches block.peb_num 0, 1, 100, 101, and 102 + with a block.ec_hdr.ec (erase count) of 1, that are valid PEB blocks. + For a full list of parameters check ubireader.ubi.block.description. + """ + parser = argparse.ArgumentParser(usage=usage, description=description) + + parser.add_argument('-l', '--log', action='store_true', dest='log', + help='Print extraction information to screen.') + + parser.add_argument('-v', '--verbose-log', action='store_true', dest='verbose', + help='Prints nearly everything about anything to screen.') + + parser.add_argument('-p', '--peb-size', type=int, dest='block_size', + help='Specify PEB size. (UBI Only)') + + parser.add_argument('-e', '--leb-size', type=int, dest='block_size', + help='Specify LEB size. (UBIFS Only)') + + parser.add_argument('-s', '--start-offset', type=int, dest='start_offset', + help='Specify offset of UBI/UBIFS data in file. (default: 0)') + + parser.add_argument('-n', '--end-offset', type=int, dest='end_offset', + help='Specify end offset of UBI/UBIFS data in file.') + + parser.add_argument('-g', '--guess-offset', type=int, dest='guess_offset', + help='Specify offset to start guessing where UBI data is in file. (default: 0)') + + parser.add_argument('-w', '--warn-only-block-read-errors', action='store_true', dest='warn_only_block_read_errors', + help='Attempts to continue extracting files even with bad block reads. Some data will be missing or corrupted! (default: False)') + + parser.add_argument('-i', '--ignore-block-header-errors', action='store_true', dest='ignore_block_header_errors', + help='Forces unused and error containing blocks to be included and also displayed with log/verbose. (default: False)') + + parser.add_argument('-f', '--u-boot-fix', action='store_true', dest='uboot_fix', + help='Assume blocks with image_seq 0 are because of older U-boot implementations and include them. (default: False)') + + parser.add_argument('block_search_params', + help=""" + Double quoted Dict of ubi.block.description attributes, which is run through eval(). + Ex. "{\'peb_num\':[0, 1], \'ec_hdr.ec\': 1, \'is_valid\': True}" + """) + + parser.add_argument('filepath', help='File with blocks of interest.') + + if len(sys.argv) == 1: + parser.print_help() + + args = parser.parse_args() + + settings.logging_on = args.log + + settings.logging_on_verbose = args.verbose + + settings.warn_only_block_read_errors = args.warn_only_block_read_errors + + settings.ignore_block_header_errors = args.ignore_block_header_errors + + settings.uboot_fix = args.uboot_fix + + if args.filepath: + path = args.filepath + if not os.path.exists(path): + parser.error("File path doesn't exist.") + else: + parser.error('File path must be provided.') + sys.exit(1) + + if args.start_offset: + start_offset = args.start_offset + elif args.guess_offset: + start_offset = guess_start_offset(path, args.guess_offset) + else: + start_offset = guess_start_offset(path) + + if args.end_offset: + end_offset = args.end_offset + else: + end_offset = None + + filetype = guess_filetype(path, start_offset) + if not filetype: + parser.error('Could not determine file type.') + + if args.block_size: + block_size = args.block_size + else: + if filetype == UBI_EC_HDR_MAGIC: + block_size = guess_peb_size(path) + elif filetype == UBIFS_NODE_MAGIC: + block_size = guess_leb_size(path) + + if not block_size: + parser.error('Block size could not be determined.') + + if args.block_search_params: + try: + search_params = eval(args.block_search_params) + + if not isinstance(search_params, dict): + parser.error('Search Param Error: Params must be a Dict of block PEB object items:value pairs.') + + except NameError as e: + parser.error('Search Param Error: Dict key block attrs must be single quoted.') + + except Exception as e: + parser.error('Search Param Error: %s' % e) + + else: + parser.error('No search parameters given, -b arg is required.') + + + ufile_obj = ubi_file(path, block_size, start_offset, end_offset) + ubi_obj = ubi_base(ufile_obj) + blocks = [] + + for block in ubi_obj.blocks: + match = True + + for key in search_params: + b = ubi_obj.blocks[block] + + for attr in key.split('.'): + if hasattr(b, attr): + b = getattr(b, attr) + + if isinstance(search_params[key], list): + if isinstance(b, list): + for value in b: + if value in search_params[key]: + break + else: + match = False + elif b not in search_params[key]: + match = False + + elif b != search_params[key]: + match = False + break + + if match: + blocks.append(ubi_obj.blocks[block]) + + print('\nBlock matches: %s' % len(blocks)) + + for block in blocks: + print(block.display()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/scripts/ubireader_display_info new/ubi_reader-0.7.1-master/scripts/ubireader_display_info --- old/ubi_reader-0.6.3-master/scripts/ubireader_display_info 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/scripts/ubireader_display_info 2021-05-22 12:29:19.000000000 +0200 @@ -68,6 +68,9 @@ parser.add_argument('-i', '--ignore-block-header-errors', action='store_true', dest='ignore_block_header_errors', help='Forces unused and error containing blocks to be included and also displayed with log/verbose. (default: False)') + parser.add_argument('-f', '--u-boot-fix', action='store_true', dest='uboot_fix', + help='Assume blocks with image_seq 0 are because of older U-boot implementations and include them. (default: False)') + parser.add_argument('filepath', help='File to extract contents of.') if len(sys.argv) == 1: @@ -84,6 +87,8 @@ settings.ignore_block_header_errors = args.ignore_block_header_errors + settings.uboot_fix = args.uboot_fix + if args.filepath: path = args.filepath if not os.path.exists(path): @@ -162,7 +167,10 @@ print(ubifs_obj.display()) print(ubifs_obj.superblock_node.display('\t')) print(ubifs_obj.master_node.display('\t')) - print(ubifs_obj.master_node2.display('\t')) + try: + print(ubifs_obj.master_node2.display('\t')) + except: + print('Master Node Error only one valid node.') elif filetype == UBIFS_NODE_MAGIC: # Create UBIFS object @@ -170,7 +178,10 @@ print(ubifs_obj.display()) print(ubifs_obj.superblock_node.display('\t')) print(ubifs_obj.master_node.display('\t')) - print(ubifs_obj.master_node2.display('\t')) + try: + print(ubifs_obj.master_node2.display('\t')) + except: + print('Master Node Error only one valid node.') else: print('Something went wrong to get here.') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/scripts/ubireader_extract_files new/ubi_reader-0.7.1-master/scripts/ubireader_extract_files --- old/ubi_reader-0.6.3-master/scripts/ubireader_extract_files 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/scripts/ubireader_extract_files 2021-05-22 12:29:19.000000000 +0200 @@ -81,6 +81,9 @@ parser.add_argument('-i', '--ignore-block-header-errors', action='store_true', dest='ignore_block_header_errors', help='Forces unused and error containing blocks to be included and also displayed with log/verbose. (default: False)') + parser.add_argument('-f', '--u-boot-fix', action='store_true', dest='uboot_fix', + help='Assume blocks with image_seq 0 are because of older U-boot implementations and include them. (default: False)') + parser.add_argument('-o', '--output-dir', dest='outpath', help='Specify output directory path.') @@ -100,6 +103,8 @@ settings.ignore_block_header_errors = args.ignore_block_header_errors + settings.uboot_fix = args.uboot_fix + if args.filepath: path = args.filepath if not os.path.exists(path): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/scripts/ubireader_extract_images new/ubi_reader-0.7.1-master/scripts/ubireader_extract_images --- old/ubi_reader-0.6.3-master/scripts/ubireader_extract_images 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/scripts/ubireader_extract_images 2021-05-22 12:29:19.000000000 +0200 @@ -72,6 +72,9 @@ parser.add_argument('-i', '--ignore-block-header-errors', action='store_true', dest='ignore_block_header_errors', help='Forces unused and error containing blocks to be included and also displayed with log/verbose. (default: False)') + parser.add_argument('-f', '--u-boot-fix', action='store_true', dest='uboot_fix', + help='Assume blocks with image_seq 0 are because of older U-boot implementations and include them. (default: False)') + parser.add_argument('-o', '--output-dir', dest='outpath', help='Specify output directory path.') @@ -91,6 +94,8 @@ settings.ignore_block_header_errors = args.ignore_block_header_errors + settings.uboot_fix = args.uboot_fix + if args.filepath: path = args.filepath if not os.path.exists(path): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/scripts/ubireader_list_files new/ubi_reader-0.7.1-master/scripts/ubireader_list_files --- old/ubi_reader-0.6.3-master/scripts/ubireader_list_files 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/scripts/ubireader_list_files 2021-05-22 12:29:19.000000000 +0200 @@ -66,6 +66,9 @@ parser.add_argument('-i', '--ignore-block-header-errors', action='store_true', dest='ignore_block_header_errors', help='Forces unused and error containing blocks to be included and also displayed with log/verbose. (default: False)') + parser.add_argument('-f', '--u-boot-fix', action='store_true', dest='uboot_fix', + help='Assume blocks with image_seq 0 are because of older U-boot implementations and include them. (default: False)') + parser.add_argument('-P', '--path', dest='listpath', help='Path to list.') @@ -91,6 +94,8 @@ settings.ignore_block_header_errors = args.ignore_block_header_errors + settings.uboot_fix = args.uboot_fix + if args.filepath: path = args.filepath if not os.path.exists(path): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/scripts/ubireader_utils_info new/ubi_reader-0.7.1-master/scripts/ubireader_utils_info --- old/ubi_reader-0.6.3-master/scripts/ubireader_utils_info 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/scripts/ubireader_utils_info 2021-05-22 12:29:19.000000000 +0200 @@ -270,6 +270,9 @@ parser.add_argument('-i', '--ignore-block-header-errors', action='store_true', dest='ignore_block_header_errors', help='Forces unused and error containing blocks to be included and also displayed with log/verbose. (default: False)') + parser.add_argument('-f', '--u-boot-fix', action='store_true', dest='uboot_fix', + help='Assume blocks with image_seq 0 are because of older U-boot implementations and include them. (default: False)') + parser.add_argument('-o', '--output-dir', dest='outpath', help='Specify output directory path.') @@ -289,6 +292,8 @@ settings.ignore_block_header_errors = args.ignore_block_header_errors + settings.uboot_fix = args.uboot_fix + if args.filepath: path = args.filepath if not os.path.exists(path): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/setup.py new/ubi_reader-0.7.1-master/setup.py --- old/ubi_reader-0.6.3-master/setup.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/setup.py 2021-05-22 12:29:19.000000000 +0200 @@ -2,7 +2,7 @@ from setuptools import setup, find_packages -version = '0.6.3' +version = '0.7.1' setup( name='ubi_reader', @@ -22,6 +22,7 @@ 'scripts/ubireader_extract_files', 'scripts/ubireader_list_files', 'scripts/ubireader_extract_images', - 'scripts/ubireader_utils_info' + 'scripts/ubireader_utils_info', + 'scripts/ubireader_display_blocks', ], ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/ubireader/debug.py new/ubi_reader-0.7.1-master/ubireader/debug.py --- old/ubi_reader-0.6.3-master/ubireader/debug.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/ubireader/debug.py 2021-05-22 12:29:19.000000000 +0200 @@ -34,7 +34,7 @@ print(displayable_obj.display('\t')) def error(obj, level, message): - if settings.error_action is 'exit': + if settings.error_action == 'exit': print('{} {}: {}'.format(obj.__name__, level, message)) if settings.fatal_traceback: traceback.print_exc() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/ubireader/settings.py new/ubi_reader-0.7.1-master/ubireader/settings.py --- old/ubi_reader-0.6.3-master/ubireader/settings.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/ubireader/settings.py 2021-05-22 12:29:19.000000000 +0200 @@ -30,4 +30,7 @@ logging_on = False # Print debug info on. logging_on_verbose = False # Print verbose debug info on. -use_dummy_socket_file = False # Create regular file place holder. +use_dummy_socket_file = False # Create regular file place holder for sockets. +use_dummy_devices = False # Create regular file place holder for devices. + +uboot_fix = False # Older u-boot sets image_seq to 0 on blocks it's written to. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/ubireader/ubi/block/sort.py new/ubi_reader-0.7.1-master/ubireader/ubi/block/sort.py --- old/ubi_reader-0.6.3-master/ubireader/ubi/block/sort.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/ubireader/ubi/block/sort.py 2021-05-22 12:29:19.000000000 +0200 @@ -16,9 +16,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. ############################################################# +from ubireader import settings def by_image_seq(blocks, image_seq): """Filter blocks to return only those associated with the provided image_seq number. + If uboot_fix is set, associate blocks with an image_seq of 0 also. Argument: List:blocks -- List of block objects to sort. @@ -27,7 +29,11 @@ Returns: List -- List of block indexes matching image_seq number. """ - return list(filter(lambda block: blocks[block].ec_hdr.image_seq == image_seq, blocks)) + if settings.uboot_fix: + return list(filter(lambda block: blocks[block].ec_hdr.image_seq == image_seq or image_seq == 0 or blocks[block].ec_hdr.image_seq == 0, blocks)) + + else: + return list(filter(lambda block: blocks[block].ec_hdr.image_seq == image_seq, blocks)) def by_leb(blocks): """Sort blocks by Logical Erase Block number. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/ubireader/ubi_io.py new/ubi_reader-0.7.1-master/ubireader/ubi_io.py --- old/ubi_reader-0.6.3-master/ubireader/ubi_io.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/ubireader/ubi_io.py 2021-05-22 12:29:19.000000000 +0200 @@ -17,6 +17,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. ############################################################# +from ubireader import settings from ubireader.debug import error, log, verbose_log from ubireader.ubi.block import sort @@ -66,10 +67,14 @@ log(self, 'Start Offset: %s' % (self._start_offset)) if end_offset: + tail = file_size - end_offset self._end_offset = end_offset else: - self._end_offset = file_size + tail = (file_size - start_offset) % block_size + self._end_offset = file_size - tail log(self, 'End Offset: %s' % (self._end_offset)) + if tail > 0: + log(self, 'File Tail Size: %s' % (tail)) self._block_size = block_size log(self, 'Block Size: %s' % block_size) @@ -80,6 +85,13 @@ if ( not end_offset is None ) and ( end_offset > file_size ): error(self, 'Fatal', 'End offset larger than file size.') + remainder = (self._end_offset - start_offset) % block_size + if remainder != 0: + if settings.warn_only_block_read_errors: + error(self, 'Error', 'File read is not block aligned.') + else: + error(self, 'Fatal', 'File read is not block aligned.') + self._fhandle.seek(self._start_offset) self._last_read_addr = self._fhandle.tell() self.is_valid = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/ubireader/ubifs/__init__.py new/ubi_reader-0.7.1-master/ubireader/ubifs/__init__.py --- old/ubi_reader-0.6.3-master/ubireader/ubifs/__init__.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/ubireader/ubifs/__init__.py 2021-05-22 12:29:19.000000000 +0200 @@ -49,7 +49,7 @@ if sb_chdr.node_type == UBIFS_SB_NODE: self.file.seek(UBIFS_COMMON_HDR_SZ) buf = self.file.read(UBIFS_SB_NODE_SZ) - self._sb_node = nodes.sb_node(buf) + self._sb_node = nodes.sb_node(buf, self.file.last_read_addr()) self._min_io_size = self._sb_node.min_io_size self._leb_size = self._sb_node.leb_size log(self , '%s file addr: %s' % (self._sb_node, self.file.last_read_addr())) @@ -71,16 +71,21 @@ if mst_chdr.node_type == UBIFS_MST_NODE: self.file.seek(mst_offset + UBIFS_COMMON_HDR_SZ) buf = self.file.read(UBIFS_MST_NODE_SZ) - self._mst_nodes[i] = nodes.mst_node(buf) + self._mst_nodes[i] = nodes.mst_node(buf, self.file.last_read_addr()) log(self , '%s%s file addr: %s' % (self._mst_nodes[i], i, self.file.last_read_addr())) verbose_display(self._mst_nodes[i]) else: raise Exception('Wrong node type.') except Exception as e: - error(self, 'Fatal', 'Master block %s error: %s' % (i, e)) + error(self, 'Warn', 'Master block %s error: %s' % (i, e)) - if not self._mst_nodes[0] or not self._mst_nodes[1]: - error(self, 'Fatal', 'Less than 2 Master blocks found.') + if self._mst_nodes[0] is None and self._mst_nodes[1] is None: + error(self, 'Fatal', 'No valid Master Node found.') + + elif self._mst_nodes[0] is None and self._mst_nodes[1] is not None: + self._mst_nodes[0] = self._mst_nodes[1] + self._mst_nodes[1] = None + log(self , 'Swapping Master Nodes due to bad first node.') def _get_file(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/ubireader/ubifs/defines.py new/ubi_reader-0.7.1-master/ubireader/ubifs/defines.py --- old/ubi_reader-0.6.3-master/ubireader/ubifs/defines.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/ubireader/ubifs/defines.py 2021-05-22 12:29:19.000000000 +0200 @@ -156,31 +156,38 @@ UBIFS_FL_MASK = 0x0000001F # Compression alogrithms. -UBIFS_COMPR_NONE = 0 # No compression -UBIFS_COMPR_LZO = 1 # LZO compression -UBIFS_COMPR_ZLIB = 2 # ZLIB compression -UBIFS_COMPR_TYPES_CNT = 3 # Count of supported compression types -PRINT_UBIFS_COMPR = ['none','lzo','zlib'] +UBIFS_COMPR_NONE = 0 # No compression +UBIFS_COMPR_LZO = 1 # LZO compression +UBIFS_COMPR_ZLIB = 2 # ZLIB compression +UBIFS_COMPR_ZSTD = 3 # ZSTD compression +UBIFS_COMPR_TYPES_CNT = 4 # Count of supported compression types +PRINT_UBIFS_COMPR = ['none','lzo','zlib', 'zstd'] # UBIFS node types -UBIFS_INO_NODE = 0 # Inode node -UBIFS_DATA_NODE = 1 # Data node -UBIFS_DENT_NODE = 2 # Directory entry node -UBIFS_XENT_NODE = 3 # Extended attribute node -UBIFS_TRUN_NODE = 4 # Truncation node -UBIFS_PAD_NODE = 5 # Padding node -UBIFS_SB_NODE = 6 # Superblock node -UBIFS_MST_NODE = 7 # Master node -UBIFS_REF_NODE = 8 # LEB reference node -UBIFS_IDX_NODE = 9 # Index node -UBIFS_CS_NODE = 10 # Commit start node -UBIFS_ORPH_NODE = 11 # Orphan node -UBIFS_NODE_TYPES_CNT = 12 # Count of supported node types +UBIFS_INO_NODE = 0 # Inode node +UBIFS_DATA_NODE = 1 # Data node +UBIFS_DENT_NODE = 2 # Directory entry node +UBIFS_XENT_NODE = 3 # Extended attribute node +UBIFS_TRUN_NODE = 4 # Truncation node +UBIFS_PAD_NODE = 5 # Padding node +UBIFS_SB_NODE = 6 # Superblock node +UBIFS_MST_NODE = 7 # Master node +UBIFS_REF_NODE = 8 # LEB reference node +UBIFS_IDX_NODE = 9 # Index node +UBIFS_CS_NODE = 10 # Commit start node +UBIFS_ORPH_NODE = 11 # Orphan node +UBIFS_AUTH_NODE = 12 # Authentication node +UBIFS_SIG_NODE = 13 # Signature node +UBIFS_NODE_TYPES_CNT = 14 # Count of supported node types # Master node flags -UBIFS_MST_DIRTY = 1 # Rebooted uncleanly -UBIFS_MST_NO_ORPHS = 2 # No orphans present -UBIFS_MST_RCVRY = 4 # Written by recovery +UBIFS_MST_DIRTY = 1 # Rebooted uncleanly +UBIFS_MST_NO_ORPHS = 2 # No orphans present +UBIFS_MST_RCVRY = 4 # Written by recovery +PRINT_UBIFS_MST = [[UBIFS_MST_DIRTY, 'Dirty'], + [UBIFS_MST_NO_ORPHS, 'No orphans'], + [UBIFS_MST_RCVRY, 'Recovery write'], + ] # Node group type UBIFS_NO_NODE_GROUP = 0 # This node is not part of a group @@ -188,21 +195,30 @@ UBIFS_LAST_OF_NODE_GROUP = 2 # This node is the last in a group # Superblock flags -UBIFS_FLG_BIGLPT = 2 # if 'big' LPT model is used if set. -UBIFS_FLG_SPACE_FIXUP = 4 # first-mount 'fixup' of free space within - +UBIFS_FLG_BIGLPT = 2 # If 'big' LPT model is used if set. +UBIFS_FLG_SPACE_FIXUP = 4 # First-mount 'fixup' of free space within. +UBIFS_FLG_DOUBLE_HASH = 8 # Store 32bit cookie for 64bit support. +UBIFS_FLG_ENCRYPTION = 16 # If filesystem contains encrypted files. +UBIFS_FLG_AUTHENTICATION = 32 # If contains hashes for authentication. +PRINT_UBIFS_FLGS = [[UBIFS_FLG_BIGLPT, 'Big LPT'], + [UBIFS_FLG_SPACE_FIXUP, 'Space fixup'], + [UBIFS_FLG_DOUBLE_HASH, 'Double hash'], + [UBIFS_FLG_ENCRYPTION, 'Encryption'], + [UBIFS_FLG_AUTHENTICATION,'Authentication'], + ] # Struct defines # Common header node UBIFS_COMMON_HDR_FORMAT = '<IIQIBB2s' -UBIFS_COMMON_HDR_FIELDS = ['magic', # UBIFS node magic number. - 'crc', # CRC32 checksum of header. - 'sqnum', # Sequence number. - 'len', # Full node length. - 'node_type', # Node type. - 'group_type',# Node group type. - 'padding'] # Reserved for future, zeros. +UBIFS_COMMON_HDR_FIELDS = ['magic', # UBIFS node magic number. + 'crc', # CRC32 checksum of header. + 'sqnum', # Sequence number. + 'len', # Full node length. + 'node_type', # Node type. + 'group_type', # Node group type. + 'padding', # Reserved for future, zeros. + ] UBIFS_COMMON_HDR_SZ = struct.calcsize(UBIFS_COMMON_HDR_FORMAT) # LEBs needed. # Key offset in key nodes @@ -212,12 +228,13 @@ # Device node descriptor UBIFS_DEV_DESC_FORMAT = '<IQ' UBIFS_DEV_DESC_FIELDS = ['new', # New type device descriptor. - 'huge'] # huge type device descriptor. + 'huge', # huge type device descriptor. + ] UBIFS_DEV_DESC_SZ = struct.calcsize(UBIFS_DEV_DESC_FORMAT) # Inode node UBIFS_INO_NODE_FORMAT = '<%ssQQQQQIIIIIIIIIII4sIH26s' % (UBIFS_MAX_KEY_LEN) -UBIFS_INO_NODE_FIELDS = ['key', # Node key +UBIFS_INO_NODE_FIELDS = ['key', # Node key. 'creat_sqnum', # Sequence number at time of creation. 'size', # Inode size in bytes (uncompressed). 'atime_sec', # Access time in seconds. @@ -232,46 +249,52 @@ 'mode', # Access flags. 'flags', # Per-inode flags. 'data_len', # Inode data length. - 'xattr_cnt', # Count of extended attr this inode has + 'xattr_cnt', # Count of extended attr this inode has. 'xattr_size', # Summarized size of all extended # attributes in bytes. 'padding1', # Reserved for future, zeros. - 'xattr_names', # Sum of lengths of all extended. + 'xattr_names', # Sum of lengths of all extended # attribute names belonging to this # inode. 'compr_type', # Compression type used for this inode. - 'padding2'] # Reserved for future, zeros. - # 'data' No size + 'padding2', # Reserved for future, zeros. + ] + # 'data', no size. UBIFS_INO_NODE_SZ = struct.calcsize(UBIFS_INO_NODE_FORMAT) # Directory entry node -UBIFS_DENT_NODE_FORMAT = '<%ssQBBH4s' % (UBIFS_MAX_KEY_LEN) -UBIFS_DENT_NODE_FIELDS = ['key', # Node key. - 'inum', # Target inode number. - 'padding1',# Reserved for future, zeros. - 'type', # Type of target inode. - 'nlen', # Name length. - 'padding2']# Reserved for future, zeros. - # 'Name' No size +UBIFS_DENT_NODE_FORMAT = '<%ssQBBHI' % (UBIFS_MAX_KEY_LEN) +UBIFS_DENT_NODE_FIELDS = ['key', # Node key. + 'inum', # Target inode number. + 'padding1', # Reserved for future, zeros. + 'type', # Type of target inode. + 'nlen', # Name length. + 'cookie', # 32bit random number, used to + # construct a 64bit identifier. + ] + # 'name', no size. UBIFS_DENT_NODE_SZ = struct.calcsize(UBIFS_DENT_NODE_FORMAT) # Data node -UBIFS_DATA_NODE_FORMAT = '<%ssIH2s' % (UBIFS_MAX_KEY_LEN) -UBIFS_DATA_NODE_FIELDS = ['key', # Node key. - 'size', # Uncompressed data size. - 'compr_type', # Compression type UBIFS_COMPR_* - 'padding'] # Reserved for future, zeros. - # 'data' No size +UBIFS_DATA_NODE_FORMAT = '<%ssIHH' % (UBIFS_MAX_KEY_LEN) +UBIFS_DATA_NODE_FIELDS = ['key', # Node key. + 'size', # Uncompressed data size. + 'compr_type', # Compression type UBIFS_COMPR_*. + 'compr_size', # Compressed data size in bytes + # only valid when data is encrypted. + ] + # 'data', no size. UBIFS_DATA_NODE_SZ = struct.calcsize(UBIFS_DATA_NODE_FORMAT) # Truncation node UBIFS_TRUN_NODE_FORMAT = '<I12sQQ' -UBIFS_TRUN_NODE_FIELDS = ['inum', # Truncated inode number. - 'padding', # Reserved for future, zeros. - 'old_size', # size before truncation. - 'new_size'] # Size after truncation. +UBIFS_TRUN_NODE_FIELDS = ['inum', # Truncated inode number. + 'padding', # Reserved for future, zeros. + 'old_size', # size before truncation. + 'new_size', # Size after truncation. + ] UBIFS_TRUN_NODE_SZ = struct.calcsize(UBIFS_TRUN_NODE_FORMAT) # Padding node @@ -279,8 +302,16 @@ UBIFS_PAD_NODE_FIELDS = ['pad_len'] # Number of bytes after this inode unused. UBIFS_PAD_NODE_SZ = struct.calcsize(UBIFS_PAD_NODE_FORMAT) + +# The maxmimum size of a hash, enough for sha512 +UBIFS_MAX_HASH_LEN = 64 + +# The maxmimum size of a hmac, enough for hmac(sha512) +UBIFS_MAX_HMAC_LEN = 64 + + # Superblock node -UBIFS_SB_NODE_FORMAT = '<2sBBIIIIIQIIIIIIIH2sIIQI16sI3968s' +UBIFS_SB_NODE_FORMAT = '<2sBBIIIIIQIIIIIIIH2sIIQI16sI%ss%ssH%ss3774s' % (UBIFS_MAX_HMAC_LEN, UBIFS_MAX_HMAC_LEN, UBIFS_MAX_HASH_LEN) UBIFS_SB_NODE_FIELDS = ['padding', # Reserved for future, zeros. 'key_hash', # Type of hash func used in keys. 'key_fmt', # Format of the key. @@ -295,7 +326,7 @@ # table. 'orph_lebs', # Number of LEBS used for # recording orphans. - 'jhead_cnt', # Count of journal heads + 'jhead_cnt', # Count of journal heads. 'fanout', # Tree fanout, max number of links # per indexing node. 'lsave_cnt', # Number of LEB numbers in LPT's @@ -303,72 +334,99 @@ 'fmt_version', # UBIFS on-flash format version. 'default_compr', # Default compression used. 'padding1', # Reserved for future, zeros. - 'rp_uid', # Reserve pool UID - 'rp_gid', # Reserve pool GID - 'rp_size', # Reserve pool size in bytes + 'rp_uid', # Reserve pool UID. + 'rp_gid', # Reserve pool GID. + 'rp_size', # Reserve pool size in bytes. 'time_gran', # Time granularity in nanoseconds. 'uuid', # UUID generated when the FS image # was created. 'ro_compat_version',# UBIFS R/O Compatibility version. - 'padding2'] #Reserved for future, zeros + 'hmac', # HAMC to authenticate the superblock node. + 'hmac_wkm', # HMAC of a well known message (the string "UBIFS"). + # as a convenience to the user to chek if the correct + # key is past. + 'hash_algo', # The has algo used for this feilseystem. + # (one of enum hash_algo). + 'hash_mst', # Hash of the master node, only valid for + # signed images in which the master node + # does not contain a hmac. + 'padding2' # Reserved for future, zeros. + ] UBIFS_SB_NODE_SZ = struct.calcsize(UBIFS_SB_NODE_FORMAT) # Master node -UBIFS_MST_NODE_FORMAT = '<QQIIIIIIIIQQQQQQIIIIIIIIIIII344s' -UBIFS_MST_NODE_FIELDS = ['highest_inum',# Highest inode number in the - # committed index. - 'cmt_no', # Commit Number. - 'flags', # Various flags. - 'log_lnum', # LEB num start of log. - 'root_lnum', # LEB num of root indexing node. - 'root_offs', # Offset within root_lnum - 'root_len', # Root indexing node length. - 'gc_lnum', # LEB reserved for garbage collection. - 'ihead_lnum', # LEB num of index head. - 'ihead_offs', # Offset of index head. - 'index_size', # Size of index on flash. - 'total_free', # Total free space in bytes. - 'total_dirty', # Total dirty space in bytes. - 'total_used', # Total used space in bytes (data LEBs) - 'total_dead', # Total dead space in bytes (data LEBs) - 'total_dark', # Total dark space in bytes (data LEBs) - 'lpt_lnum', # LEB num of LPT root nnode. - 'lpt_offs', # Offset of LPT root nnode. - 'nhead_lnum', # LEB num of LPT head. - 'nhead_offs', # Offset of LPT head. - 'ltab_lnum', # LEB num of LPT's own lprop table. - 'ltab_offs', # Offset of LPT's own lprop table. - 'lsave_lnum', # LEB num of LPT's save table. - 'lsave_offs', # Offset of LPT's save table. - 'lscan_lnum', # LEB num of last LPT scan. - 'empty_lebs', # Number of empty LEBs. - 'idx_lebs', # Number of indexing LEBs. - 'leb_cnt', # Count of LEBs used by FS. - 'padding'] # Reserved for future, zeros. +UBIFS_MST_NODE_FORMAT = '<QQIIIIIIIIQQQQQQIIIIIIIIIIII%ss%ss%ss152s' % (UBIFS_MAX_HASH_LEN, UBIFS_MAX_HASH_LEN, UBIFS_MAX_HMAC_LEN) +UBIFS_MST_NODE_FIELDS = ['highest_inum', # Highest inode number in the + # committed index. + 'cmt_no', # Commit Number. + 'flags', # Various flags. + 'log_lnum', # LEB num start of log. + 'root_lnum', # LEB num of root indexing node. + 'root_offs', # Offset within root_lnum + 'root_len', # Root indexing node length. + 'gc_lnum', # LEB reserved for garbage collection. + 'ihead_lnum', # LEB num of index head. + 'ihead_offs', # Offset of index head. + 'index_size', # Size of index on flash. + 'total_free', # Total free space in bytes. + 'total_dirty', # Total dirty space in bytes. + 'total_used', # Total used space in bytes (data LEBs) + 'total_dead', # Total dead space in bytes (data LEBs) + 'total_dark', # Total dark space in bytes (data LEBs) + 'lpt_lnum', # LEB num of LPT root nnode. + 'lpt_offs', # Offset of LPT root nnode. + 'nhead_lnum', # LEB num of LPT head. + 'nhead_offs', # Offset of LPT head. + 'ltab_lnum', # LEB num of LPT's own lprop table. + 'ltab_offs', # Offset of LPT's own lprop table. + 'lsave_lnum', # LEB num of LPT's save table. + 'lsave_offs', # Offset of LPT's save table. + 'lscan_lnum', # LEB num of last LPT scan. + 'empty_lebs', # Number of empty LEBs. + 'idx_lebs', # Number of indexing LEBs. + 'leb_cnt', # Count of LEBs used by FS. + 'hash_root_idx', # The hash of the root index node. + 'hash_lpt', # The has of the LPT. + 'hmac', # HMAC to athenticate the master node. + 'padding', # Reserved for future, zeros. + ] UBIFS_MST_NODE_SZ = struct.calcsize(UBIFS_MST_NODE_FORMAT) # LEB Reference node UBIFS_REF_NODE_FORMAT = '<III28s' -UBIFS_REF_NODE_FIELDS = ['lnum', # Referred LEB number. - 'offs', # Start offset of referred LEB. - 'jhead', # Journal head number. - 'padding'] # Reserved for future, zeros. +UBIFS_REF_NODE_FIELDS = ['lnum', # Referred LEB number. + 'offs', # Start offset of referred LEB. + 'jhead', # Journal head number. + 'padding', # Reserved for future, zeros. + ] UBIFS_REF_NODE_SZ = struct.calcsize(UBIFS_REF_NODE_FORMAT) +# Signature node +UBIFS_SIG_NODE_FORMAT = '<II32s' +UBIFS_SIG_NODE_FIELDS = ['type', # Type of the signature. + 'len', # Length of signature data. + 'padding', # Reserved for future, zeros. + ] + # 'sig', no size. + +UBIFS_SIG_NODE_SZ = struct.calcsize(UBIFS_SIG_NODE_FORMAT) + # key/reference/length branch UBIFS_BRANCH_FORMAT = '<III%ss' % (UBIFS_SK_LEN) -UBIFS_BRANCH_FIELDS = ['lnum', # LEB number of target node. - 'offs', # Offset within lnum. - 'len', # Target node length. - 'key'] # Using UBIFS_SK_LEN as size. +UBIFS_BRANCH_FIELDS = ['lnum', # LEB number of target node. + 'offs', # Offset within lnum. + 'len', # Target node length. + 'key', # Using UBIFS_SK_LEN as size. + ] UBIFS_BRANCH_SZ = struct.calcsize(UBIFS_BRANCH_FORMAT) # Indexing node UBIFS_IDX_NODE_FORMAT = '<HH' -UBIFS_IDX_NODE_FIELDS = ['child_cnt', # Number of child index nodes. - 'level'] # Tree level. - # branches, no size. +UBIFS_IDX_NODE_FIELDS = ['child_cnt', # Number of child index nodes. + 'level', # Tree level. + ] + # 'branches', no size. UBIFS_IDX_NODE_SZ = struct.calcsize(UBIFS_IDX_NODE_FORMAT) # File chunk size for reads. -FILE_CHUNK_SZ = 5 * 1024 *1024 \ No newline at end of file +FILE_CHUNK_SZ = 5 * 1024 *1024 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/ubireader/ubifs/display.py new/ubi_reader-0.7.1-master/ubireader/ubifs/display.py --- old/ubi_reader-0.6.3-master/ubireader/ubifs/display.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/ubireader/ubifs/display.py 2021-05-22 12:29:19.000000000 +0200 @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. ############################################################# +from ubireader.ubifs.defines import PRINT_UBIFS_FLGS, PRINT_UBIFS_MST def ubifs(ubifs, tab=''): buf = '%sUBIFS Image\n' % (tab) @@ -41,6 +42,7 @@ def sb_node(node, tab=''): buf = '%s%s\n' % (tab, node) + buf += '%sFile offset: %s\n' % (tab, node.file_offset) buf += '%s---------------------\n' % (tab) tab += '\t' for key, value in node: @@ -50,6 +52,17 @@ buf += '%s%s: %s\n' % (tab, key, ','.join(value)) elif key == 'uuid': buf += '%s%s: %r\n' % (tab, key, value) + elif key == 'flags': + flags = '' + for flag in PRINT_UBIFS_FLGS: + if value & flag[0]: + flags += '%s, ' % flag[1] + + if flags.endswith(', '): + flags = flags[0:-2] + + buf += '%s%s: %s\n' % (tab, key, flags) + else: buf += '%s%s: %r\n' % (tab, key, value) return buf @@ -57,6 +70,7 @@ def mst_node(node, tab=''): buf = '%s%s\n' % (tab, node) + buf += '%sFile offset: %s\n' % (tab, node.file_offset) buf += '%s---------------------\n' % (tab) tab += '\t' for key, value in node: @@ -64,6 +78,16 @@ continue elif key == 'errors': buf += '%s%s: %s\n' % (tab, key, ','.join(value)) + elif key == 'flags': + flags = '' + for flag in PRINT_UBIFS_MST: + if value & flag[0]: + flags += '%s, ' % flag[1] + + if flags.endswith(', '): + flags = flags[0:-2] + + buf += '%s%s: %s\n' % (tab, key, flags) else: buf += '%s%s: %r\n' % (tab, key, value) return buf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/ubireader/ubifs/nodes.py new/ubi_reader-0.7.1-master/ubireader/ubifs/nodes.py --- old/ubi_reader-0.6.3-master/ubireader/ubifs/nodes.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/ubireader/ubifs/nodes.py 2021-05-22 12:29:19.000000000 +0200 @@ -209,10 +209,12 @@ Arguments: Bin:buf -- Raw data to extract header information from. + Int:offset -- Offset in LEB of data node. See ubifs/defines.py for object attributes. """ - def __init__(self, buf): + def __init__(self, buf, file_offset=-1): + self.file_offset = file_offset fields = dict(list(zip(UBIFS_SB_NODE_FIELDS, struct.unpack(UBIFS_SB_NODE_FORMAT, buf)))) for key in fields: setattr(self, key, fields[key]) @@ -236,10 +238,12 @@ Arguments: Bin:buf -- Raw data to extract header information from. + Int:offset -- Offset in LEB of data node. See ubifs/defines.py for object attributes. """ - def __init__(self, buf): + def __init__(self, buf, file_offset=-1): + self.file_offset = file_offset fields = dict(list(zip(UBIFS_MST_NODE_FIELDS, struct.unpack(UBIFS_MST_NODE_FORMAT, buf)))) for key in fields: setattr(self, key, fields[key]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ubi_reader-0.6.3-master/ubireader/ubifs/output.py new/ubi_reader-0.7.1-master/ubireader/ubifs/output.py --- old/ubi_reader-0.6.3-master/ubireader/ubifs/output.py 2019-04-16 20:26:50.000000000 +0200 +++ new/ubi_reader-0.7.1-master/ubireader/ubifs/output.py 2021-05-22 12:29:19.000000000 +0200 @@ -112,14 +112,14 @@ elif dent_node.type in [UBIFS_ITYPE_BLK, UBIFS_ITYPE_CHR]: try: dev = struct.unpack('<II', inode['ino'].data)[0] - if True: + if not settings.use_dummy_devices: os.mknod(dent_path, inode['ino'].mode, dev) log(extract_dents, 'Make Device Node: %s' % (dent_path)) if perms: - _set_file_perms(path, inode) + _set_file_perms(dent_path, inode) else: - log(extract_dents, 'Create dummy node.') + log(extract_dents, 'Create dummy device.') _write_reg_file(dent_path, str(dev)) if perms: @@ -149,8 +149,8 @@ def _set_file_perms(path, inode): - os.chmod(path, inode['ino'].mode) os.chown(path, inode['ino'].uid, inode['ino'].gid) + os.chmod(path, inode['ino'].mode) verbose_log(_set_file_perms, 'perms:%s, owner: %s.%s, path: %s' % (inode['ino'].mode, inode['ino'].uid, inode['ino'].gid, path)) def _set_file_timestamps(path, inode):
