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 def AddUserdata(output_zip): 51 """Create an empty userdata image and store it in output_zip.""" 52 53 print "creating userdata.img..." 54 55 # The name of the directory it is making an image out of matters to 56 # mkyaffs2image. So we create a temp dir, and within it we create an 57 # empty dir named "data", and build the image from that. 58 temp_dir = tempfile.mkdtemp() 59 user_dir = os.path.join(temp_dir, "data") 60 os.mkdir(user_dir) 61 img = tempfile.NamedTemporaryFile() 62 63 build_command = [] 64 if OPTIONS.info_dict["fstab"]["/data"].fs_type.startswith("ext"): 65 build_command = ["mkuserimg.sh", 66 user_dir, img.name, 67 OPTIONS.info_dict["fstab"]["/data"].fs_type, "data"] 68 if "userdata_size" in OPTIONS.info_dict: 69 build_command.append(str(OPTIONS.info_dict["userdata_size"])) 70 else: 71 build_command = ["mkyaffs2image", "-f"] 72 extra = OPTIONS.info_dict.get("mkyaffs2_extra_flags", None) 73 if extra: 74 build_command.extend(extra.split()) 75 build_command.append(user_dir) 76 build_command.append(img.name) 77 78 p = common.Run(build_command) 79 p.communicate() 80 assert p.returncode == 0, "build userdata.img image failed" 81 82 common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict) 83 output_zip.write(img.name, "userdata.img") 84 img.close() 85 os.rmdir(user_dir) 86 os.rmdir(temp_dir) 87 88 89 def AddSystem(output_zip): 90 """Turn the contents of SYSTEM into a system image and store it in 91 output_zip.""" 92 93 print "creating system.img..." 94 95 img = tempfile.NamedTemporaryFile() 96 97 # The name of the directory it is making an image out of matters to 98 # mkyaffs2image. It wants "system" but we have a directory named 99 # "SYSTEM", so create a symlink. 100 try: 101 os.symlink(os.path.join(OPTIONS.input_tmp, "SYSTEM"), 102 os.path.join(OPTIONS.input_tmp, "system")) 103 except OSError, e: 104 # bogus error on my mac version? 105 # File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem 106 # os.path.join(OPTIONS.input_tmp, "system")) 107 # OSError: [Errno 17] File exists 108 if (e.errno == errno.EEXIST): 109 pass 110 111 build_command = [] 112 if OPTIONS.info_dict["fstab"]["/system"].fs_type.startswith("ext"): 113 build_command = ["mkuserimg.sh", 114 os.path.join(OPTIONS.input_tmp, "system"), img.name, 115 OPTIONS.info_dict["fstab"]["/system"].fs_type, "system"] 116 if "system_size" in OPTIONS.info_dict: 117 build_command.append(str(OPTIONS.info_dict["system_size"])) 118 else: 119 build_command = ["mkyaffs2image", "-f"] 120 extra = OPTIONS.info_dict.get("mkyaffs2_extra_flags", None) 121 if extra: 122 build_command.extend(extra.split()) 123 build_command.append(os.path.join(OPTIONS.input_tmp, "system")) 124 build_command.append(img.name) 125 126 p = common.Run(build_command) 127 p.communicate() 128 assert p.returncode == 0, "build system.img image failed" 129 130 img.seek(os.SEEK_SET, 0) 131 data = img.read() 132 img.close() 133 134 common.CheckSize(data, "system.img", OPTIONS.info_dict) 135 common.ZipWriteStr(output_zip, "system.img", data) 136 137 138 def CopyInfo(output_zip): 139 """Copy the android-info.txt file from the input to the output.""" 140 output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"), 141 "android-info.txt") 142 143 144 def main(argv): 145 146 def option_handler(o, a): 147 if o in ("-b", "--board_config"): 148 pass # deprecated 149 else: 150 return False 151 return True 152 153 args = common.ParseOptions(argv, __doc__, 154 extra_opts="b:", 155 extra_long_opts=["board_config="], 156 extra_option_handler=option_handler) 157 158 if len(args) != 2: 159 common.Usage(__doc__) 160 sys.exit(1) 161 162 OPTIONS.input_tmp = common.UnzipTemp(args[0]) 163 164 input_zip = zipfile.ZipFile(args[0], "r") 165 OPTIONS.info_dict = common.LoadInfoDict(input_zip) 166 167 output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) 168 169 common.AddBoot(output_zip, OPTIONS.info_dict) 170 common.AddRecovery(output_zip, OPTIONS.info_dict) 171 AddSystem(output_zip) 172 AddUserdata(output_zip) 173 CopyInfo(output_zip) 174 175 print "cleaning up..." 176 output_zip.close() 177 shutil.rmtree(OPTIONS.input_tmp) 178 179 print "done." 180 181 182 if __name__ == '__main__': 183 try: 184 main(sys.argv[1:]) 185 except common.ExternalError, e: 186 print 187 print " ERROR: %s" % (e,) 188 print 189 sys.exit(1) 190