Ejemplo n.º 1
0
    def ComputeAllPropertyFiles(input_file, needed_property_files):
        # Write the current metadata entry with placeholders.
        with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
            for property_files in needed_property_files:
                metadata.property_files[
                    property_files.name] = property_files.Compute(input_zip)
            namelist = input_zip.namelist()

        if METADATA_NAME in namelist or METADATA_PROTO_NAME in namelist:
            ZipDelete(input_file, [METADATA_NAME, METADATA_PROTO_NAME])
        output_zip = zipfile.ZipFile(input_file, 'a', allowZip64=True)
        WriteMetadata(metadata, output_zip)
        ZipClose(output_zip)

        if OPTIONS.no_signing:
            return input_file

        prelim_signing = MakeTempFile(suffix='.zip')
        SignOutput(input_file, prelim_signing)
        return prelim_signing
Ejemplo n.º 2
0
def FinalizeMetadata(metadata, input_file, output_file, needed_property_files):
    """Finalizes the metadata and signs an A/B OTA package.

  In order to stream an A/B OTA package, we need 'ota-streaming-property-files'
  that contains the offsets and sizes for the ZIP entries. An example
  property-files string is as follows.

    "payload.bin:679:343,payload_properties.txt:378:45,metadata:69:379"

  OTA server can pass down this string, in addition to the package URL, to the
  system update client. System update client can then fetch individual ZIP
  entries (ZIP_STORED) directly at the given offset of the URL.

  Args:
    metadata: The metadata dict for the package.
    input_file: The input ZIP filename that doesn't contain the package METADATA
        entry yet.
    output_file: The final output ZIP filename.
    needed_property_files: The list of PropertyFiles' to be generated.
  """
    def ComputeAllPropertyFiles(input_file, needed_property_files):
        # Write the current metadata entry with placeholders.
        with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
            for property_files in needed_property_files:
                metadata.property_files[
                    property_files.name] = property_files.Compute(input_zip)
            namelist = input_zip.namelist()

        if METADATA_NAME in namelist or METADATA_PROTO_NAME in namelist:
            ZipDelete(input_file, [METADATA_NAME, METADATA_PROTO_NAME])
        output_zip = zipfile.ZipFile(input_file, 'a', allowZip64=True)
        WriteMetadata(metadata, output_zip)
        ZipClose(output_zip)

        if OPTIONS.no_signing:
            return input_file

        prelim_signing = MakeTempFile(suffix='.zip')
        SignOutput(input_file, prelim_signing)
        return prelim_signing

    def FinalizeAllPropertyFiles(prelim_signing, needed_property_files):
        with zipfile.ZipFile(prelim_signing,
                             allowZip64=True) as prelim_signing_zip:
            for property_files in needed_property_files:
                metadata.property_files[
                    property_files.name] = property_files.Finalize(
                        prelim_signing_zip,
                        len(metadata.property_files[property_files.name]))

    # SignOutput(), which in turn calls signapk.jar, will possibly reorder the ZIP
    # entries, as well as padding the entry headers. We do a preliminary signing
    # (with an incomplete metadata entry) to allow that to happen. Then compute
    # the ZIP entry offsets, write back the final metadata and do the final
    # signing.
    prelim_signing = ComputeAllPropertyFiles(input_file, needed_property_files)
    try:
        FinalizeAllPropertyFiles(prelim_signing, needed_property_files)
    except PropertyFiles.InsufficientSpaceException:
        # Even with the preliminary signing, the entry orders may change
        # dramatically, which leads to insufficiently reserved space during the
        # first call to ComputeAllPropertyFiles(). In that case, we redo all the
        # preliminary signing works, based on the already ordered ZIP entries, to
        # address the issue.
        prelim_signing = ComputeAllPropertyFiles(prelim_signing,
                                                 needed_property_files)
        FinalizeAllPropertyFiles(prelim_signing, needed_property_files)

    # Replace the METADATA entry.
    ZipDelete(prelim_signing, [METADATA_NAME, METADATA_PROTO_NAME])
    output_zip = zipfile.ZipFile(prelim_signing, 'a', allowZip64=True)
    WriteMetadata(metadata, output_zip)
    ZipClose(output_zip)

    # Re-sign the package after updating the metadata entry.
    if OPTIONS.no_signing:
        output_file = prelim_signing
    else:
        SignOutput(prelim_signing, output_file)

    # Reopen the final signed zip to double check the streaming metadata.
    with zipfile.ZipFile(output_file, allowZip64=True) as output_zip:
        for property_files in needed_property_files:
            property_files.Verify(
                output_zip,
                metadata.property_files[property_files.name].strip())

    # If requested, dump the metadata to a separate file.
    output_metadata_path = OPTIONS.output_metadata_path
    if output_metadata_path:
        WriteMetadata(metadata, output_metadata_path)