android ota解包函数,Android OTA升级包制作脚本详解(二,解压缩)

http://blog.youkuaiyun.com/huangyabin001/article/details/43763419

第一步:解压缩(ota_from_target_files)

[python]view plain

print"unzipping target target-files..."

OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0])

上面的代码是开始进行解压缩的入口

defUnzipTemp(filename, pattern=None):

"""Unzip the given archive into a temporary directory and return the name.

If filename is of the form "foo.zip+bar.zip", unzip foo.zip into a

temp dir, then unzip bar.zip into that_dir/BOOTABLE_IMAGES.

Returns (tempdir, zipobj) where zipobj is a zipfile.ZipFile (of the

main file), open for reading.

"""

# 该函数用于创建一个临时文件夹,参数指的是临时文件夹的前缀,返回值tmp是临时文件夹的绝对路径,并赋给OPTIONS的tempfiles属性

tmp = tempfile.mkdtemp(prefix="targetfiles-")

OPTIONS.tempfiles.append(tmp)

defunzip_to_dir(filename, dirname):

#这里设置了一个变量名cmd的数组,里面存放的是需要执行的命令和参数,这个命令也就是“unzip -o -q filename -d dirname”

cmd = ["unzip","-o","-q", filename,"-d", dirname]

ifpatternisnotNone:

cmd.append(pattern)

#这里调用了Run方法

p = Run(cmd, stdout=subprocess.PIPE)

"""Popen.communicate(input=None)与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata,stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。"""

p.communicate()

ifp.returncode !=0:

raiseExternalError("failed to unzip input target-files \"%s\""%

(filename,))

#match :只从字符串的开始与正则表达式匹配,匹配成功返回所匹配的项,否则返回none;

m = re.match(r"^(.*[.]zip)\+(.*[.]zip)$", filename, re.IGNORECASE)

#如果这里加上并执行"""print m"""语句的话,结果为"""[target.zip]"""

ifm:

unzip_to_dir(m.group(1), tmp)

unzip_to_dir(m.group(2), os.path.join(tmp,"BOOTABLE_IMAGES"))

filename = m.group(1)

else:

#这里执行解压操作,文件名的值为"target.zip",tem的值为"/tmp/targetfiles-fEX9aH",并且调用upzip_to_dir方法来执行解压缩命令

unzip_to_dir(filename, tmp)

#这里返回临时路径和存储了zipfile内容的变量

# 这里的第二个参数用r表示是读取zip文件,w是创建一个zip文件

returntmp, zipfile.ZipFile(filename,"r")

#这里开启新的进程来执行解压缩的命令

defRun(args, **kwargs):

"""Create and return a subprocess.Popen object, printing the command

line on the terminal if -v was specified."""

ifOPTIONS.verbose:

print"  running: "," ".join(args)

"""这里调用Popen模块开启新的进程用来执行系统命令,这种方式可运用对进程的控制,将返回结果复制给变量,更方便去处理。args的值实际上是一个list,用于指定进程的可执行文件及其参数。"""

returnsubprocess.Popen(args, **kwargs)

接着回到main函数中对解压缩返回的结果进行处理

OPTIONS.target_tmp = OPTIONS.input_tmp

OPTIONS.info_dict = common.LoadInfoDict(input_zip)

第二步,解析target.zip中META/misc_info.txt、imagesizes.txt中的信息,如下图:

f92b20e1170a91b1ca2795cb91931f74.png

这是misc_info.txt中的内容:

recovery_api_version=3

fstab_version=2

tool_extensions=out/target/product/wt98360/obj/CUSTGEN/config/../common

default_system_dev_certificate=build/target/product/security/testkey

mkbootimg_args=

use_set_metadata=1

update_rename_support=1

fs_type=ext4

system_size=1363148800

userdata_size=1152385024

cache_size=132120576

extfs_sparse_flag=-s

mkyaffs2_extra_flags=-c 2048-s64

selinux_fc=out/target/product/wt98360/root/file_contexts

具体代码如下:

defLoadInfoDict(zip):

"""Read and parse the META/misc_info.txt key/value pairs from the

input target files and return a dict."""

#定义一个字典变量用于存储处理后的信息

d = {}

try:

#这里zip.read()方法打开update.zip中的META/misc_info.txt,并按"\n"进行切片

forlineinzip.read("META/misc_info.txt").split("\n"):

line = line.strip()#用于移除字符串头尾指定的字符(默认为空格)

ifnotlineorline.startswith("#"):continue#跳过注释信息

k, v = line.split("=",1)#这里按照第一个"="进行切片

d[k] = v#封装成数据字典

exceptKeyError:

# ok if misc_info.txt doesn't exist

pass

# backwards compatibility: These values used to be in their own

# files.  Look for them, in case we're processing an old

# target_files zip.

if"mkyaffs2_extra_flags"notind:

try:

d["mkyaffs2_extra_flags"] = zip.read("META/mkyaffs2-extra-flags.txt").strip()

exceptKeyError:

# ok if flags don't exist

pass

if"recovery_api_version"notind:

try:

d["recovery_api_version"] = zip.read("META/recovery-api-version.txt").strip()

exceptKeyError:

raiseValueError("can't find recovery API version in input target-files")

if"tool_extensions"notind:

try:

d["tool_extensions"] = zip.read("META/tool-extensions.txt").strip()

exceptKeyError:

# ok if extensions don't exist

pass

if"fstab_version"notind:

d["fstab_version"] ="1"

try:

data = zip.read("META/imagesizes.txt")

forlineindata.split("\n"):

ifnotline:continue

name, value = line.split(" ",1)

ifnotvalue:continue

ifname =="blocksize":

d[name] = value

else:

d[name + "_size"] = value

exceptKeyError:

pass

defmakeint(key):

ifkeyind:

ifd[key].endswith('M'):

d[key] = d[key].split("M")[0]

d[key] = int(d[key], 0) *1024*1024

else:

d[key] = int(d[key], 0)

makeint("recovery_api_version")

makeint("blocksize")

makeint("system_size")

makeint("userdata_size")

makeint("cache_size")

makeint("recovery_size")

makeint("boot_size")

makeint("fstab_version")

#wschen 2012-11-07

makeint("custom_size")

d["fstab"] = LoadRecoveryFSTab(zip, d["fstab_version"])

d["build.prop"] = LoadBuildProp(zip)

returnd

上面的代码中,在方法的末尾有分别去解析了分区表和Build属性,那么具体的操作流程,我们下面进行详细的分析

第三步,解析recovery分区信息

这里fastab_version的版本是2,因此

def LoadRecoveryFSTab(zip, fstab_version):

class Partition(object):

pass

try:

data = zip.read("RECOVERY/RAMDISK/etc/recovery.fstab")#当前target.zip中并没有这文件,因此这里暂不作详解

except KeyError:

print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab in %s." % zip

data = ""

if fstab_version == 1:

d = {}

for line in data.split("\n"):

line = line.strip()

if not line or line.startswith("#"): continue

pieces = line.split()

if not (3 <= len(pieces) <= 4):

raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))

p = Partition()

p.mount_point = pieces[0]

p.fs_type = pieces[1]

p.device = pieces[2]

p.length = 0

options = None

if len(pieces) >= 4:

if pieces[3].startswith("/"):

p.device2 = pieces[3]

if len(pieces) >= 5:

options = pieces[4]

else:

p.device2 = None

options = pieces[3]

else:

p.device2 = None

if options:

options = options.split(",")

for i in options:

if i.startswith("length="):

p.length = int(i[7:])

else:

print "%s: unknown option \"%s\"" % (p.mount_point, i)

d[p.mount_point] = p

elif fstab_version == 2:

d = {}

for line in data.split("\n"):

line = line.strip()

if not line or line.startswith("#"): continue

pieces = line.split()

if len(pieces) != 5:

raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))

# Ignore entries that are managed by vold

options = pieces[4]

if "voldmanaged=" in options: continue

# It's a good line, parse it

p = Partition()

p.device = pieces[0]

p.mount_point = pieces[1]

p.fs_type = pieces[2]

p.device2 = None

p.length = 0

options = options.split(",")

for i in options:

if i.startswith("length="):

p.length = int(i[7:])

else:

# Ignore all unknown options in the unified fstab

continue

d[p.mount_point] = p

else:

raise ValueError("Unknown fstab_version: \"%d\"" % (fstab_version,))

return d

第四步,解析SYSTEM/build.prop属性信息,将解析的属性信息保存为一个数据字典,并返回

defLoadBuildProp(zip):

try:

data = zip.read("SYSTEM/build.prop")

exceptKeyError:

print"Warning: could not find SYSTEM/build.prop in %s"% zip

data = ""

d = {}

forlineindata.split("\n"):

line = line.strip()

ifnotlineorline.startswith("#"):continue

name, value = line.split("=",1)

d[name] = value

returnd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值