edify_generator.py revision 14833605d26bf970cd5335c02af4354b68d93348
1c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# Copyright (C) 2009 The Android Open Source Project 2c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# 3c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# Licensed under the Apache License, Version 2.0 (the "License"); 4c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# you may not use this file except in compliance with the License. 5c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# You may obtain a copy of the License at 6c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# 7c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# http://www.apache.org/licenses/LICENSE-2.0 8c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# 9c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# Unless required by applicable law or agreed to in writing, software 10c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# distributed under the License is distributed on an "AS IS" BASIS, 11c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# See the License for the specific language governing permissions and 13c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker# limitations under the License. 14c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 15c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongkerimport os 16c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongkerimport re 17c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 18c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongkerimport common 19c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 20c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongkerclass EdifyGenerator(object): 21c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Class to generate scripts in the 'edify' recovery script language 22c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker used from donut onwards.""" 23c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 24c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def __init__(self, version): 25c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script = [] 26c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.mounts = set() 27c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.version = version 28c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 29c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def MakeTemporary(self): 30c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Make a temporary script object whose commands can latter be 31c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker appended to the parent script with AppendScript(). Used when the 32c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker caller wants to generate script commands out-of-order.""" 33c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker x = EdifyGenerator(self.version) 34c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker x.mounts = self.mounts 35c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker return x 36c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 37c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker @staticmethod 38c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def _WordWrap(cmd, linelen=80): 39c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """'cmd' should be a function call with null characters after each 40c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker parameter (eg, "somefun(foo,\0bar,\0baz)"). This function wraps cmd 41c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker to a given line length, replacing nulls with spaces and/or newlines 42c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker to format it nicely.""" 43c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker indent = cmd.index("(")+1 44c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker out = [] 45c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker first = True 46c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker x = re.compile("^(.{,%d})\0" % (linelen-indent,)) 47c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker while True: 48c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if not first: 49c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker out.append(" " * indent) 50c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker first = False 51c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker m = x.search(cmd) 52c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if not m: 53c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker parts = cmd.split("\0", 1) 54c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker out.append(parts[0]+"\n") 55c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if len(parts) == 1: 56c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker break 57c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker else: 58c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = parts[1] 59c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker continue 60c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker out.append(m.group(1)+"\n") 61c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = cmd[m.end():] 62c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 63c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker return "".join(out).replace("\0", " ").rstrip("\n") 64c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 65c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AppendScript(self, other): 66c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Append the contents of another script (which should be created 67c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker with temporary=True) to this one.""" 68c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.extend(other.script) 69c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 70c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AssertSomeFingerprint(self, *fp): 71c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Assert that the current system build fingerprint is one of *fp.""" 72c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if not fp: 73c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker raise ValueError("must specify some fingerprints") 74c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = ('assert(' + 75c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ' ||\0'.join([('file_getprop("/system/build.prop", ' 76c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker '"ro.build.fingerprint") == "%s"') 77c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker % i for i in fp]) + 78c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ');') 79c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 80c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 81c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AssertOlderBuild(self, timestamp): 82c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Assert that the build on the device is older (or the same as) 83c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker the given timestamp.""" 84c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(('assert(!less_than_int(%s, ' 85c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 'getprop("ro.build.date.utc")));') % (timestamp,)) 86c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 87c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AssertDevice(self, device): 88c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Assert that the device identifier is the given string.""" 89c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = ('assert(getprop("ro.product.device") == "%s" ||\0' 90c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 'getprop("ro.build.product") == "%s");' % (device, device)) 91c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 92c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 93c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AssertSomeBootloader(self, *bootloaders): 94c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Asert that the bootloader version is one of *bootloaders.""" 95c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = ("assert(" + 96c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker " ||\0".join(['getprop("ro.bootloader") == "%s"' % (b,) 97c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for b in bootloaders]) + 98c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ");") 99c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 100c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 101c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def ShowProgress(self, frac, dur): 102c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Update the progress bar, advancing it over 'frac' over the next 103881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker 'dur' seconds. 'dur' may be zero to advance it via SetProgress 104881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker commands instead of by time.""" 105c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append("show_progress(%f, %d);" % (frac, int(dur))) 106c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 107881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker def SetProgress(self, frac): 108881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker """Set the position of the progress bar within the chunk defined 109881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker by the most recent ShowProgress call. 'frac' should be in 110881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker [0,1].""" 111881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker self.script.append("set_progress(%f);" % (frac,)) 112881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker 113c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def PatchCheck(self, filename, *sha1): 114c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Check that the given file (or MTD reference) has one of the 115c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker given *sha1 hashes.""" 116c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append('assert(apply_patch_check("%s"' % (filename,) + 117c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker "".join([', "%s"' % (i,) for i in sha1]) + 118c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker '));') 119c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 120c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def CacheFreeSpaceCheck(self, amount): 121c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Check that there's at least 'amount' space that can be made 122c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker available on /cache.""" 123c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append("assert(apply_patch_space(%d));" % (amount,)) 124c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 125c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def Mount(self, kind, what, path): 126c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Mount the given 'what' at the given path. 'what' should be a 127c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker partition name if kind is "MTD", or a block device if kind is 128c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker "vfat". No other values of 'kind' are supported.""" 129c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append('mount("%s", "%s", "%s");' % (kind, what, path)) 130c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.mounts.add(path) 131c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 132c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def UnpackPackageDir(self, src, dst): 133c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Unpack a given directory from the OTA package into the given 134c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker destination directory.""" 135c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append('package_extract_dir("%s", "%s");' % (src, dst)) 136c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 137c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def Comment(self, comment): 138c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Write a comment into the update script.""" 139c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append("") 140c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for i in comment.split("\n"): 141c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append("# " + i) 142c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append("") 143c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 144c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def Print(self, message): 145c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Log a message to the screen (if the logs are visible).""" 146c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append('ui_print("%s");' % (message,)) 147c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 148c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def FormatPartition(self, partition): 149c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Format the given MTD partition.""" 150c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append('format("MTD", "%s");' % (partition,)) 151c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 152c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def DeleteFiles(self, file_list): 153c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Delete all files in file_list.""" 154c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if not file_list: return 155c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = "delete(" + ",\0".join(['"%s"' % (i,) for i in file_list]) + ");" 156c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 157c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 158c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs): 159c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Apply binary patches (in *patchpairs) to the given srcfile to 160c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker produce tgtfile (which may be "-" to indicate overwriting the 161c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker source file.""" 162c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if len(patchpairs) % 2 != 0 or len(patchpairs) == 0: 163c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker raise ValueError("bad patches given to ApplyPatch") 164c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = ['apply_patch("%s",\0"%s",\0%s,\0%d' 165c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker % (srcfile, tgtfile, tgtsha1, tgtsize)] 166c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for i in range(0, len(patchpairs), 2): 167c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd.append(',\0"%s:%s"' % patchpairs[i:i+2]) 168c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd.append(');') 169c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = "".join(cmd) 170c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 171c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 172c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def WriteFirmwareImage(self, kind, fn): 173c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Arrange to update the given firmware image (kind must be 174c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker "hboot" or "radio") when recovery finishes.""" 175c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if self.version == 1: 176c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append( 177c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ('assert(package_extract_file("%(fn)s", "/tmp/%(kind)s.img"),\n' 178c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ' write_firmware_image("/tmp/%(kind)s.img", "%(kind)s"));') 179c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker % {'kind': kind, 'fn': fn}) 180c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker else: 181c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append( 182c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 'write_firmware_image("PACKAGE:%s", "%s");' % (fn, kind)) 183c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 184c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def WriteRawImage(self, partition, fn): 185c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Write the given package file into the given MTD partition.""" 186c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append( 187c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ('assert(package_extract_file("%(fn)s", "/tmp/%(partition)s.img"),\n' 188c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ' write_raw_image("/tmp/%(partition)s.img", "%(partition)s"),\n' 189c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ' delete("/tmp/%(partition)s.img"));') 190c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker % {'partition': partition, 'fn': fn}) 191c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 192c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def SetPermissions(self, fn, uid, gid, mode): 193c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Set file ownership and permissions.""" 194c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append('set_perm(%d, %d, 0%o, "%s");' % (uid, gid, mode, fn)) 195c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 196c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode): 197c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Recursively set path ownership and permissions.""" 198c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append('set_perm_recursive(%d, %d, 0%o, 0%o, "%s");' 199c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker % (uid, gid, dmode, fmode, fn)) 200c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 201c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def MakeSymlinks(self, symlink_list): 202c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Create symlinks, given a list of (dest, link) pairs.""" 203c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker by_dest = {} 204c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for d, l in symlink_list: 205c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker by_dest.setdefault(d, []).append(l) 206c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 207c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for dest, links in sorted(by_dest.iteritems()): 208c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = ('symlink("%s", ' % (dest,) + 209c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ",\0".join(['"' + i + '"' for i in sorted(links)]) + ");") 210c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 211c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 212c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AppendExtra(self, extra): 213c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Append text verbatim to the output script.""" 214c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(extra) 215c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 21614833605d26bf970cd5335c02af4354b68d93348Doug Zongker def UnmountAll(self): 21714833605d26bf970cd5335c02af4354b68d93348Doug Zongker for p in sorted(self.mounts): 21814833605d26bf970cd5335c02af4354b68d93348Doug Zongker self.script.append('unmount("%s");' % (p,)) 21914833605d26bf970cd5335c02af4354b68d93348Doug Zongker self.mounts = set() 22014833605d26bf970cd5335c02af4354b68d93348Doug Zongker 221c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AddToZip(self, input_zip, output_zip, input_path=None): 222c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Write the accumulated script to the output_zip file. input_zip 223c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker is used as the source for the 'updater' binary needed to run 224c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script. If input_path is not None, it will be used as a local 225c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker path for the binary instead of input_zip.""" 226c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 22714833605d26bf970cd5335c02af4354b68d93348Doug Zongker self.UnmountAll() 228c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 229c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker common.ZipWriteStr(output_zip, "META-INF/com/google/android/updater-script", 230c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker "\n".join(self.script) + "\n") 231c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 232c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if input_path is None: 233c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker data = input_zip.read("OTA/bin/updater") 234c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker else: 235c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker data = open(os.path.join(input_path, "updater")).read() 236c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-binary", 237c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker data, perms=0755) 238