simulate_ota.py: truncate partitions to multiples of 4 KiB
If a partition size is not a multiple size of 4 KiB then
simulate_ota.py will fail since delta_generator operates
on 4KiB blocks only.
Truncate partitions that are not multiple of 4 KiB.
Target partitions are rounded up and source partitions
are rounded down.
The logic is copied from brillo_update_payload
reference: a479a4d0039308fcfdda21f2a8ec8d040fd716f2
Set python interpreter to python3 since this script contains
python3 specific code.
Chmod script +x.
Bug: 230761009
Test: Execute simulate_ota.py with images not aligned to 4 KiB
Test: pylint3 --rcfile=../pylintrc simulate_ota.py
Change-Id: I428d8e5d2422010b4171c0214689b109ff5c9caa
diff --git a/scripts/simulate_ota.py b/scripts/simulate_ota.py
old mode 100644
new mode 100755
index bf1fc98..0e5a21b
--- a/scripts/simulate_ota.py
+++ b/scripts/simulate_ota.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
#
# Copyright (C) 2020 The Android Open Source Project
#
@@ -17,8 +18,6 @@
"""Tools for running host side simulation of an OTA update."""
-from __future__ import print_function
-
import argparse
import filecmp
import os
@@ -49,7 +48,8 @@
return fp.read(4) == b'\x3A\xFF\x26\xED'
-def extract_img(zip_archive: zipfile.ZipFile, img_name, output_path):
+def extract_img(zip_archive: zipfile.ZipFile, img_name, output_path, is_source):
+ """ Extract and unsparse partition image from zip archive """
entry_name = "IMAGES/" + img_name + ".img"
try:
extract_file(zip_archive, entry_name, output_path)
@@ -61,6 +61,22 @@
subprocess.check_output(["simg2img", output_path, raw_img_path])
os.rename(raw_img_path, output_path)
+ # delta_generator only supports images multiple of 4 KiB. For target images
+ # we pad the data with zeros if needed, but for source images we truncate
+ # down the data since the last block of the old image could be padded on
+ # disk with unknown data.
+ file_size = os.path.getsize(output_path)
+ if file_size % 4096 != 0:
+ if is_source:
+ print("Rounding DOWN partition {} to a multiple of 4 KiB."
+ .format(output_path))
+ file_size = file_size & -4096
+ else:
+ print("Rounding UP partition {} to a multiple of 4 KiB."
+ .format(output_path))
+ file_size = (file_size + 4095) & -4096
+ with open(output_path, 'a') as f:
+ f.truncate(file_size)
def run_ota(source, target, payload_path, tempdir, output_dir):
"""Run an OTA on host side"""
@@ -87,10 +103,10 @@
"source target file must point to a valid zipfile or directory " + \
source
print("Extracting source image for", name)
- extract_img(source, name, old_image)
+ extract_img(source, name, old_image, True)
if target_exist:
print("Extracting target image for", name)
- extract_img(target, name, new_image)
+ extract_img(target, name, new_image, False)
old_partitions.append(old_image)
scratch_image_name = new_image + ".actual"