[diffoscope] 01/01: Support Android ROM boot.img introspection. (Closes: #884557)

Chris Lamb chris at chris-lamb.co.uk
Mon Dec 18 23:04:02 CET 2017


This is an automated email from the git hooks/post-receive script.

lamby pushed a commit to branch master
in repository diffoscope.

commit 18364f495ead8352325ac4783a3f35ebcf0297fb
Author: Chris Lamb <lamby at debian.org>
Date:   Sun Dec 17 20:16:51 2017 +0000

    Support Android ROM boot.img introspection. (Closes: #884557)
---
 debian/control                     |   1 +
 diffoscope/comparators/__init__.py |   1 +
 diffoscope/comparators/android.py  |  87 +++++++++++++++++++++++++++++++++++++
 diffoscope/external_tools.py       |   3 ++
 tests/comparators/test_android.py  |  61 ++++++++++++++++++++++++++
 tests/data/android1.img            | Bin 0 -> 4208640 bytes
 tests/data/android2.img            | Bin 0 -> 4210688 bytes
 tests/data/android_expected_diff   |  26 +++++++++++
 8 files changed, 179 insertions(+)

diff --git a/debian/control b/debian/control
index a19eefa..7988b16 100644
--- a/debian/control
+++ b/debian/control
@@ -9,6 +9,7 @@ Uploaders:
  Reiner Herrmann <reiner at reiner-h.de>,
  Ximin Luo <infinity0 at debian.org>,
 Build-Depends:
+ abootimg <!nocheck>,
  apktool <!nocheck>,
  bash-completion,
  binutils-multiarch <!nocheck>,
diff --git a/diffoscope/comparators/__init__.py b/diffoscope/comparators/__init__.py
index 9b4791c..311f43c 100644
--- a/diffoscope/comparators/__init__.py
+++ b/diffoscope/comparators/__init__.py
@@ -83,6 +83,7 @@ class ComparatorManager(object):
         ('image.ICOImageFile',),
         ('cbfs.CbfsFile',),
         ('git.GitIndexFile',),
+        ('android.AndroidBootImgFile',),
         ('openssh.PublicKeyFile',),
         ('gif.GifFile',),
         ('pcap.PcapFile',),
diff --git a/diffoscope/comparators/android.py b/diffoscope/comparators/android.py
new file mode 100644
index 0000000..a54d6aa
--- /dev/null
+++ b/diffoscope/comparators/android.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+#
+# diffoscope: in-depth comparison of files, archives, and directories
+#
+# Copyright © 2017 Chris Lamb <lamby at debian.org>
+#
+# diffoscope 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.
+#
+# diffoscope 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 diffoscope.  If not, see <https://www.gnu.org/licenses/>.
+
+import os
+import re
+import logging
+import subprocess
+
+from diffoscope.tools import tool_required
+from diffoscope.tempfiles import get_temporary_directory
+from diffoscope.difference import Difference
+
+from .utils.file import File
+from .utils.archive import Archive
+from .utils.command import Command
+
+logger = logging.getLogger(__name__)
+
+
+class AbootimgInfo(Command):
+    @tool_required('abootimg')
+    def cmdline(self):
+        return ['abootimg', '-i', self.path]
+
+    def filter(self, line):
+        if line.startswith(b'* file name = '):
+            return b''
+        return line
+
+
+class AndroidBootImgContainer(Archive):
+    @property
+    def path(self):
+        return self._path
+
+    @tool_required('abootimg')
+    def open_archive(self):
+        self._members = []
+        self._unpacked = get_temporary_directory()
+
+        logger.debug(
+            "Extracting Android boot image to %s",
+            self._unpacked.name,
+        )
+
+        subprocess.check_call(
+            ['abootimg', '-x', os.path.abspath(self.source.path)],
+            cwd=self._unpacked.name,
+            stdout=subprocess.PIPE,
+        )
+
+        self._members = sorted(os.listdir(self._unpacked.name))
+
+        return self
+
+    def close_archive(self):
+        self._unpacked.cleanup()
+
+    def extract(self, member_name, dest_dir):
+        return os.path.join(self._unpacked.name, member_name)
+
+    def get_member_names(self):
+        return self._members
+
+
+class AndroidBootImgFile(File):
+    FILE_TYPE_RE = re.compile(r'^Android bootimg\b')
+    CONTAINER_CLASS = AndroidBootImgContainer
+
+    def compare_details(self, other, source=None):
+        return [Difference.from_command(AbootimgInfo, self.path, other.path)]
diff --git a/diffoscope/external_tools.py b/diffoscope/external_tools.py
index 7114d0b..cdb097b 100644
--- a/diffoscope/external_tools.py
+++ b/diffoscope/external_tools.py
@@ -18,6 +18,9 @@
 # along with diffoscope.  If not, see <https://www.gnu.org/licenses/>.
 
 EXTERNAL_TOOLS = {
+    'abootimg': {
+        'debian': 'abootimg',
+    },
     'apktool': {
         'debian': 'apktool',
     },
diff --git a/tests/comparators/test_android.py b/tests/comparators/test_android.py
new file mode 100644
index 0000000..5676833
--- /dev/null
+++ b/tests/comparators/test_android.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+#
+# diffoscope: in-depth comparison of files, archives, and directories
+#
+# Copyright © 2017 Chris Lamb <lamby at debian.org>
+#
+# diffoscope 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.
+#
+# diffoscope 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 diffoscope.  If not, see <https://www.gnu.org/licenses/>.
+
+import pytest
+
+from diffoscope.config import Config
+from diffoscope.comparators.android import AndroidBootImgFile
+from diffoscope.comparators.missing_file import MissingFile
+
+from ..utils.data import load_fixture, get_data
+from ..utils.tools import skip_unless_tools_exist
+
+bootimg1 = load_fixture('android1.img')
+bootimg2 = load_fixture('android2.img')
+
+
+def test_identification(bootimg1):
+    assert isinstance(bootimg1, AndroidBootImgFile)
+
+
+def test_no_differences(bootimg1):
+    difference = bootimg1.compare(bootimg1)
+    assert difference is None
+
+
+ at pytest.fixture
+def differences(bootimg1, bootimg2):
+    return bootimg1.compare(bootimg2).details
+
+
+ at skip_unless_tools_exist('abootimg')
+def test_diff(differences):
+    # FIXME
+    with open('tests/data/android_expected_diff', 'w') as f:
+        f.write(differences[0].unified_diff)
+    expected_diff = get_data('android_expected_diff')
+    assert differences[0].unified_diff == expected_diff
+
+
+ at skip_unless_tools_exist('abootimg')
+def test_compare_non_existing(monkeypatch, bootimg1):
+    monkeypatch.setattr(Config(), 'new_file', True)
+    difference = bootimg1.compare(MissingFile('/nonexisting', bootimg1))
+    assert difference.source2 == '/nonexisting'
+    assert len(difference.details) > 0
diff --git a/tests/data/android1.img b/tests/data/android1.img
new file mode 100644
index 0000000..7c740b9
Binary files /dev/null and b/tests/data/android1.img differ
diff --git a/tests/data/android2.img b/tests/data/android2.img
new file mode 100644
index 0000000..7a7251e
Binary files /dev/null and b/tests/data/android2.img differ
diff --git a/tests/data/android_expected_diff b/tests/data/android_expected_diff
new file mode 100644
index 0000000..e627c5e
--- /dev/null
+++ b/tests/data/android_expected_diff
@@ -0,0 +1,26 @@
+@@ -1,21 +1,21 @@
+ 
+ Android Boot Image Info:
+ 
+ 
+-* image size = 4208640 bytes (4.01 MB)
++* image size = 4210688 bytes (4.02 MB)
+   page size  = 2048 bytes
+ 
+ * Boot Name = ""
+ 
+-* kernel size       = 3362536 bytes (3.21 MB)
+-  ramdisk size      = 843767 bytes (0.80 MB)
++* kernel size       = 3364168 bytes (3.21 MB)
++  ramdisk size      = 843423 bytes (0.80 MB)
+ 
+ * load addresses:
+   kernel:       0x40008000
+   ramdisk:      0x41000000
+   tags:         0x40000100
+ 
+ * cmdline = console=ttySAC2,115200
+ 
+-* id = 0xbc355d43 0x2bb553fa 0x07a2b7e7 0x3a478a8e 0x7ad80fc9 0x00000000 0x00000000 0x00000000 
++* id = 0x14f85169 0x2cf191e4 0xb417063f 0x774f8d57 0x83136834 0x00000000 0x00000000 0x00000000 
+ 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git


More information about the diffoscope mailing list