Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1372206
  • 博文数量: 478
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4833
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-28 11:12
文章分类

全部博文(478)

文章存档

2019年(1)

2018年(27)

2017年(21)

2016年(171)

2015年(258)

我的朋友

分类: Android平台

2016-05-26 14:47:55

http://blog.csdn.net/huangyabin001/article/details/43763419

第一步:解压缩(ota_from_target_files)
[python] view plain copy

 print?
  1. print "unzipping target target-files..."  
  2. OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0])  
上面的代码是开始进行解压缩的入口
[python] view plain copy
 print?
  1. def UnzipTemp(filename, pattern=None):  
  2.   """Unzip the given archive into a temporary directory and return the name. 
  3.  
  4.   If filename is of the form "foo.zip+bar.zip", unzip foo.zip into a 
  5.   temp dir, then unzip bar.zip into that_dir/BOOTABLE_IMAGES. 
  6.  
  7.   Returns (tempdir, zipobj) where zipobj is a zipfile.ZipFile (of the 
  8.   main file), open for reading. 
  9.   """  
  10.   # 该函数用于创建一个临时文件夹,参数指的是临时文件夹的前缀,返回值tmp是临时文件夹的绝对路径,并赋给OPTIONS的tempfiles属性  
  11.   tmp = tempfile.mkdtemp(prefix="targetfiles-")  
  12.   OPTIONS.tempfiles.append(tmp)  
  13.   
  14.   def unzip_to_dir(filename, dirname):  
  15.     #这里设置了一个变量名cmd的数组,里面存放的是需要执行的命令和参数,这个命令也就是“unzip -o -q filename -d dirname”  
  16.     cmd = ["unzip""-o""-q", filename, "-d", dirname]  
  17.     if pattern is not None:  
  18.       cmd.append(pattern)  
  19.     #这里调用了Run方法  
  20.     p = Run(cmd, stdout=subprocess.PIPE)  
  21.     """Popen.communicate(input=None)与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata,stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。"""  
  22.     p.communicate()  
  23.     if p.returncode != 0:  
  24.       raise ExternalError("failed to unzip input target-files \"%s\"" %  
  25.                           (filename,))  
  26.   #match :只从字符串的开始与正则表达式匹配,匹配成功返回所匹配的项,否则返回none;  
  27.   m = re.match(r"^(.*[.]zip)\+(.*[.]zip)$", filename, re.IGNORECASE)  
  28.   #如果这里加上并执行"""print m"""语句的话,结果为"""[target.zip]"""  
  29.   if m:  
  30.     unzip_to_dir(m.group(1), tmp)  
  31.     unzip_to_dir(m.group(2), os.path.join(tmp, "BOOTABLE_IMAGES"))  
  32.     filename = m.group(1)  
  33.   else:  
  34.     #这里执行解压操作,文件名的值为"target.zip",tem的值为"/tmp/targetfiles-fEX9aH",并且调用upzip_to_dir方法来执行解压缩命令  
  35.     unzip_to_dir(filename, tmp)  
  36.   
  37.   #这里返回临时路径和存储了zipfile内容的变量  
  38.   # 这里的第二个参数用r表示是读取zip文件,w是创建一个zip文件  
  39.   return tmp, zipfile.ZipFile(filename, "r")  
#这里开启新的进程来执行解压缩的命令
[python] view plain copy
 print?
  1. def Run(args, **kwargs):  
  2.   """Create and return a subprocess.Popen object, printing the command 
  3.   line on the terminal if -v was specified."""  
  4.   if OPTIONS.verbose:  
  5.     print "  running: "" ".join(args)  
  6.   """这里调用Popen模块开启新的进程用来执行系统命令,这种方式可运用对进程的控制,将返回结果复制给变量,更方便去处理。args的值实际上是一个list,用于指定进程的可执行文件及其参数。"""  
  7.   return subprocess.Popen(args, **kwargs)  
接着回到main函数中对解压缩返回的结果进行处理



[python] view plain copy
 print?
  1. OPTIONS.target_tmp = OPTIONS.input_tmp  
  2. OPTIONS.info_dict = common.LoadInfoDict(input_zip)  
第二步,解析target.zip中META/misc_info.txt、imagesizes.txt中的信息,如下图:


这是misc_info.txt中的内容:


[python] view plain copy
 print?
  1. recovery_api_version=3  
  2. fstab_version=2  
  3. tool_extensions=out/target/product/wt98360/obj/CUSTGEN/config/../common  
  4. default_system_dev_certificate=build/target/product/security/testkey  
  5. mkbootimg_args=  
  6. use_set_metadata=1  
  7. update_rename_support=1  
  8. fs_type=ext4  
  9. system_size=1363148800  
  10. userdata_size=1152385024  
  11. cache_size=132120576  
  12. extfs_sparse_flag=-s  
  13. mkyaffs2_extra_flags=-c 2048 -s 64     
  14. selinux_fc=out/target/product/wt98360/root/file_contexts  


具体代码如下:

[python] view plain copy
 print?
  1. def LoadInfoDict(zip):  
  2.   """Read and parse the META/misc_info.txt key/value pairs from the 
  3.   input target files and return a dict."""  
  4.   #定义一个字典变量用于存储处理后的信息  
  5.   d = {}  
  6.   try:  
  7.     #这里zip.read()方法打开update.zip中的META/misc_info.txt,并按"\n"进行切片  
  8.     for line in zip.read("META/misc_info.txt").split("\n"):  
  9.       line = line.strip()#用于移除字符串头尾指定的字符(默认为空格)  
  10.       if not line or line.startswith("#"): continue#跳过注释信息  
  11.       k, v = line.split("="1)#这里按照第一个"="进行切片  
  12.       d[k] = v#封装成数据字典  
  13.   except KeyError:  
  14.     # ok if misc_info.txt doesn't exist  
  15.     pass  
  16.   
  17.   # backwards compatibility: These values used to be in their own  
  18.   # files.  Look for them, in case we're processing an old  
  19.   # target_files zip.  
  20.   
  21.   if "mkyaffs2_extra_flags" not in d:  
  22.     try:  
  23.       d["mkyaffs2_extra_flags"] = zip.read("META/mkyaffs2-extra-flags.txt").strip()  
  24.     except KeyError:  
  25.       # ok if flags don't exist  
  26.       pass  
  27.   
  28.   if "recovery_api_version" not in d:  
  29.     try:  
  30.       d["recovery_api_version"] = zip.read("META/recovery-api-version.txt").strip()  
  31.     except KeyError:  
  32.       raise ValueError("can't find recovery API version in input target-files")  
  33.   
  34.   if "tool_extensions" not in d:  
  35.     try:  
  36.       d["tool_extensions"] = zip.read("META/tool-extensions.txt").strip()  
  37.     except KeyError:  
  38.       # ok if extensions don't exist  
  39.       pass  
  40.   
  41.   if "fstab_version" not in d:  
  42.     d["fstab_version"] = "1"  
  43.   
  44.   try:  
  45.     data = zip.read("META/imagesizes.txt")  
  46.     for line in data.split("\n"):  
  47.       if not line: continue  
  48.       name, value = line.split(" "1)  
  49.       if not value: continue  
  50.       if name == "blocksize":  
  51.         d[name] = value  
  52.       else:  
  53.         d[name + "_size"] = value  
  54.   except KeyError:  
  55.     pass  
  56.   
  57.   def makeint(key):  
  58.     if key in d:  
  59.       if d[key].endswith('M'):  
  60.         d[key] = d[key].split("M")[0]  
  61.         d[key] = int(d[key], 0) * 1024 * 1024  
  62.       else:  
  63.         d[key] = int(d[key], 0)  
  64.   
  65.   makeint("recovery_api_version")  
  66.   makeint("blocksize")  
  67.   makeint("system_size")  
  68.   makeint("userdata_size")  
  69.   makeint("cache_size")  
  70.   makeint("recovery_size")  
  71.   makeint("boot_size")  
  72.   makeint("fstab_version")  
  73.   #wschen 2012-11-07   
  74.   makeint("custom_size")  
  75.   
  76.   
  77.   d["fstab"] = LoadRecoveryFSTab(zip, d["fstab_version"])  
  78.   d["build.prop"] = LoadBuildProp(zip)  
  79.   return d  


上面的代码中,在方法的末尾有分别去解析了分区表和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属性信息,将解析的属性信息保存为一个数据字典,并返回


[python] view plain copy
 print?
  1. def LoadBuildProp(zip):  
  2.   try:  
  3.     data = zip.read("SYSTEM/build.prop")  
  4.   except KeyError:  
  5.     print "Warning: could not find SYSTEM/build.prop in %s" % zip  
  6.     data = ""  
  7.   
  8.   d = {}  
  9.   for line in data.split("\n"):  
  10.     line = line.strip()  
  11.     if not line or line.startswith("#"): continue  
  12.     name, value = line.split("="1)  
  13.     d[name] = value  
  14.   return d  
阅读(2290) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~