/*
 * Copyright (C) 2008 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.
 */

// This file is a nearly line-for-line copy of bspatch.c from the
// bsdiff-4.3 distribution; the primary differences being how the
// input and output data are read and the error handling.  Running
// applypatch with the -l option will display the bsdiff license
// notice.

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

#include <bzlib.h>

#include "mincrypt/sha.h"

void ShowBSDiffLicense() {
  puts("The bsdiff library used herein is:\n"
       "\n"
       "Copyright 2003-2005 Colin Percival\n"
       "All rights reserved\n"
       "\n"
       "Redistribution and use in source and binary forms, with or without\n"
       "modification, are permitted providing that the following conditions\n"
       "are met:\n"
       "1. Redistributions of source code must retain the above copyright\n"
       "   notice, this list of conditions and the following disclaimer.\n"
       "2. Redistributions in binary form must reproduce the above copyright\n"
       "   notice, this list of conditions and the following disclaimer in the\n"
       "   documentation and/or other materials provided with the distribution.\n"
       "\n"
       "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
       "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
       "WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
       "ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n"
       "DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"
       "DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"
       "OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n"
       "HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n"
       "STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n"
       "IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
       "POSSIBILITY OF SUCH DAMAGE.\n"
       "\n------------------\n\n"
       "This program uses Julian R Seward's \"libbzip2\" library, available\n"
       "from http://www.bzip.org/.\n"
       );
}

static off_t offtin(u_char *buf)
{
  off_t y;

  y=buf[7]&0x7F;
  y=y*256;y+=buf[6];
  y=y*256;y+=buf[5];
  y=y*256;y+=buf[4];
  y=y*256;y+=buf[3];
  y=y*256;y+=buf[2];
  y=y*256;y+=buf[1];
  y=y*256;y+=buf[0];

  if(buf[7]&0x80) y=-y;

  return y;
}

int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
                     const char* patch_filename,
                     FILE* output, SHA_CTX* ctx) {

  FILE* f;
  if ((f = fopen(patch_filename, "rb")) == NULL) {
    fprintf(stderr, "failed to open patch file\n");
    return 1;
  }

  // File format:
  //   0       8       "BSDIFF40"
  //   8       8       X
  //   16      8       Y
  //   24      8       sizeof(newfile)
  //   32      X       bzip2(control block)
  //   32+X    Y       bzip2(diff block)
  //   32+X+Y  ???     bzip2(extra block)
  // with control block a set of triples (x,y,z) meaning "add x bytes
  // from oldfile to x bytes from the diff block; copy y bytes from the
  // extra block; seek forwards in oldfile by z bytes".

  unsigned char header[32];
  if (fread(header, 1, 32, f) < 32) {
    fprintf(stderr, "failed to read patch file header\n");
    return 1;
  }

  if (memcmp(header, "BSDIFF40", 8) != 0) {
    fprintf(stderr, "corrupt patch file header (magic number)\n");
    return 1;
  }

  ssize_t ctrl_len, data_len;
  ssize_t new_size;
  ctrl_len = offtin(header+8);
  data_len = offtin(header+16);
  new_size = offtin(header+24);

  if (ctrl_len < 0 || data_len < 0 || new_size < 0) {
    fprintf(stderr, "corrupt patch file header (data lengths)\n");
    return 1;
  }

  fclose(f);

  int bzerr;

#define OPEN_AT(f, bzf, offset)                                          \
  FILE* f;                                                               \
  BZFILE* bzf;                                                           \
  if ((f = fopen(patch_filename, "rb")) == NULL) {                       \
    fprintf(stderr, "failed to open patch file\n");                      \
    return 1;                                                            \
  }                                                                      \
  if (fseeko(f, offset, SEEK_SET)) {                                     \
    fprintf(stderr, "failed to seek in patch file\n");                   \
    return 1;                                                            \
  }                                                                      \
  if ((bzf = BZ2_bzReadOpen(&bzerr, f, 0, 0, NULL, 0)) == NULL) {        \
    fprintf(stderr, "failed to bzReadOpen in patch file (%d)\n", bzerr); \
    return 1;                                                            \
  }

  OPEN_AT(cpf, cpfbz2, 32);
  OPEN_AT(dpf, dpfbz2, 32+ctrl_len);
  OPEN_AT(epf, epfbz2, 32+ctrl_len+data_len);

#undef OPEN_AT

  unsigned char* new_data = malloc(new_size);
  if (new_data == NULL) {
    fprintf(stderr, "failed to allocate memory for output file\n");
    return 1;
  }

  off_t oldpos = 0, newpos = 0;
  off_t ctrl[3];
  off_t len_read;
  int i;
  unsigned char buf[8];
  while (newpos < new_size) {
    // Read control data
    for (i = 0; i < 3; ++i) {
      len_read = BZ2_bzRead(&bzerr, cpfbz2, buf, 8);
      if (len_read < 8 || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
        fprintf(stderr, "corrupt patch (read control)\n");
        return 1;
      }
      ctrl[i] = offtin(buf);
    }

    // Sanity check
    if (newpos + ctrl[0] > new_size) {
      fprintf(stderr, "corrupt patch (new file overrun)\n");
      return 1;
    }

    // Read diff string
    len_read = BZ2_bzRead(&bzerr, dpfbz2, new_data + newpos, ctrl[0]);
    if (len_read < ctrl[0] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
      fprintf(stderr, "corrupt patch (read diff)\n");
      return 1;
    }

    // Add old data to diff string
    for (i = 0; i < ctrl[0]; ++i) {
      if ((oldpos+i >= 0) && (oldpos+i < old_size)) {
        new_data[newpos+i] += old_data[oldpos+i];
      }
    }

    // Adjust pointers
    newpos += ctrl[0];
    oldpos += ctrl[0];

    // Sanity check
    if (newpos + ctrl[1] > new_size) {
      fprintf(stderr, "corrupt patch (new file overrun)\n");
      return 1;
    }

    // Read extra string
    len_read = BZ2_bzRead(&bzerr, epfbz2, new_data + newpos, ctrl[1]);
    if (len_read < ctrl[1] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
      fprintf(stderr, "corrupt patch (read extra)\n");
      return 1;
    }

    // Adjust pointers
    newpos += ctrl[1];
    oldpos += ctrl[2];
  }

  BZ2_bzReadClose(&bzerr, cpfbz2);
  BZ2_bzReadClose(&bzerr, dpfbz2);
  BZ2_bzReadClose(&bzerr, epfbz2);
  fclose(cpf);
  fclose(dpf);
  fclose(epf);

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

  return 0;
}
