Merge "Restrict NDK link type to matching STLs."
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 3bb8b9c..ed60188 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -15,27 +15,33 @@
 # limitations under the License.
 
 """
-Build image output_image_file from input_directory, properties_file, and target_out_dir
+Builds output_image from the given input_directory, properties_file,
+and writes the image to target_output_directory.
 
-Usage:  build_image input_directory properties_file output_image_file target_out_dir
-
+Usage:  build_image.py input_directory properties_file output_image \\
+            target_output_directory
 """
+
+from __future__ import print_function
+
 import os
 import os.path
 import re
-import subprocess
-import sys
-import common
 import shlex
 import shutil
+import subprocess
+import sys
+
+import common
 import sparse_img
-import tempfile
+
 
 OPTIONS = common.OPTIONS
 
 FIXED_SALT = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7"
 BLOCK_SIZE = 4096
 
+
 def RunCommand(cmd, verbose=None):
   """Echo and run the given command.
 
@@ -56,6 +62,7 @@
     print(output.rstrip())
   return (output, p.returncode)
 
+
 def GetVerityFECSize(partition_size):
   cmd = ["fec", "-s", str(partition_size)]
   output, exit_code = RunCommand(cmd, False)
@@ -63,6 +70,7 @@
     return False, 0
   return True, int(output)
 
+
 def GetVerityTreeSize(partition_size):
   cmd = ["build_verity_tree", "-s", str(partition_size)]
   output, exit_code = RunCommand(cmd, False)
@@ -70,6 +78,7 @@
     return False, 0
   return True, int(output)
 
+
 def GetVerityMetadataSize(partition_size):
   cmd = ["system/extras/verity/build_verity_metadata.py", "size",
          str(partition_size)]
@@ -78,6 +87,7 @@
     return False, 0
   return True, int(output)
 
+
 def GetVeritySize(partition_size, fec_supported):
   success, verity_tree_size = GetVerityTreeSize(partition_size)
   if not success:
@@ -93,16 +103,19 @@
     return verity_size + fec_size
   return verity_size
 
+
 def GetSimgSize(image_file):
   simg = sparse_img.SparseImage(image_file, build_map=False)
   return simg.blocksize * simg.total_blocks
 
+
 def ZeroPadSimg(image_file, pad_size):
   blocks = pad_size // BLOCK_SIZE
   print("Padding %d blocks (%d bytes)" % (blocks, pad_size))
   simg = sparse_img.SparseImage(image_file, mode="r+b", build_map=False)
   simg.AppendFillChunk(0, blocks)
 
+
 def AVBCalcMaxImageSize(avbtool, footer_type, partition_size, additional_args):
   """Calculates max image size for a given partition size.
 
@@ -115,8 +128,8 @@
   Returns:
     The maximum image size or 0 if an error occurred.
   """
-  cmd =[avbtool, "add_%s_footer" % footer_type,
-        "--partition_size", partition_size, "--calc_max_image_size"]
+  cmd = [avbtool, "add_%s_footer" % footer_type,
+         "--partition_size", partition_size, "--calc_max_image_size"]
   cmd.extend(shlex.split(additional_args))
 
   (output, exit_code) = RunCommand(cmd)
@@ -125,6 +138,7 @@
   else:
     return int(output)
 
+
 def AVBAddFooter(image_path, avbtool, footer_type, partition_size,
                  partition_name, key_path, algorithm, salt,
                  additional_args):
@@ -140,14 +154,15 @@
     algorithm: Name of algorithm to use or None.
     salt: The salt to use (a hexadecimal string) or None.
     additional_args: Additional arguments to pass to 'avbtool
-      add_hashtree_image'.
+        add_hashtree_image'.
+
   Returns:
     True if the operation succeeded.
   """
-  cmd =[avbtool, "add_%s_footer" % footer_type,
-        "--partition_size", partition_size,
-        "--partition_name", partition_name,
-        "--image", image_path]
+  cmd = [avbtool, "add_%s_footer" % footer_type,
+         "--partition_size", partition_size,
+         "--partition_name", partition_name,
+         "--image", image_path]
 
   if key_path and algorithm:
     cmd.extend(["--key", key_path, "--algorithm", algorithm])
@@ -159,12 +174,15 @@
   (_, exit_code) = RunCommand(cmd)
   return exit_code == 0
 
+
 def AdjustPartitionSizeForVerity(partition_size, fec_supported):
   """Modifies the provided partition size to account for the verity metadata.
 
   This information is used to size the created image appropriately.
+
   Args:
     partition_size: the size of the partition to be verified.
+
   Returns:
     A tuple of the size of the partition adjusted for verity metadata, and
     the size of verity metadata.
@@ -201,30 +219,34 @@
   AdjustPartitionSizeForVerity.results[key] = (result, verity_size)
   return (result, verity_size)
 
+
 AdjustPartitionSizeForVerity.results = {}
 
+
 def BuildVerityFEC(sparse_image_path, verity_path, verity_fec_path,
                    padding_size):
   cmd = ["fec", "-e", "-p", str(padding_size), sparse_image_path,
          verity_path, verity_fec_path]
   output, exit_code = RunCommand(cmd)
   if exit_code != 0:
-    print "Could not build FEC data! Error: %s" % output
+    print("Could not build FEC data! Error: %s" % output)
     return False
   return True
 
+
 def BuildVerityTree(sparse_image_path, verity_image_path, prop_dict):
   cmd = ["build_verity_tree", "-A", FIXED_SALT, sparse_image_path,
          verity_image_path]
   output, exit_code = RunCommand(cmd)
   if exit_code != 0:
-    print "Could not build verity tree! Error: %s" % output
+    print("Could not build verity tree! Error: %s" % output)
     return False
   root, salt = output.split()
   prop_dict["verity_root_hash"] = root
   prop_dict["verity_salt"] = salt
   return True
 
+
 def BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt,
                         block_device, signer_path, key, signer_args,
                         verity_disable):
@@ -237,10 +259,11 @@
     cmd.append("--verity_disable")
   output, exit_code = RunCommand(cmd)
   if exit_code != 0:
-    print "Could not build verity metadata! Error: %s" % output
+    print("Could not build verity metadata! Error: %s" % output)
     return False
   return True
 
+
 def Append2Simg(sparse_image_path, unsparse_image_path, error_message):
   """Appends the unsparse image to the given sparse image.
 
@@ -253,18 +276,23 @@
   cmd = ["append2simg", sparse_image_path, unsparse_image_path]
   output, exit_code = RunCommand(cmd)
   if exit_code != 0:
-    print "%s: %s" % (error_message, output)
+    print("%s: %s" % (error_message, output))
     return False
   return True
 
+
 def Append(target, file_to_append, error_message):
-  # appending file_to_append to target
-  with open(target, "a") as out_file:
-    with open(file_to_append, "r") as input_file:
+  """Appends file_to_append to target."""
+  try:
+    with open(target, "a") as out_file, open(file_to_append, "r") as input_file:
       for line in input_file:
         out_file.write(line)
+  except IOError:
+    print(error_message)
+    return False
   return True
 
+
 def BuildVerifiedImage(data_image_path, verity_image_path,
                        verity_metadata_path, verity_fec_path,
                        padding_size, fec_supported):
@@ -286,6 +314,7 @@
     return False
   return True
 
+
 def UnsparseImage(sparse_image_path, replace=True):
   img_dir = os.path.dirname(sparse_image_path)
   unsparse_image_path = "unsparse_" + os.path.basename(sparse_image_path)
@@ -302,6 +331,7 @@
     return False, None
   return True, unsparse_image_path
 
+
 def MakeVerityEnabledImage(out_file, fec_supported, prop_dict):
   """Creates an image that is verifiable using dm-verity.
 
@@ -360,14 +390,12 @@
 
   return True
 
+
 def ConvertBlockMapToBaseFs(block_map_file):
   base_fs_file = common.MakeTempFile(prefix="script_gen_", suffix=".base_fs")
-
   convert_command = ["blk_alloc_to_base_fs", block_map_file, base_fs_file]
   (_, exit_code) = RunCommand(convert_command)
-  if exit_code != 0:
-    return None
-  return base_fs_file
+  return base_fs_file if exit_code == 0 else None
 
 
 def CheckHeadroom(ext4fs_output, prop_dict):
@@ -396,7 +424,8 @@
   ext4fs_stats = re.compile(
       r'Created filesystem with .* (?P<used_blocks>[0-9]+)/'
       r'(?P<total_blocks>[0-9]+) blocks')
-  m = ext4fs_stats.match(ext4fs_output.strip().split('\n')[-1])
+  last_line = ext4fs_output.strip().split('\n')[-1]
+  m = ext4fs_stats.match(last_line)
   used_blocks = int(m.groupdict().get('used_blocks'))
   total_blocks = int(m.groupdict().get('total_blocks'))
   headroom_blocks = int(prop_dict['partition_headroom']) / BLOCK_SIZE
@@ -418,7 +447,8 @@
     in_dir: path of input directory.
     prop_dict: property dictionary.
     out_file: path of the output image file.
-    target_out: path of the product out directory to read device specific FS config files.
+    target_out: path of the product out directory to read device specific FS
+        config files.
 
   Returns:
     True iff the image is built successfully.
@@ -427,10 +457,10 @@
   # /system and the ramdisk, and can be mounted at the root of the file system.
   origin_in = in_dir
   fs_config = prop_dict.get("fs_config")
-  if (prop_dict.get("system_root_image") == "true"
-      and prop_dict["mount_point"] == "system"):
+  if (prop_dict.get("system_root_image") == "true" and
+      prop_dict["mount_point"] == "system"):
     in_dir = common.MakeTempDir()
-    # Change the mount point to "/"
+    # Change the mount point to "/".
     prop_dict["mount_point"] = "/"
     if fs_config:
       # We need to merge the fs_config files of system and ramdisk.
@@ -446,7 +476,7 @@
 
   build_command = []
   fs_type = prop_dict.get("fs_type", "")
-  run_fsck = False
+  run_e2fsck = False
 
   fs_spans_partition = True
   if fs_type.startswith("squash"):
@@ -460,8 +490,8 @@
   # verified.
   if verity_supported and is_verity_partition:
     partition_size = int(prop_dict.get("partition_size"))
-    (adjusted_size, verity_size) = AdjustPartitionSizeForVerity(partition_size,
-                                                                verity_fec_supported)
+    (adjusted_size, verity_size) = AdjustPartitionSizeForVerity(
+        partition_size, verity_fec_supported)
     if not adjusted_size:
       return False
     prop_dict["partition_size"] = str(adjusted_size)
@@ -480,8 +510,8 @@
     partition_size = prop_dict["partition_size"]
     # avb_add_hash_footer_args or avb_add_hashtree_footer_args.
     additional_args = prop_dict["avb_add_" + avb_footer_type + "_footer_args"]
-    max_image_size = AVBCalcMaxImageSize(avbtool, avb_footer_type, partition_size,
-                                         additional_args)
+    max_image_size = AVBCalcMaxImageSize(avbtool, avb_footer_type,
+                                         partition_size, additional_args)
     if max_image_size == 0:
       return False
     prop_dict["partition_size"] = str(max_image_size)
@@ -491,7 +521,7 @@
     build_command = [prop_dict["ext_mkuserimg"]]
     if "extfs_sparse_flag" in prop_dict:
       build_command.append(prop_dict["extfs_sparse_flag"])
-      run_fsck = True
+      run_e2fsck = True
     build_command.extend([in_dir, out_file, fs_type,
                           prop_dict["mount_point"]])
     build_command.append(prop_dict["partition_size"])
@@ -545,7 +575,7 @@
       build_command.extend(["-zo", prop_dict["squashfs_compressor_opt"]])
     if "squashfs_block_size" in prop_dict:
       build_command.extend(["-b", prop_dict["squashfs_block_size"]])
-    if "squashfs_disable_4k_align" in prop_dict and prop_dict.get("squashfs_disable_4k_align") == "true":
+    if prop_dict.get("squashfs_disable_4k_align") == "true":
       build_command.extend(["-a"])
   elif fs_type.startswith("f2fs"):
     build_command = ["mkf2fsuserimg.sh"]
@@ -575,18 +605,14 @@
     shutil.rmtree(staging_system, ignore_errors=True)
     shutil.copytree(origin_in, staging_system, symlinks=True)
 
-  ext4fs_output = None
-  if fs_type.startswith("ext4"):
-    (ext4fs_output, exit_code) = RunCommand(build_command)
-  else:
-    (_, exit_code) = RunCommand(build_command)
+  (mkfs_output, exit_code) = RunCommand(build_command)
   if exit_code != 0:
     print("Error: '%s' failed with exit code %d" % (build_command, exit_code))
     return False
 
   # Check if there's enough headroom space available for ext4 image.
   if "partition_headroom" in prop_dict and fs_type.startswith("ext4"):
-    if not CheckHeadroom(ext4fs_output, prop_dict):
+    if not CheckHeadroom(mkfs_output, prop_dict):
       return False
 
   if not fs_spans_partition:
@@ -600,7 +626,7 @@
     if verity_supported and is_verity_partition:
       ZeroPadSimg(out_file, partition_size - image_size)
 
-  # create the verified image if this is to be verified
+  # Create the verified image if this is to be verified.
   if verity_supported and is_verity_partition:
     if not MakeVerityEnabledImage(out_file, verity_fec_supported, prop_dict):
       return False
@@ -616,11 +642,12 @@
     salt = prop_dict.get("avb_salt")
     # avb_add_hash_footer_args or avb_add_hashtree_footer_args
     additional_args = prop_dict["avb_add_" + avb_footer_type + "_footer_args"]
-    if not AVBAddFooter(out_file, avbtool, avb_footer_type, original_partition_size,
-                        partition_name, key_path, algorithm, salt, additional_args):
+    if not AVBAddFooter(out_file, avbtool, avb_footer_type,
+                        original_partition_size, partition_name, key_path,
+                        algorithm, salt, additional_args):
       return False
 
-  if run_fsck and prop_dict.get("skip_fsck") != "true":
+  if run_e2fsck and prop_dict.get("skip_fsck") != "true":
     success, unsparse_image = UnsparseImage(out_file, replace=False)
     if not success:
       return False
@@ -632,7 +659,8 @@
     os.remove(unsparse_image)
 
     if exit_code != 0:
-      print("Error: '%s' failed with exit code %d" % (e2fsck_command, exit_code))
+      print("Error: '%s' failed with exit code %d" % (e2fsck_command,
+                                                      exit_code))
       return False
 
   return True
@@ -699,7 +727,8 @@
     copy_prop("system_base_fs_file", "base_fs_file")
     copy_prop("system_extfs_inode_count", "extfs_inode_count")
   elif mount_point == "system_other":
-    # We inherit the selinux policies of /system since we contain some of its files.
+    # We inherit the selinux policies of /system since we contain some of its
+    # files.
     d["mount_point"] = "system"
     copy_prop("avb_system_hashtree_enable", "avb_hashtree_enable")
     copy_prop("avb_system_add_hashtree_footer_args",
@@ -721,7 +750,7 @@
     copy_prop("fs_type", "fs_type")
     copy_prop("userdata_fs_type", "fs_type")
     copy_prop("userdata_size", "partition_size")
-    copy_prop("flash_logical_block_size","flash_logical_block_size")
+    copy_prop("flash_logical_block_size", "flash_logical_block_size")
     copy_prop("flash_erase_block_size", "flash_erase_block_size")
   elif mount_point == "cache":
     copy_prop("cache_fs_type", "fs_type")
@@ -767,7 +796,7 @@
 
 def main(argv):
   if len(argv) != 4:
-    print __doc__
+    print(__doc__)
     sys.exit(1)
 
   in_dir = argv[0]
@@ -796,14 +825,14 @@
     elif image_filename == "oem.img":
       mount_point = "oem"
     else:
-      print >> sys.stderr, "error: unknown image file name ", image_filename
+      print("error: unknown image file name ", image_filename, file=sys.stderr)
       sys.exit(1)
 
     image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
 
   if not BuildImage(in_dir, image_properties, out_file, target_out):
-    print >> sys.stderr, "error: failed to build %s from %s" % (out_file,
-                                                                in_dir)
+    print("error: failed to build %s from %s" % (out_file, in_dir),
+          file=sys.stderr)
     sys.exit(1)