def _ApplyOperations(self, operations, base_name, old_part_file,
                         new_part_file, part_size):
        """Applies a sequence of update operations to a partition.

    Args:
      operations: the sequence of operations
      base_name: the name of the operation sequence
      old_part_file: the old partition file object, open for reading/writing
      new_part_file: the new partition file object, open for reading/writing
      part_size: the partition size

    Raises:
      PayloadError if anything goes wrong while processing the payload.
    """
        for op, op_name in common.OperationIter(operations, base_name):
            # Read data blob.
            data = self.payload.ReadDataBlob(op.data_offset, op.data_length)

            if op.type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ,
                           common.OpType.REPLACE_XZ):
                self._ApplyReplaceOperation(op, op_name, data, new_part_file,
                                            part_size)
            elif op.type == common.OpType.ZERO:
                self._ApplyZeroOperation(op, op_name, new_part_file)
            elif op.type == common.OpType.SOURCE_COPY:
                self._ApplySourceCopyOperation(op, op_name, old_part_file,
                                               new_part_file)
            elif op.type in (common.OpType.SOURCE_BSDIFF,
                             common.OpType.PUFFDIFF,
                             common.OpType.BROTLI_BSDIFF):
                self._ApplyDiffOperation(op, op_name, data, old_part_file,
                                         new_part_file)
            else:
                raise PayloadError('%s: unknown operation type (%d)' %
                                   (op_name, op.type))
Exemplo n.º 2
0
  def _TraceBlock(block, skip, trace_out_file, operations, base_name):
    """Trace the origin of a given block through a sequence of operations.

    This method tries to map the given dest block to the corresponding source
    block from which its content originates in the course of an update. It
    further tries to trace transitive origins through MOVE operations. It is
    rather efficient, doing the actual tracing by means of a single reverse
    sweep through the operation sequence. It dumps a log of operations and
    source blocks responsible for the data in the given dest block to the
    provided output file.

    Args:
      block: the block number to trace
      skip: number of initial transitive origins to ignore
      trace_out_file: a file object to dump the trace to
      operations: the sequence of operations
      base_name: name of the operation sequence
    """
    # Traverse operations backwards.
    for op, op_name in common.OperationIter(operations, base_name,
                                            reverse=True):
      total_block_offset = 0
      found = False

      # Is the traced block mentioned in the dest extents?
      for dst_ex, dst_ex_name in common.ExtentIter(op.dst_extents,
                                                   op_name + '.dst_extents'):
        if (block >= dst_ex.start_block
            and block < dst_ex.start_block + dst_ex.num_blocks):
          if skip:
            skip -= 1
          else:
            total_block_offset += block - dst_ex.start_block
            trace_out_file.write(
                '%d: %s: found %s (total block offset: %d)\n' %
                (block, dst_ex_name, common.FormatExtent(dst_ex),
                 total_block_offset))
            found = True
            break

        total_block_offset += dst_ex.num_blocks

      if found:
        # Don't trace further, unless it's a MOVE.
        if op.type != common.OpType.MOVE:
          break

        # For MOVE, find corresponding source block and keep tracing.
        for src_ex, src_ex_name in common.ExtentIter(op.src_extents,
                                                     op_name + '.src_extents'):
          if total_block_offset < src_ex.num_blocks:
            block = src_ex.start_block + total_block_offset
            trace_out_file.write(
                '%s:  mapped to %s (%d)\n' %
                (src_ex_name, common.FormatExtent(src_ex), block))
            break

          total_block_offset -= src_ex.num_blocks