/*
 * 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.
 */

#include "applypatch/applypatch.h"

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

#include <algorithm>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <openssl/sha.h>

#include "bmlutils/bmlutils.h"
#include "mtdutils/mtdutils.h"

#include "edify/expr.h"
#include "otautil/paths.h"
#include "otautil/print_sha1.h"

using namespace std::string_literals;

static bool GenerateTarget(const Partition& target, const FileContents& source_file,
                           const Value& patch, const Value* bonus_data);

bool LoadFileContents(const std::string& filename, FileContents* file) {
  // No longer allow loading contents from eMMC partitions.
  if (android::base::StartsWith(filename, "EMMC:")) {
    return false;
  }

  std::string data;
  if (!android::base::ReadFileToString(filename, &data)) {
    PLOG(ERROR) << "Failed to read \"" << filename << "\"";
    return false;
  }

  file->data = std::vector<unsigned char>(data.begin(), data.end());
  SHA1(file->data.data(), file->data.size(), file->sha1);
  return true;
}

// Reads the contents of a Partition to the given FileContents buffer.
static bool ReadPartitionToBuffer(const Partition& partition, FileContents* out,
                                  bool check_backup) {
  uint8_t expected_sha1[SHA_DIGEST_LENGTH];
  if (ParseSha1(partition.hash, expected_sha1) != 0) {
    LOG(ERROR) << "Failed to parse target hash \"" << partition.hash << "\"";
    return false;
  }

  android::base::unique_fd dev(open(partition.name.c_str(), O_RDONLY));
  if (dev == -1) {
    PLOG(ERROR) << "Failed to open eMMC partition \"" << partition << "\"";
  } else {
    std::vector<unsigned char> buffer(partition.size);
    if (!android::base::ReadFully(dev, buffer.data(), buffer.size())) {
      PLOG(ERROR) << "Failed to read " << buffer.size() << " bytes of data for partition "
                  << partition;
    } else {
      SHA1(buffer.data(), buffer.size(), out->sha1);
      if (memcmp(out->sha1, expected_sha1, SHA_DIGEST_LENGTH) == 0) {
        out->data = std::move(buffer);
        return true;
      }
    }
  }

  if (!check_backup) {
    LOG(ERROR) << "Partition contents don't have the expected checksum";
    return false;
  }

  if (LoadFileContents(Paths::Get().cache_temp_source(), out) &&
      memcmp(out->sha1, expected_sha1, SHA_DIGEST_LENGTH) == 0) {
    return true;
  }

  LOG(ERROR) << "Both of partition contents and backup don't have the expected checksum";
  return false;
}

bool SaveFileContents(const std::string& filename, const FileContents* file) {
  android::base::unique_fd fd(
      open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR));
  if (fd == -1) {
    PLOG(ERROR) << "Failed to open \"" << filename << "\" for write";
    return false;
  }

  if (!android::base::WriteFully(fd, file->data.data(), file->data.size())) {
    PLOG(ERROR) << "Failed to write " << file->data.size() << " bytes of data to " << filename;
    return false;
  }

  if (fsync(fd) != 0) {
    PLOG(ERROR) << "Failed to fsync \"" << filename << "\"";
    return false;
  }

  if (close(fd.release()) != 0) {
    PLOG(ERROR) << "Failed to close \"" << filename << "\"";
    return false;
  }

  return true;
}

// Writes a memory buffer to 'target' Partition.
static bool WriteBufferToPartition(const FileContents& file_contents, const Partition& partition) {
  const unsigned char* data = file_contents.data.data();
  size_t len = file_contents.data.size();
  size_t start = 0;
  bool success = false;
  for (size_t attempt = 0; attempt < 2; ++attempt) {
    android::base::unique_fd fd(open(partition.name.c_str(), O_RDWR));
    if (fd == -1) {
      PLOG(ERROR) << "Failed to open \"" << partition << "\"";
      return false;
    }

    if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) {
      PLOG(ERROR) << "Failed to seek to " << start << " on \"" << partition << "\"";
      return false;
    }

    if (!android::base::WriteFully(fd, data + start, len - start)) {
      PLOG(ERROR) << "Failed to write " << len - start << " bytes to \"" << partition << "\"";
      return false;
    }

    if (fsync(fd) != 0) {
      PLOG(ERROR) << "Failed to sync \"" << partition << "\"";
      return false;
    }
    if (close(fd.release()) != 0) {
      PLOG(ERROR) << "Failed to close \"" << partition << "\"";
      return false;
    }

    fd.reset(open(partition.name.c_str(), O_RDONLY));
    if (fd == -1) {
      PLOG(ERROR) << "Failed to reopen \"" << partition << "\" for verification";
      return false;
    }

    // Drop caches so our subsequent verification read won't just be reading the cache.
    sync();
    std::string drop_cache = "/proc/sys/vm/drop_caches";
    if (!android::base::WriteStringToFile("3\n", drop_cache)) {
      PLOG(ERROR) << "Failed to write to " << drop_cache;
    } else {
      LOG(INFO) << "  caches dropped";
    }
    sleep(1);

    // Verify.
    if (TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET)) == -1) {
      PLOG(ERROR) << "Failed to seek to 0 on " << partition;
      return false;
    }

    const char* partition = pieces[1].c_str();

        PLOG(ERROR) << "Failed to verify-read " << partition << " at " << p;
        return false;
      }

      if (memcmp(buffer, data + p, to_read) != 0) {
        LOG(ERROR) << "Verification failed starting at " << p;
        start = p;
        break;
      }
    }

    if (start == len) {
      LOG(INFO) << "Verification read succeeded (attempt " << attempt + 1 << ")";
      success = true;
      break;
    }

    if (close(fd.release()) != 0) {
      PLOG(ERROR) << "Failed to close " << partition;
      return false;
    }
  }

  if (!success) {
    LOG(ERROR) << "Failed to verify after all attempts";
    return false;
  }

  sync();

  return true;
}

int ParseSha1(const std::string& str, uint8_t* digest) {
  const char* ps = str.c_str();
  uint8_t* pd = digest;
  for (int i = 0; i < SHA_DIGEST_LENGTH * 2; ++i, ++ps) {
    int digit;
    if (*ps >= '0' && *ps <= '9') {
      digit = *ps - '0';
    } else if (*ps >= 'a' && *ps <= 'f') {
      digit = *ps - 'a' + 10;
    } else if (*ps >= 'A' && *ps <= 'F') {
      digit = *ps - 'A' + 10;
    } else {
      return -1;
    }
    if (i % 2 == 0) {
      *pd = digit << 4;
    } else {
      *pd |= digit;
      ++pd;
    }
  }
  if (*ps != '\0') return -1;
  return 0;
}

bool PatchPartitionCheck(const Partition& target, const Partition& source) {
  FileContents target_file;
  FileContents source_file;
  return (ReadPartitionToBuffer(target, &target_file, false) ||
          ReadPartitionToBuffer(source, &source_file, true));
}

int ShowLicenses() {
  ShowBSDiffLicense();
  return 0;
}

bool PatchPartition(const Partition& target, const Partition& source, const Value& patch,
                    const Value* bonus) {
  LOG(INFO) << "Patching " << target.name;

  // We try to load and check against the target hash first.
  FileContents target_file;
  if (ReadPartitionToBuffer(target, &target_file, false)) {
    // The early-exit case: the patch was already applied, this file has the desired hash, nothing
    // for us to do.
    LOG(INFO) << "  already " << target.hash.substr(0, 8);
    return true;
  }

  FileContents source_file;
  if (ReadPartitionToBuffer(source, &source_file, true)) {
    return GenerateTarget(target, source_file, patch, bonus);
  }

  LOG(ERROR) << "Failed to find any match";
  return false;
}

bool FlashPartition(const Partition& partition, const std::string& source_filename) {
  LOG(INFO) << "Flashing " << partition;

  // We try to load and check against the target hash first.
  FileContents target_file;
  if (ReadPartitionToBuffer(partition, &target_file, false)) {
    // The early-exit case: the patch was already applied, this file has the desired hash, nothing
    // for us to do.
    LOG(INFO) << "  already " << partition.hash.substr(0, 8);
    return true;
  }

  FileContents source_file;
  if (!LoadFileContents(source_filename, &source_file)) {
    LOG(ERROR) << "Failed to load source file";
    return false;
  }

  uint8_t expected_sha1[SHA_DIGEST_LENGTH];
  if (ParseSha1(partition.hash, expected_sha1) != 0) {
    LOG(ERROR) << "Failed to parse source hash \"" << partition.hash << "\"";
    return false;
  }

  if (memcmp(source_file.sha1, expected_sha1, SHA_DIGEST_LENGTH) != 0) {
    // The source doesn't have desired checksum.
    LOG(ERROR) << "source \"" << source_filename << "\" doesn't have expected SHA-1 sum";
    LOG(ERROR) << "expected: " << partition.hash.substr(0, 8)
               << ", found: " << short_sha1(source_file.sha1);
    return false;
  }
  if (!WriteBufferToPartition(source_file, partition)) {
    LOG(ERROR) << "Failed to write to " << partition;
    return false;
  }
  return true;
}

static bool GenerateTarget(const Partition& target, const FileContents& source_file,
                           const Value& patch, const Value* bonus_data) {
  uint8_t expected_sha1[SHA_DIGEST_LENGTH];
  if (ParseSha1(target.hash, expected_sha1) != 0) {
    LOG(ERROR) << "Failed to parse target hash \"" << target.hash << "\"";
    return false;
  }

  if (patch.type != Value::Type::BLOB) {
    LOG(ERROR) << "patch is not a blob";
    return false;
  }

  const char* header = patch.data.data();
  size_t header_bytes_read = patch.data.size();
  bool use_bsdiff = false;
  if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) {
    use_bsdiff = true;
  } else if (header_bytes_read >= 8 && memcmp(header, "IMGDIFF2", 8) == 0) {
    use_bsdiff = false;
  } else {
    LOG(ERROR) << "Unknown patch file format";
    return false;
  }

  // We write the original source to cache, in case the partition write is interrupted.
  if (!CheckAndFreeSpaceOnCache(source_file.data.size())) {
    LOG(ERROR) << "Not enough free space on /cache";
    return false;
  }
  if (!SaveFileContents(Paths::Get().cache_temp_source(), &source_file)) {
    LOG(ERROR) << "Failed to back up source file";
    return false;
  }

  // We store the decoded output in memory.
  FileContents patched;
  SHA_CTX ctx;
  SHA1_Init(&ctx);
  SinkFn sink = [&patched, &ctx](const unsigned char* data, size_t len) {
    SHA1_Update(&ctx, data, len);
    patched.data.insert(patched.data.end(), data, data + len);
    return len;
  };

  int result;
  if (use_bsdiff) {
    result = ApplyBSDiffPatch(source_file.data.data(), source_file.data.size(), patch, 0, sink);
  } else {
    result =
        ApplyImagePatch(source_file.data.data(), source_file.data.size(), patch, sink, bonus_data);
  }

  if (result != 0) {
    LOG(ERROR) << "Failed to apply the patch: " << result;
    return false;
  }

  SHA1_Final(patched.sha1, &ctx);
  if (memcmp(patched.sha1, expected_sha1, SHA_DIGEST_LENGTH) != 0) {
    LOG(ERROR) << "Patching did not produce the expected SHA-1 of " << short_sha1(expected_sha1);

    LOG(ERROR) << "target size " << patched.data.size() << " SHA-1 " << short_sha1(patched.sha1);
    LOG(ERROR) << "source size " << source_file.data.size() << " SHA-1 "
               << short_sha1(source_file.sha1);

    uint8_t patch_digest[SHA_DIGEST_LENGTH];
    SHA1(reinterpret_cast<const uint8_t*>(patch.data.data()), patch.data.size(), patch_digest);
    LOG(ERROR) << "patch size " << patch.data.size() << " SHA-1 " << short_sha1(patch_digest);

    if (bonus_data != nullptr) {
      uint8_t bonus_digest[SHA_DIGEST_LENGTH];
      SHA1(reinterpret_cast<const uint8_t*>(bonus_data->data.data()), bonus_data->data.size(),
           bonus_digest);
      LOG(ERROR) << "bonus size " << bonus_data->data.size() << " SHA-1 "
                 << short_sha1(bonus_digest);
    }

    return false;
  }

  LOG(INFO) << "  now " << short_sha1(expected_sha1);

  // Write back the temp file to the partition.
  if (*this) {
    return "EMMC:"s + name + ":" + std::to_string(size) + ":" + hash;
  }
  return "<invalid-partition>";
}

std::ostream& operator<<(std::ostream& os, const Partition& partition) {
  os << partition.ToString();
  return os;
}
