Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 344c8eb4 authored by Tao Bao's avatar Tao Bao Committed by Gerrit Code Review
Browse files

Merge "Add tests for imgdiff."

parents f24d2a6b 97555da4
Loading
Loading
Loading
Loading
+69 −21
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ LOCAL_PATH := $(call my-dir)
# libapplypatch (static library)
# ===============================
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_SRC_FILES := \
    applypatch.cpp \
    bspatch.cpp \
@@ -26,11 +25,11 @@ LOCAL_SRC_FILES := \
    utils.cpp
LOCAL_MODULE := libapplypatch
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += \
LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/include \
    bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES += \
LOCAL_STATIC_LIBRARIES := \
    libotafault \
    libbase \
    libcrypto \
@@ -42,36 +41,45 @@ include $(BUILD_STATIC_LIBRARY)
# libimgpatch (static library)
# ===============================
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp
LOCAL_SRC_FILES := \
    bspatch.cpp \
    imgpatch.cpp \
    utils.cpp
LOCAL_MODULE := libimgpatch
LOCAL_C_INCLUDES += \
LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/include \
    bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES += libcrypto libbz libz
LOCAL_STATIC_LIBRARIES := \
    libcrypto \
    libbz \
    libz
LOCAL_CFLAGS := -Werror
include $(BUILD_STATIC_LIBRARY)

# libimgpatch (host static library)
# ===============================
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp
LOCAL_SRC_FILES := \
    bspatch.cpp \
    imgpatch.cpp \
    utils.cpp
LOCAL_MODULE := libimgpatch
LOCAL_MODULE_HOST_OS := linux
LOCAL_C_INCLUDES += \
LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/include \
    bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES += libcrypto libbz libz
LOCAL_STATIC_LIBRARIES := \
    libcrypto \
    libbz \
    libz
LOCAL_CFLAGS := -Werror
include $(BUILD_HOST_STATIC_LIBRARY)

# libapplypatch_modes (static library)
# ===============================
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_SRC_FILES := \
    applypatch_modes.cpp
LOCAL_MODULE := libapplypatch_modes
@@ -87,7 +95,6 @@ include $(BUILD_STATIC_LIBRARY)
# applypatch (target executable)
# ===============================
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_SRC_FILES := applypatch_main.cpp
LOCAL_MODULE := applypatch
LOCAL_C_INCLUDES := bootable/recovery
@@ -106,18 +113,59 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_CFLAGS := -Werror
include $(BUILD_EXECUTABLE)

libimgdiff_src_files := \
    imgdiff.cpp \
    utils.cpp

# libbsdiff is compiled with -D_FILE_OFFSET_BITS=64.
libimgdiff_cflags := \
    -Werror \
    -D_FILE_OFFSET_BITS=64

libimgdiff_static_libraries := \
    libbsdiff \
    libz

# libimgdiff (static library)
# ===============================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
    $(libimgdiff_src_files)
LOCAL_MODULE := libimgdiff
LOCAL_CFLAGS := \
    $(libimgdiff_cflags)
LOCAL_STATIC_LIBRARIES := \
    $(libimgdiff_static_libraries)
LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
include $(BUILD_STATIC_LIBRARY)

# libimgdiff (host static library)
# ===============================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
    $(libimgdiff_src_files)
LOCAL_MODULE := libimgdiff
LOCAL_CFLAGS := \
    $(libimgdiff_cflags)
LOCAL_STATIC_LIBRARIES := \
    $(libimgdiff_static_libraries)
LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
include $(BUILD_HOST_STATIC_LIBRARY)

# imgdiff (host static executable)
# ===============================
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_SRC_FILES := imgdiff.cpp utils.cpp
LOCAL_SRC_FILES := imgdiff_main.cpp
LOCAL_MODULE := imgdiff
LOCAL_STATIC_LIBRARIES += \
    libbsdiff \
LOCAL_CFLAGS := -Werror
LOCAL_STATIC_LIBRARIES := \
    libimgdiff \
    $(libimgdiff_static_libraries) \
    libbz \
    libdivsufsort64 \
    libdivsufsort \
    libz
LOCAL_CFLAGS := -Werror
LOCAL_FORCE_STATIC_EXECUTABLE := true
    libdivsufsort64
include $(BUILD_HOST_EXECUTABLE)
+24 −30
Original line number Diff line number Diff line
@@ -121,19 +121,19 @@
 * information that is stored on the system partition.
 */

#include "applypatch/imgdiff.h"

#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>

#include <bsdiff.h>
#include <zlib.h>

#include "zlib.h"
#include "imgdiff.h"
#include "utils.h"

typedef struct {
@@ -374,8 +374,7 @@ unsigned char* ReadZip(const char* filename,
 * return value when done with all the chunks.  Returns NULL on
 * failure.
 */
unsigned char* ReadImage(const char* filename,
                         int* num_chunks, ImageChunk** chunks) {
unsigned char* ReadImage(const char* filename, int* num_chunks, ImageChunk** chunks) {
  struct stat st;
  if (stat(filename, &st) != 0) {
    printf("failed to stat \"%s\": %s\n", filename, strerror(errno));
@@ -413,8 +412,7 @@ unsigned char* ReadImage(const char* filename,
      size_t chunk_offset = pos;

      *num_chunks += 3;
      *chunks = static_cast<ImageChunk*>(realloc(*chunks,
          *num_chunks * sizeof(ImageChunk)));
      *chunks = static_cast<ImageChunk*>(realloc(*chunks, *num_chunks * sizeof(ImageChunk)));
      ImageChunk* curr = *chunks + (*num_chunks-3);

      // create a normal chunk for the header.
@@ -502,8 +500,7 @@ unsigned char* ReadImage(const char* filename,
      // the decompression.
      size_t footer_size = Read4(p-4);
      if (footer_size != curr[-2].len) {
        printf("Error: footer size %zu != decompressed size %zu\n",
            footer_size, curr[-2].len);
        printf("Error: footer size %zu != decompressed size %zu\n", footer_size, curr[-2].len);
        free(img);
        return NULL;
      }
@@ -637,7 +634,11 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) {
    }
  }

#if defined(__ANDROID__)
  char ptemp[] = "/data/local/tmp/imgdiff-patch-XXXXXX";
#else
  char ptemp[] = "/tmp/imgdiff-patch-XXXXXX";
#endif
  int fd = mkstemp(ptemp);

  if (fd == -1) {
@@ -793,10 +794,8 @@ void MergeAdjacentNormalChunks(ImageChunk* chunks, int* num_chunks) {
  *num_chunks = out;
}

ImageChunk* FindChunkByName(const char* name,
                            ImageChunk* chunks, int num_chunks) {
  int i;
  for (i = 0; i < num_chunks; ++i) {
ImageChunk* FindChunkByName(const char* name, ImageChunk* chunks, int num_chunks) {
  for (int i = 0; i < num_chunks; ++i) {
    if (chunks[i].type == CHUNK_DEFLATE && chunks[i].filename &&
        strcmp(name, chunks[i].filename) == 0) {
      return chunks+i;
@@ -812,11 +811,11 @@ void DumpChunks(ImageChunk* chunks, int num_chunks) {
    }
}

int main(int argc, char** argv) {
  int zip_mode = 0;
int imgdiff(int argc, const char** argv) {
  bool zip_mode = false;

  if (argc >= 2 && strcmp(argv[1], "-z") == 0) {
    zip_mode = 1;
    zip_mode = true;
    --argc;
    ++argv;
  }
@@ -880,12 +879,10 @@ int main(int argc, char** argv) {
    // Verify that the source and target images have the same chunk
    // structure (ie, the same sequence of deflate and normal chunks).

    if (!zip_mode) {
    // Merge the gzip header and footer in with any adjacent
    // normal chunks.
    MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks);
    MergeAdjacentNormalChunks(src_chunks, &num_src_chunks);
    }

    if (num_src_chunks != num_tgt_chunks) {
      printf("source and target don't have same number of chunks!\n");
@@ -897,8 +894,7 @@ int main(int argc, char** argv) {
    }
    for (i = 0; i < num_src_chunks; ++i) {
      if (src_chunks[i].type != tgt_chunks[i].type) {
        printf("source and target don't have same chunk "
                "structure! (chunk %d)\n", i);
        printf("source and target don't have same chunk structure! (chunk %d)\n", i);
        printf("source chunks:\n");
        DumpChunks(src_chunks, num_src_chunks);
        printf("target chunks:\n");
@@ -983,8 +979,7 @@ int main(int argc, char** argv) {
    if (zip_mode) {
      ImageChunk* src;
      if (tgt_chunks[i].type == CHUNK_DEFLATE &&
          (src = FindChunkByName(tgt_chunks[i].filename, src_chunks,
                                 num_src_chunks))) {
          (src = FindChunkByName(tgt_chunks[i].filename, src_chunks, num_src_chunks))) {
        patch_data[i] = MakePatch(src, tgt_chunks+i, patch_size+i);
      } else {
        patch_data[i] = MakePatch(src_chunks, tgt_chunks+i, patch_size+i);
@@ -1000,8 +995,7 @@ int main(int argc, char** argv) {

      patch_data[i] = MakePatch(src_chunks+i, tgt_chunks+i, patch_size+i);
    }
    printf("patch %3d is %zu bytes (of %zu)\n",
           i, patch_size[i], tgt_chunks[i].source_len);
    printf("patch %3d is %zu bytes (of %zu)\n", i, patch_size[i], tgt_chunks[i].source_len);
  }

  // Figure out how big the imgdiff file header is going to be, so
+21 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "applypatch/imgdiff.h"

int main(int argc, char** argv) {
  return imgdiff(argc, const_cast<const char**>(argv));
}
+200 −205
Original line number Diff line number Diff line
@@ -14,30 +14,32 @@
 * limitations under the License.
 */

// See imgdiff.c in this directory for a description of the patch file
// See imgdiff.cpp in this directory for a description of the patch file
// format.

#include <applypatch/imgpatch.h>

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/cdefs.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

#include <string>
#include <vector>

#include "zlib.h"
#include "openssl/sha.h"
#include "applypatch/applypatch.h"
#include "imgdiff.h"
#include <applypatch/applypatch.h>
#include <applypatch/imgdiff.h>
#include <openssl/sha.h>
#include <zlib.h>

#include "utils.h"

int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
                    const unsigned char* patch_data, ssize_t patch_size,
                    SinkFn sink, void* token) {
    Value patch(VAL_BLOB, std::string(
            reinterpret_cast<const char*>(patch_data), patch_size));
  Value patch(VAL_BLOB, std::string(reinterpret_cast<const char*>(patch_data), patch_size));

  return ApplyImagePatch(old_data, old_size, &patch, sink, token, nullptr, nullptr);
}
@@ -48,10 +50,8 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
 * file, and update the SHA context with the output data as well.
 * Return 0 on success.
 */
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
                    const Value* patch,
                    SinkFn sink, void* token, SHA_CTX* ctx,
                    const Value* bonus_data) {
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value* patch,
                    SinkFn sink, void* token, SHA_CTX* ctx, const Value* bonus_data) {
  if (patch->data.size() < 12) {
    printf("patch too short to contain header\n");
    return -1;
@@ -94,8 +94,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
        printf("source data too short\n");
        return -1;
      }
            ApplyBSDiffPatch(old_data + src_start, src_len,
                             patch, patch_offset, sink, token, ctx);
      ApplyBSDiffPatch(old_data + src_start, src_len, patch, patch_offset, sink, token, ctx);
    } else if (type == CHUNK_RAW) {
      const char* raw_header = &patch->data[pos];
      pos += 4;
@@ -111,8 +110,8 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
        return -1;
      }
      if (ctx) SHA1_Update(ctx, &patch->data[pos], data_len);
            if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]),
                     data_len, token) != data_len) {
      if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]), data_len, token) !=
          data_len) {
        printf("failed to write chunk %d raw data\n", i);
        return -1;
      }
@@ -161,12 +160,11 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
        strm.zfree = Z_NULL;
        strm.opaque = Z_NULL;
        strm.avail_in = src_len;
                strm.next_in = (unsigned char*)(old_data + src_start);
        strm.next_in = const_cast<unsigned char*>(old_data + src_start);
        strm.avail_out = expanded_len;
        strm.next_out = expanded_source.data();

                int ret;
                ret = inflateInit2(&strm, -15);
        int ret = inflateInit2(&strm, -15);
        if (ret != Z_OK) {
          printf("failed to init source inflation: %d\n", ret);
          return -1;
@@ -188,22 +186,20 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
        inflateEnd(&strm);

        if (bonus_size) {
                    memcpy(expanded_source.data() + (expanded_len - bonus_size),
                           &bonus_data->data[0], bonus_size);
          memcpy(expanded_source.data() + (expanded_len - bonus_size), &bonus_data->data[0],
                 bonus_size);
        }
      }

            // Next, apply the bsdiff patch (in memory) to the uncompressed
            // data.
      // Next, apply the bsdiff patch (in memory) to the uncompressed data.
      std::vector<unsigned char> uncompressed_target_data;
            if (ApplyBSDiffPatchMem(expanded_source.data(), expanded_len,
                                    patch, patch_offset,
      if (ApplyBSDiffPatchMem(expanded_source.data(), expanded_len, patch, patch_offset,
                              &uncompressed_target_data) != 0) {
        return -1;
      }
      if (uncompressed_target_data.size() != target_len) {
                printf("expected target len to be %zu, but it's %zu\n",
                       target_len, uncompressed_target_data.size());
        printf("expected target len to be %zu, but it's %zu\n", target_len,
               uncompressed_target_data.size());
        return -1;
      }

@@ -237,8 +233,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
          ssize_t have = temp_data.size() - strm.avail_out;

          if (sink(temp_data.data(), have, token) != have) {
                        printf("failed to write %zd compressed bytes to output\n",
                               have);
            printf("failed to write %zd compressed bytes to output\n", have);
            return -1;
          }
          if (ctx) SHA1_Update(ctx, temp_data.data(), have);
+15 −6
Original line number Diff line number Diff line
@@ -14,6 +14,11 @@
 * limitations under the License.
 */

#ifndef _APPLYPATCH_IMGDIFF_H
#define _APPLYPATCH_IMGDIFF_H

#include <stddef.h>

// Image patch chunk types
#define CHUNK_NORMAL 0
#define CHUNK_GZIP 1     // version 1 only
@@ -24,7 +29,11 @@
// support gzipped data with any of the optional fields, so for now it
// will always be ten bytes.  See RFC 1952 for the definition of the
// gzip format.
#define GZIP_HEADER_LEN   10
static constexpr size_t GZIP_HEADER_LEN = 10;

// The gzip footer size really is fixed.
#define GZIP_FOOTER_LEN   8
static constexpr size_t GZIP_FOOTER_LEN = 8;

int imgdiff(int argc, const char** argv);

#endif  // _APPLYPATCH_IMGDIFF_H
Loading