[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