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 24b4c7d32cbac0ef36062c4e2f348b47e027610eefDoug Zongker def __init__(self, version, info): 25c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script = [] 26c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.mounts = set() 27c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.version = version 28b4c7d32cbac0ef36062c4e2f348b47e027610eefDoug Zongker self.info = info 29c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 30c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def MakeTemporary(self): 31c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Make a temporary script object whose commands can latter be 32c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker appended to the parent script with AppendScript(). Used when the 33c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker caller wants to generate script commands out-of-order.""" 3467369983cf23e12724c135c3850c98326558256bDoug Zongker x = EdifyGenerator(self.version, self.info) 35c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker x.mounts = self.mounts 36c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker return x 37c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 38c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker @staticmethod 39c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def _WordWrap(cmd, linelen=80): 40c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """'cmd' should be a function call with null characters after each 41c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker parameter (eg, "somefun(foo,\0bar,\0baz)"). This function wraps cmd 42c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker to a given line length, replacing nulls with spaces and/or newlines 43c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker to format it nicely.""" 44c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker indent = cmd.index("(")+1 45c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker out = [] 46c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker first = True 47c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker x = re.compile("^(.{,%d})\0" % (linelen-indent,)) 48c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker while True: 49c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if not first: 50c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker out.append(" " * indent) 51c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker first = False 52c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker m = x.search(cmd) 53c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if not m: 54c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker parts = cmd.split("\0", 1) 55c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker out.append(parts[0]+"\n") 56c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if len(parts) == 1: 57c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker break 58c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker else: 59c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = parts[1] 60c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker continue 61c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker out.append(m.group(1)+"\n") 62c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = cmd[m.end():] 63c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 64c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker return "".join(out).replace("\0", " ").rstrip("\n") 65c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 66c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AppendScript(self, other): 67c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Append the contents of another script (which should be created 68c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker with temporary=True) to this one.""" 69c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.extend(other.script) 70c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 71c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AssertSomeFingerprint(self, *fp): 72c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Assert that the current system build fingerprint is one of *fp.""" 73c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if not fp: 74c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker raise ValueError("must specify some fingerprints") 750d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker cmd = ( 760d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker ' ||\n '.join([('file_getprop("/system/build.prop", ' 77c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker '"ro.build.fingerprint") == "%s"') 78c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker % i for i in fp]) + 790d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker ' ||\n abort("Package expects build fingerprint of %s; this ' 800d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker 'device has " + getprop("ro.build.fingerprint") + ".");' 810d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker ) % (" or ".join(fp),) 820d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker self.script.append(cmd) 83c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 840d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker def AssertOlderBuild(self, timestamp, timestamp_text): 85c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Assert that the build on the device is older (or the same as) 86c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker the given timestamp.""" 870d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker self.script.append( 880d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker ('(!less_than_int(%s, getprop("ro.build.date.utc"))) || ' 890d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker 'abort("Can\'t install this package (%s) over newer ' 900d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker 'build (" + getprop("ro.build.date") + ").");' 910d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker ) % (timestamp, timestamp_text)) 92c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 93c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AssertDevice(self, device): 94c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Assert that the device identifier is the given string.""" 950d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker cmd = ('getprop("ro.product.device") == "%s" || ' 960d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker 'abort("This package is for \\"%s\\" devices; ' 970d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker 'this is a \\"" + getprop("ro.product.device") + "\\".");' 980d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker ) % (device, device) 990d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker self.script.append(cmd) 100c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 101c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AssertSomeBootloader(self, *bootloaders): 102c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Asert that the bootloader version is one of *bootloaders.""" 103c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = ("assert(" + 104c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker " ||\0".join(['getprop("ro.bootloader") == "%s"' % (b,) 105c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for b in bootloaders]) + 106c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ");") 107c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 108c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 109c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def ShowProgress(self, frac, dur): 110c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Update the progress bar, advancing it over 'frac' over the next 111881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker 'dur' seconds. 'dur' may be zero to advance it via SetProgress 112881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker commands instead of by time.""" 113c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append("show_progress(%f, %d);" % (frac, int(dur))) 114c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 115881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker def SetProgress(self, frac): 116881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker """Set the position of the progress bar within the chunk defined 117881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker by the most recent ShowProgress call. 'frac' should be in 118881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker [0,1].""" 119881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker self.script.append("set_progress(%f);" % (frac,)) 120881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker 121c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def PatchCheck(self, filename, *sha1): 122c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Check that the given file (or MTD reference) has one of the 123c8d446bcde877ec94f8e68dd5af68fe34eb1b1f9Doug Zongker given *sha1 hashes, checking the version saved in cache if the 124c8d446bcde877ec94f8e68dd5af68fe34eb1b1f9Doug Zongker file does not match.""" 1250d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker self.script.append( 1260d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker 'apply_patch_check("%s"' % (filename,) + 1270d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker "".join([', "%s"' % (i,) for i in sha1]) + 1280d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker ') || abort("\\"%s\\" has unexpected contents.");' % (filename,)) 129c8d446bcde877ec94f8e68dd5af68fe34eb1b1f9Doug Zongker 130c8d446bcde877ec94f8e68dd5af68fe34eb1b1f9Doug Zongker def FileCheck(self, filename, *sha1): 131c8d446bcde877ec94f8e68dd5af68fe34eb1b1f9Doug Zongker """Check that the given file (or MTD reference) has one of the 132c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker given *sha1 hashes.""" 1335a48209541d5eed602bfb8e2c4ff51e31443daf2Doug Zongker self.script.append('assert(sha1_check(read_file("%s")' % (filename,) + 134c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker "".join([', "%s"' % (i,) for i in sha1]) + 135c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker '));') 136c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 137c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def CacheFreeSpaceCheck(self, amount): 138c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Check that there's at least 'amount' space that can be made 139c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker available on /cache.""" 1400d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker self.script.append(('apply_patch_space(%d) || abort("Not enough free space ' 1410d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker 'on /system to apply patches.");') % (amount,)) 142c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 1439ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker def Mount(self, mount_point): 1449ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker """Mount the partition with the given mount_point.""" 1459ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker fstab = self.info.get("fstab", None) 1469ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker if fstab: 1479ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker p = fstab[mount_point] 1489ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker self.script.append('mount("%s", "%s", "%s", "%s");' % 14996a57e737707d05333dced5b657c4ef21c44088aDoug Zongker (p.fs_type, common.PARTITION_TYPES[p.fs_type], 1509ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker p.device, p.mount_point)) 1519ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker self.mounts.add(p.mount_point) 152c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 153c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def UnpackPackageDir(self, src, dst): 154c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Unpack a given directory from the OTA package into the given 155c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker destination directory.""" 156c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append('package_extract_dir("%s", "%s");' % (src, dst)) 157c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 158c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def Comment(self, comment): 159c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Write a comment into the update script.""" 160c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append("") 161c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for i in comment.split("\n"): 162c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append("# " + i) 163c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append("") 164c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 165c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def Print(self, message): 166c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Log a message to the screen (if the logs are visible).""" 167c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append('ui_print("%s");' % (message,)) 168c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 169c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def FormatPartition(self, partition): 1709ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker """Format the given partition, specified by its mount point (eg, 1719ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker "/system").""" 1729ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker 173a67616acfd436ac0ba224e675dc972c8491901fcKen Sumrall reserve_size = 0 1749ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker fstab = self.info.get("fstab", None) 1759ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker if fstab: 1769ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker p = fstab[partition] 177df2056e29e557a493ec8057628ca640b98e54823Doug Zongker self.script.append('format("%s", "%s", "%s", "%s", "%s");' % 178086cbb0acb873603c19101b1fc01d125d8b63b7aDoug Zongker (p.fs_type, common.PARTITION_TYPES[p.fs_type], 179df2056e29e557a493ec8057628ca640b98e54823Doug Zongker p.device, p.length, p.mount_point)) 180c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 181c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def DeleteFiles(self, file_list): 182c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Delete all files in file_list.""" 183c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if not file_list: return 184c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = "delete(" + ",\0".join(['"%s"' % (i,) for i in file_list]) + ");" 185c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 186c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 187c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs): 188c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Apply binary patches (in *patchpairs) to the given srcfile to 189c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker produce tgtfile (which may be "-" to indicate overwriting the 190c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker source file.""" 191c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if len(patchpairs) % 2 != 0 or len(patchpairs) == 0: 192c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker raise ValueError("bad patches given to ApplyPatch") 193c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = ['apply_patch("%s",\0"%s",\0%s,\0%d' 194c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker % (srcfile, tgtfile, tgtsha1, tgtsize)] 195c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for i in range(0, len(patchpairs), 2): 196c8d446bcde877ec94f8e68dd5af68fe34eb1b1f9Doug Zongker cmd.append(',\0%s, package_extract_file("%s")' % patchpairs[i:i+2]) 197c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd.append(');') 198c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = "".join(cmd) 199c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 200c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 2019ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker def WriteRawImage(self, mount_point, fn): 2029ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker """Write the given package file into the partition for the given 2039ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker mount point.""" 204b4c7d32cbac0ef36062c4e2f348b47e027610eefDoug Zongker 2059ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker fstab = self.info["fstab"] 2069ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker if fstab: 2079ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker p = fstab[mount_point] 20896a57e737707d05333dced5b657c4ef21c44088aDoug Zongker partition_type = common.PARTITION_TYPES[p.fs_type] 2099ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker args = {'device': p.device, 'fn': fn} 2109ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker if partition_type == "MTD": 2119ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker self.script.append( 21202da210a5cb4f9cdc7320885484499856236e5a4Doug Zongker 'write_raw_image(package_extract_file("%(fn)s"), "%(device)s");' 21302da210a5cb4f9cdc7320885484499856236e5a4Doug Zongker % args) 2149ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker elif partition_type == "EMMC": 2159ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker self.script.append( 2169ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker 'package_extract_file("%(fn)s", "%(device)s");' % args) 2179ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker else: 2189ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker raise ValueError("don't know how to write \"%s\" partitions" % (p.fs_type,)) 219c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 2200eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich def SetPermissions(self, fn, uid, gid, mode, selabel, capabilities): 221c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Set file ownership and permissions.""" 2220eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if not self.info.get("use_set_metadata", False): 2230eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich self.script.append('set_perm(%d, %d, 0%o, "%s");' % (uid, gid, mode, fn)) 2240eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich else: 2250eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if capabilities is None: capabilities = "0x0" 2260eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich cmd = 'set_metadata("%s", "uid", %d, "gid", %d, "mode", 0%o, ' \ 2270eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich '"capabilities", %s' % (fn, uid, gid, mode, capabilities) 2280eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if selabel is not None: 2290eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich cmd += ', "selabel", "%s"' % ( selabel ) 2300eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich cmd += ');' 2310eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich self.script.append(cmd) 232c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 2330eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode, selabel, capabilities): 234c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Recursively set path ownership and permissions.""" 2350eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if not self.info.get("use_set_metadata", False): 2360eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich self.script.append('set_perm_recursive(%d, %d, 0%o, 0%o, "%s");' 2370eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich % (uid, gid, dmode, fmode, fn)) 2380eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich else: 2390eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if capabilities is None: capabilities = "0x0" 2400eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich cmd = 'set_metadata_recursive("%s", "uid", %d, "gid", %d, ' \ 2410eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich '"dmode", 0%o, "fmode", 0%o, "capabilities", %s' \ 2420eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich % (fn, uid, gid, dmode, fmode, capabilities) 2430eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if selabel is not None: 2440eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich cmd += ', "selabel", "%s"' % ( selabel ) 2450eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich cmd += ');' 2460eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich self.script.append(cmd) 247c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 248c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def MakeSymlinks(self, symlink_list): 249c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Create symlinks, given a list of (dest, link) pairs.""" 250c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker by_dest = {} 251c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for d, l in symlink_list: 252c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker by_dest.setdefault(d, []).append(l) 253c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 254c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker for dest, links in sorted(by_dest.iteritems()): 255c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker cmd = ('symlink("%s", ' % (dest,) + 256c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker ",\0".join(['"' + i + '"' for i in sorted(links)]) + ");") 257c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(self._WordWrap(cmd)) 258c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 259c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AppendExtra(self, extra): 260c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Append text verbatim to the output script.""" 261c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker self.script.append(extra) 262c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 26314833605d26bf970cd5335c02af4354b68d93348Doug Zongker def UnmountAll(self): 26414833605d26bf970cd5335c02af4354b68d93348Doug Zongker for p in sorted(self.mounts): 26514833605d26bf970cd5335c02af4354b68d93348Doug Zongker self.script.append('unmount("%s");' % (p,)) 26614833605d26bf970cd5335c02af4354b68d93348Doug Zongker self.mounts = set() 26714833605d26bf970cd5335c02af4354b68d93348Doug Zongker 268c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def AddToZip(self, input_zip, output_zip, input_path=None): 269c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker """Write the accumulated script to the output_zip file. input_zip 270c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker is used as the source for the 'updater' binary needed to run 271c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script. If input_path is not None, it will be used as a local 272c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker path for the binary instead of input_zip.""" 273c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 27414833605d26bf970cd5335c02af4354b68d93348Doug Zongker self.UnmountAll() 275c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 276c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker common.ZipWriteStr(output_zip, "META-INF/com/google/android/updater-script", 277c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker "\n".join(self.script) + "\n") 278c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 279c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker if input_path is None: 280c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker data = input_zip.read("OTA/bin/updater") 281c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker else: 282c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker data = open(os.path.join(input_path, "updater")).read() 283c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-binary", 284c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker data, perms=0755) 285