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

Commit 6c770467 authored by Doug Zongker's avatar Doug Zongker
Browse files

applypatch changes for patching recovery image

Make some changes needed to applypatch in order to store the recovery
image in the system partition as a binary patch relative to the boot
image:

  - make applypatch use shared libraries, so it's smaller.  It will
    need to be on the main system so it can install the recovery
    image.  Make an applypatch_static binary for use in recovery
    packages (still needed for updating cupcake devices to donut).

  - output the results of patching to an in-memory buffer and write
    that to the partition; there's no convenient /tmp for us to us.
    (This should be basically a no-op in recovery, since /tmp is a
    ramdisk anyway.)
parent 289d80ee
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -788,6 +788,7 @@ endef

built_ota_tools := \
	$(call intermediates-dir-for,EXECUTABLES,applypatch)/applypatch \
	$(call intermediates-dir-for,EXECUTABLES,applypatch_static)/applypatch_static \
	$(call intermediates-dir-for,EXECUTABLES,check_prereq)/check_prereq \
	$(call intermediates-dir-for,EXECUTABLES,updater)/updater
$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_OTA_TOOLS := $(built_ota_tools)
+11 −3
Original line number Diff line number Diff line
@@ -29,11 +29,19 @@ include $(CLEAR_VARS)

LOCAL_SRC_FILES := main.c
LOCAL_MODULE := applypatch
LOCAL_STATIC_LIBRARIES += libapplypatch libmtdutils libmincrypt libbz
LOCAL_SHARED_LIBRARIES += libz libcutils libstdc++ libc

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := main.c
LOCAL_MODULE := applypatch_static
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_TAGS := eng
LOCAL_STATIC_LIBRARIES += libapplypatch
LOCAL_STATIC_LIBRARIES += libmtdutils libmincrypt libbz libz
LOCAL_STATIC_LIBRARIES += libcutils libstdc++ libc
LOCAL_STATIC_LIBRARIES += libapplypatch libmtdutils libmincrypt libbz
LOCAL_STATIC_LIBRARIES += libz libcutils libstdc++ libc

include $(BUILD_EXECUTABLE)

+65 −38
Original line number Diff line number Diff line
@@ -282,9 +282,10 @@ int SaveFileContents(const char* filename, FileContents file) {
  return 0;
}

// Copy the contents of source_file to target_mtd partition, a string
// of the form "MTD:<partition>[:...]".  Return 0 on success.
int CopyToMTDPartition(const char* source_file, const char* target_mtd) {
// Write a memory buffer to target_mtd partition, a string of the form
// "MTD:<partition>[:...]".  Return 0 on success.
int WriteToMTDPartition(unsigned char* data, size_t len,
                        const char* target_mtd) {
  char* partition = strchr(target_mtd, ':');
  if (partition == NULL) {
    fprintf(stderr, "bad MTD target name \"%s\"\n", target_mtd);
@@ -298,13 +299,6 @@ int CopyToMTDPartition(const char* source_file, const char* target_mtd) {
  if (end != NULL)
    *end = '\0';

  FILE* f = fopen(source_file, "rb");
  if (f == NULL) {
    fprintf(stderr, "failed to open %s for reading: %s\n",
            source_file, strerror(errno));
    return -1;
  }

  if (!mtd_partitions_scanned) {
    mtd_scan_partitions();
    mtd_partitions_scanned = 1;
@@ -323,20 +317,14 @@ int CopyToMTDPartition(const char* source_file, const char* target_mtd) {
    return -1;
  }

  const int buffer_size = 4096;
  char buffer[buffer_size];
  size_t read;
  while ((read = fread(buffer, 1, buffer_size, f)) > 0) {
    size_t written = mtd_write_data(ctx, buffer, read);
    if (written != read) {
  size_t written = mtd_write_data(ctx, (char*)data, len);
  if (written != len) {
    fprintf(stderr, "only wrote %d of %d bytes to MTD %s\n",
              written, read, partition);
            written, len, partition);
    mtd_write_close(ctx);
    return -1;
  }
  }

  fclose(f);
  if (mtd_erase_blocks(ctx, -1) < 0) {
    fprintf(stderr, "error finishing mtd write of %s\n", partition);
    mtd_write_close(ctx);
@@ -476,6 +464,26 @@ int ShowLicenses() {
  return 0;
}

size_t FileSink(unsigned char* data, size_t len, void* token) {
  return fwrite(data, 1, len, (FILE*)token);
}

typedef struct {
  unsigned char* buffer;
  size_t size;
  size_t pos;
} MemorySinkInfo;

size_t MemorySink(unsigned char* data, size_t len, void* token) {
  MemorySinkInfo* msi = (MemorySinkInfo*)token;
  if (msi->size - msi->pos < len) {
    return -1;
  }
  memcpy(msi->buffer + msi->pos, data, len);
  msi->pos += len;
  return len;
}

// Return the amount of free space (in bytes) on the filesystem
// containing filename.  filename must exist.  Return -1 on error.
size_t FreeSpaceForFile(const char* filename) {
@@ -720,20 +728,37 @@ int applypatch(int argc, char** argv) {
  }

  char* outname = NULL;
  FILE* output = NULL;
  MemorySinkInfo msi;
  SinkFn sink = NULL;
  void* token = NULL;
  if (strncmp(target_filename, "MTD:", 4) == 0) {
    outname = MTD_TARGET_TEMP_FILE;
    // We store the decoded output in memory.
    msi.buffer = malloc(target_size);
    if (msi.buffer == NULL) {
      fprintf(stderr, "failed to alloc %ld bytes for output\n",
              (long)target_size);
      return 1;
    }
    msi.pos = 0;
    msi.size = target_size;
    sink = MemorySink;
    token = &msi;
  } else {
    // We write the decoded output to "<tgt-file>.patch".
    outname = (char*)malloc(strlen(target_filename) + 10);
    strcpy(outname, target_filename);
    strcat(outname, ".patch");
  }
  FILE* output = fopen(outname, "wb");

    output = fopen(outname, "wb");
    if (output == NULL) {
      fprintf(stderr, "failed to open output file %s: %s\n",
              outname, strerror(errno));
      return 1;
    }
    sink = FileSink;
    token = output;
  }

#define MAX_HEADER_LENGTH 8
  unsigned char header[MAX_HEADER_LENGTH];
@@ -759,7 +784,7 @@ int applypatch(int argc, char** argv) {
  } else if (header_bytes_read >= 8 &&
             memcmp(header, "BSDIFF40", 8) == 0) {
    int result = ApplyBSDiffPatch(source_to_use->data, source_to_use->size,
                                  patch_filename, 0, output, &ctx);
                                  patch_filename, 0, sink, token, &ctx);
    if (result != 0) {
      fprintf(stderr, "ApplyBSDiffPatch failed\n");
      return result;
@@ -768,7 +793,7 @@ int applypatch(int argc, char** argv) {
             memcmp(header, "IMGDIFF", 7) == 0 &&
             (header[7] == '1' || header[7] == '2')) {
    int result = ApplyImagePatch(source_to_use->data, source_to_use->size,
                                 patch_filename, output, &ctx);
                                 patch_filename, sink, token, &ctx);
    if (result != 0) {
      fprintf(stderr, "ApplyImagePatch failed\n");
      return result;
@@ -778,9 +803,11 @@ int applypatch(int argc, char** argv) {
    return 1;
  }

  if (output != NULL) {
    fflush(output);
    fsync(fileno(output));
    fclose(output);
  }

  const uint8_t* current_target_sha1 = SHA_final(&ctx);
  if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
@@ -788,13 +815,13 @@ int applypatch(int argc, char** argv) {
    return 1;
  }

  if (strcmp(outname, MTD_TARGET_TEMP_FILE) == 0) {
  if (output == NULL) {
    // Copy the temp file to the MTD partition.
    if (CopyToMTDPartition(outname, target_filename) != 0) {
      fprintf(stderr, "copy of %s to %s failed\n", outname, target_filename);
    if (WriteToMTDPartition(msi.buffer, msi.pos, target_filename) != 0) {
      fprintf(stderr, "write of patched data to %s failed\n", target_filename);
      return 1;
    }
    unlink(outname);
    free(msi.buffer);
  } else {
    // Give the .patch file the same owner, group, and mode of the
    // original source file.
+4 −7
Original line number Diff line number Diff line
@@ -39,10 +39,7 @@ typedef struct _FileContents {
// and use it as the source instead.
#define CACHE_TEMP_SOURCE "/cache/saved.file"

// When writing to an MTD partition, we first put the output in this
// temp file, then copy it to the partition once the patching is
// finished (and the target sha1 verified).
#define MTD_TARGET_TEMP_FILE "/tmp/mtd-temp"
typedef size_t (*SinkFn)(unsigned char*, size_t, void*);

// applypatch.c
size_t FreeSpaceForFile(const char* filename);
@@ -52,7 +49,7 @@ int applypatch(int argc, char** argv);
void ShowBSDiffLicense();
int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
                     const char* patch_filename, ssize_t offset,
                     FILE* output, SHA_CTX* ctx);
                     SinkFn sink, void* token, SHA_CTX* ctx);
int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
                        const char* patch_filename, ssize_t patch_offset,
                        unsigned char** new_data, ssize_t* new_size);
@@ -60,7 +57,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
// imgpatch.c
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
                    const char* patch_filename,
                     FILE* output, SHA_CTX* ctx);
                    SinkFn sink, void* token, SHA_CTX* ctx);

// freecache.c
int MakeFreeSpaceOnCache(size_t bytes_needed);
+2 −2
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ static off_t offtin(u_char *buf)

int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
                     const char* patch_filename, ssize_t patch_offset,
                     FILE* output, SHA_CTX* ctx) {
                     SinkFn sink, void* token, SHA_CTX* ctx) {

  unsigned char* new_data;
  ssize_t new_size;
@@ -93,7 +93,7 @@ int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
    return -1;
  }

  if (fwrite(new_data, 1, new_size, output) < new_size) {
  if (sink(new_data, new_size, token) < new_size) {
    fprintf(stderr, "short write of output: %d (%s)\n", errno, strerror(errno));
    return 1;
  }
Loading