platform_build/tools/releasetools/img_from_target_files.py
Tao Bao 2ed665a033 Wrap zipfile.write(), writestr() and close()
In order to work around the zip 2GiB limit, we need to wrap the related
functions in zipfile. Calls to those functions should always be replaced
with calls to the wrappers instead.

Bug: 18015246
Change-Id: Ice494371ca6654e88ded2ae0eb680f51082effcb
2015-05-08 13:51:12 -07:00

151 lines
4.5 KiB
Python
Executable file

#!/usr/bin/env python
#
# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Given a target-files zipfile, produces an image zipfile suitable for
use with 'fastboot update'.
Usage: img_from_target_files [flags] input_target_files output_image_zip
-z (--bootable_zip)
Include only the bootable images (eg 'boot' and 'recovery') in
the output.
"""
import sys
if sys.hexversion < 0x02070000:
print >> sys.stderr, "Python 2.7 or newer is required."
sys.exit(1)
import os
import shutil
import zipfile
import common
OPTIONS = common.OPTIONS
def CopyInfo(output_zip):
"""Copy the android-info.txt file from the input to the output."""
common.ZipWrite(
output_zip, os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"),
"android-info.txt")
def main(argv):
bootable_only = [False]
def option_handler(o, _):
if o in ("-z", "--bootable_zip"):
bootable_only[0] = True
else:
return False
return True
args = common.ParseOptions(argv, __doc__,
extra_opts="z",
extra_long_opts=["bootable_zip"],
extra_option_handler=option_handler)
bootable_only = bootable_only[0]
if len(args) != 2:
common.Usage(__doc__)
sys.exit(1)
OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0])
output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED)
CopyInfo(output_zip)
try:
done = False
images_path = os.path.join(OPTIONS.input_tmp, "IMAGES")
if os.path.exists(images_path):
# If this is a new target-files, it already contains the images,
# and all we have to do is copy them to the output zip.
images = os.listdir(images_path)
if images:
for image in images:
if bootable_only and image not in ("boot.img", "recovery.img"):
continue
if not image.endswith(".img"):
continue
common.ZipWrite(
output_zip, os.path.join(images_path, image), image)
done = True
if not done:
# We have an old target-files that doesn't already contain the
# images, so build them.
import add_img_to_target_files
OPTIONS.info_dict = common.LoadInfoDict(input_zip)
# If this image was originally labelled with SELinux contexts,
# make sure we also apply the labels in our new image. During
# building, the "file_contexts" is in the out/ directory tree,
# but for repacking from target-files.zip it's in the root
# directory of the ramdisk.
if "selinux_fc" in OPTIONS.info_dict:
OPTIONS.info_dict["selinux_fc"] = os.path.join(
OPTIONS.input_tmp, "BOOT", "RAMDISK", "file_contexts")
boot_image = common.GetBootableImage(
"boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
if boot_image:
boot_image.AddToZip(output_zip)
recovery_image = common.GetBootableImage(
"recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY")
if recovery_image:
recovery_image.AddToZip(output_zip)
def banner(s):
print "\n\n++++ " + s + " ++++\n\n"
if not bootable_only:
banner("AddSystem")
add_img_to_target_files.AddSystem(output_zip, prefix="")
try:
input_zip.getinfo("VENDOR/")
banner("AddVendor")
add_img_to_target_files.AddVendor(output_zip, prefix="")
except KeyError:
pass # no vendor partition for this device
banner("AddUserdata")
add_img_to_target_files.AddUserdata(output_zip, prefix="")
banner("AddCache")
add_img_to_target_files.AddCache(output_zip, prefix="")
finally:
print "cleaning up..."
common.ZipClose(output_zip)
shutil.rmtree(OPTIONS.input_tmp)
print "done."
if __name__ == '__main__':
try:
common.CloseInheritedPipes()
main(sys.argv[1:])
except common.ExternalError as e:
print
print " ERROR: %s" % (e,)
print
sys.exit(1)