Home | History | Annotate | Download | only in releasetools
      1 #!/usr/bin/env python
      2 #
      3 # Copyright (C) 2008 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 
     17 """
     18 Given a target-files zipfile, produces an image zipfile suitable for
     19 use with 'fastboot update'.
     20 
     21 Usage:  img_from_target_files [flags] input_target_files output_image_zip
     22 
     23   -b  (--board_config)  <file>
     24       Deprecated.
     25 
     26 """
     27 
     28 import sys
     29 
     30 if sys.hexversion < 0x02040000:
     31   print >> sys.stderr, "Python 2.4 or newer is required."
     32   sys.exit(1)
     33 
     34 import errno
     35 import os
     36 import re
     37 import shutil
     38 import subprocess
     39 import tempfile
     40 import zipfile
     41 
     42 # missing in Python 2.4 and before
     43 if not hasattr(os, "SEEK_SET"):
     44   os.SEEK_SET = 0
     45 
     46 import common
     47 
     48 OPTIONS = common.OPTIONS
     49 
     50 
     51 def AddUserdata(output_zip):
     52   """Create an empty userdata image and store it in output_zip."""
     53 
     54   print "creating userdata.img..."
     55 
     56   # The name of the directory it is making an image out of matters to
     57   # mkyaffs2image.  So we create a temp dir, and within it we create an
     58   # empty dir named "data", and build the image from that.
     59   temp_dir = tempfile.mkdtemp()
     60   user_dir = os.path.join(temp_dir, "data")
     61   os.mkdir(user_dir)
     62   img = tempfile.NamedTemporaryFile()
     63 
     64   p = common.Run(["mkyaffs2image", "-f", user_dir, img.name])
     65   p.communicate()
     66   assert p.returncode == 0, "mkyaffs2image of userdata.img image failed"
     67 
     68   common.CheckSize(img.name, "userdata.img")
     69   output_zip.write(img.name, "userdata.img")
     70   img.close()
     71   os.rmdir(user_dir)
     72   os.rmdir(temp_dir)
     73 
     74 
     75 def AddSystem(output_zip):
     76   """Turn the contents of SYSTEM into a system image and store it in
     77   output_zip."""
     78 
     79   print "creating system.img..."
     80 
     81   img = tempfile.NamedTemporaryFile()
     82 
     83   # The name of the directory it is making an image out of matters to
     84   # mkyaffs2image.  It wants "system" but we have a directory named
     85   # "SYSTEM", so create a symlink.
     86   try:
     87     os.symlink(os.path.join(OPTIONS.input_tmp, "SYSTEM"),
     88                os.path.join(OPTIONS.input_tmp, "system"))
     89   except OSError, e:
     90       # bogus error on my mac version?
     91       #   File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem
     92       #     os.path.join(OPTIONS.input_tmp, "system"))
     93       # OSError: [Errno 17] File exists
     94     if (e.errno == errno.EEXIST):
     95       pass
     96 
     97   p = common.Run(["mkyaffs2image", "-f",
     98                   os.path.join(OPTIONS.input_tmp, "system"), img.name])
     99   p.communicate()
    100   assert p.returncode == 0, "mkyaffs2image of system.img image failed"
    101 
    102   img.seek(os.SEEK_SET, 0)
    103   data = img.read()
    104   img.close()
    105 
    106   common.CheckSize(data, "system.img")
    107   common.ZipWriteStr(output_zip, "system.img", data)
    108 
    109 
    110 def CopyInfo(output_zip):
    111   """Copy the android-info.txt file from the input to the output."""
    112   output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"),
    113                    "android-info.txt")
    114 
    115 
    116 def main(argv):
    117 
    118   def option_handler(o, a):
    119     if o in ("-b", "--board_config"):
    120       pass       # deprecated
    121     else:
    122       return False
    123     return True
    124 
    125   args = common.ParseOptions(argv, __doc__,
    126                              extra_opts="b:",
    127                              extra_long_opts=["board_config="],
    128                              extra_option_handler=option_handler)
    129 
    130   if len(args) != 2:
    131     common.Usage(__doc__)
    132     sys.exit(1)
    133 
    134   OPTIONS.input_tmp = common.UnzipTemp(args[0])
    135 
    136   common.LoadMaxSizes()
    137   if not OPTIONS.max_image_size:
    138     print
    139     print "  WARNING:  Failed to load max image sizes; will not enforce"
    140     print "  image size limits."
    141     print
    142 
    143   output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED)
    144 
    145   common.AddBoot(output_zip)
    146   common.AddRecovery(output_zip)
    147   AddSystem(output_zip)
    148   AddUserdata(output_zip)
    149   CopyInfo(output_zip)
    150 
    151   print "cleaning up..."
    152   output_zip.close()
    153   shutil.rmtree(OPTIONS.input_tmp)
    154 
    155   print "done."
    156 
    157 
    158 if __name__ == '__main__':
    159   try:
    160     main(sys.argv[1:])
    161   except common.ExternalError, e:
    162     print
    163     print "   ERROR: %s" % (e,)
    164     print
    165     sys.exit(1)
    166