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

Commit a1e3d67b authored by Tianjie Xu's avatar Tianjie Xu Committed by Gerrit Code Review
Browse files

Merge "Remove otafault"

parents 9d7f9185 22f11205
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ cc_library_static {
        "libbz",
        "libcrypto",
        "libedify",
        "libotafault",
        "libotautil",
        "libz",
    ],
@@ -100,7 +99,6 @@ cc_binary {
        "libapplypatch_modes",
        "libapplypatch",
        "libedify",
        "libotafault",
        "libotautil",
        "libbspatch",
    ],
+46 −104
Original line number Diff line number Diff line
@@ -26,24 +26,25 @@
#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 "edify/expr.h"
#include "otafault/ota_io.h"
#include "otautil/paths.h"
#include "otautil/print_sha1.h"

static int LoadPartitionContents(const std::string& filename, FileContents* file);
static size_t FileSink(const unsigned char* data, size_t len, int fd);
static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch,
                          const std::string& target_filename,
                          const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data);
@@ -54,26 +55,13 @@ int LoadFileContents(const std::string& filename, FileContents* file) {
    return LoadPartitionContents(filename, file);
  }

  struct stat sb;
  if (stat(filename.c_str(), &sb) == -1) {
    PLOG(ERROR) << "Failed to stat \"" << filename << "\"";
  std::string data;
  if (!android::base::ReadFileToString(filename, &data)) {
    PLOG(ERROR) << "Failed to read \"" << filename << "\"";
    return -1;
  }

  std::vector<unsigned char> data(sb.st_size);
  unique_file f(ota_fopen(filename.c_str(), "rb"));
  if (!f) {
    PLOG(ERROR) << "Failed to open \"" << filename << "\"";
    return -1;
  }

  size_t bytes_read = ota_fread(data.data(), 1, data.size(), f.get());
  if (bytes_read != data.size()) {
    LOG(ERROR) << "Short read of \"" << filename << "\" (" << bytes_read << " bytes of "
               << data.size() << ")";
    return -1;
  }
  file->data = std::move(data);
  file->data = std::vector<unsigned char>(data.begin(), data.end());
  SHA1(file->data.data(), file->data.size(), file->sha1);
  return 0;
}
@@ -110,8 +98,8 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file
  std::sort(pairs.begin(), pairs.end());

  const char* partition = pieces[1].c_str();
  unique_file dev(ota_fopen(partition, "rb"));
  if (!dev) {
  android::base::unique_fd dev(open(partition, O_RDONLY));
  if (dev == -1) {
    PLOG(ERROR) << "Failed to open eMMC partition \"" << partition << "\"";
    return -1;
  }
@@ -121,8 +109,7 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file

  // Allocate enough memory to hold the largest size.
  std::vector<unsigned char> buffer(pairs[pair_count - 1].first);
  unsigned char* buffer_ptr = buffer.data();
  size_t buffer_size = 0;  // # bytes read so far
  size_t offset = 0;  // # bytes read so far
  bool found = false;

  for (const auto& pair : pairs) {
@@ -131,19 +118,16 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file

    // Read enough additional bytes to get us up to the next size. (Again,
    // we're trying the possibilities in order of increasing size).
    size_t next = current_size - buffer_size;
    if (next > 0) {
      size_t read = ota_fread(buffer_ptr, 1, next, dev.get());
      if (next != read) {
        LOG(ERROR) << "Short read (" << read << " bytes of " << next << ") for partition \""
                   << partition << "\"";
    if (current_size - offset > 0) {
      if (!android::base::ReadFully(dev, buffer.data() + offset, current_size - offset)) {
        PLOG(ERROR) << "Failed to read " << current_size - offset << " bytes of data at offset "
                    << offset << " for partition " << partition;
        return -1;
      }
      SHA1_Update(&sha_ctx, buffer_ptr, read);
      buffer_size += read;
      buffer_ptr += read;
    }

      SHA1_Update(&sha_ctx, buffer.data() + offset, current_size - offset);
      offset = current_size;
    }
    // Duplicate the SHA context and finalize the duplicate so we can
    // check it against this pair's expected hash.
    SHA_CTX temp_ctx;
@@ -173,31 +157,31 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file

  SHA1_Final(file->sha1, &sha_ctx);

  buffer.resize(buffer_size);
  buffer.resize(offset);
  file->data = std::move(buffer);

  return 0;
}

int SaveFileContents(const std::string& filename, const FileContents* file) {
  unique_fd fd(
      ota_open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR));
  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 -1;
  }

  size_t bytes_written = FileSink(file->data.data(), file->data.size(), fd);
  if (bytes_written != file->data.size()) {
    PLOG(ERROR) << "Short write of \"" << filename << "\" (" << bytes_written << " bytes of "
                << file->data.size();
  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 -1;
  }
  if (ota_fsync(fd) != 0) {

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

  if (close(fd.release()) != 0) {
    PLOG(ERROR) << "Failed to close \"" << filename << "\"";
    return -1;
  }
@@ -215,42 +199,36 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st
    return -1;
  }

  const char* partition = pieces[1].c_str();
  unique_fd fd(ota_open(partition, O_RDWR));
  size_t start = 0;
  bool success = false;
  for (size_t attempt = 0; attempt < 2; ++attempt) {
    std::string partition = pieces[1];
    android::base::unique_fd fd(open(partition.c_str(), O_RDWR));
    if (fd == -1) {
      PLOG(ERROR) << "Failed to open \"" << partition << "\"";
      return -1;
    }

  size_t start = 0;
  bool success = false;
  for (size_t attempt = 0; attempt < 2; ++attempt) {
    if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) {
      PLOG(ERROR) << "Failed to seek to " << start << " on \"" << partition << "\"";
      return -1;
    }
    while (start < len) {
      size_t to_write = len - start;
      if (to_write > 1 << 20) to_write = 1 << 20;

      ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data + start, to_write));
      if (written == -1) {
        PLOG(ERROR) << "Failed to write to \"" << partition << "\"";
    if (!android::base::WriteFully(fd, data + start, len - start)) {
      PLOG(ERROR) << "Failed to write " << len - start << " bytes to \"" << partition << "\"";
      return -1;
    }
      start += written;
    }

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

    fd.reset(ota_open(partition, O_RDONLY));
    fd.reset(open(partition.c_str(), O_RDONLY));
    if (fd == -1) {
      PLOG(ERROR) << "Failed to reopen \"" << partition << "\" for verification";
      return -1;
@@ -258,13 +236,12 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st

    // Drop caches so our subsequent verification read won't just be reading the cache.
    sync();
    unique_fd dc(ota_open("/proc/sys/vm/drop_caches", O_WRONLY));
    if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) {
      PLOG(ERROR) << "Failed to write to /proc/sys/vm/drop_caches";
    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";
    }
    ota_close(dc);
    sleep(1);

    // Verify.
@@ -281,21 +258,9 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st
        to_read = sizeof(buffer);
      }

      size_t so_far = 0;
      while (so_far < to_read) {
        ssize_t read_count = TEMP_FAILURE_RETRY(ota_read(fd, buffer + so_far, to_read - so_far));
        if (read_count == -1) {
      if (!android::base::ReadFully(fd, buffer, to_read)) {
        PLOG(ERROR) << "Failed to verify-read " << partition << " at " << p;
        return -1;
        } else if (read_count == 0) {
          LOG(ERROR) << "Verify-reading " << partition << " reached unexpected EOF at " << p;
          return -1;
        }
        if (static_cast<size_t>(read_count) < to_read) {
          LOG(INFO) << "Short verify-read " << partition << " at " << p << ": expected " << to_read
                    << " actual " << read_count;
        }
        so_far += read_count;
      }

      if (memcmp(buffer, data + p, to_read) != 0) {
@@ -311,16 +276,10 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st
      break;
    }

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

    fd.reset(ota_open(partition, O_RDWR));
    if (fd == -1) {
      PLOG(ERROR) << "Failed to reopen " << partition << " for next attempt";
      return -1;
    }
  }

  if (!success) {
@@ -328,10 +287,6 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st
    return -1;
  }

  if (ota_close(fd) == -1) {
    PLOG(ERROR) << "Failed to close " << partition;
    return -1;
  }
  sync();

  return 0;
@@ -407,19 +362,6 @@ int ShowLicenses() {
  return 0;
}

static size_t FileSink(const unsigned char* data, size_t len, int fd) {
  size_t done = 0;
  while (done < len) {
    ssize_t wrote = TEMP_FAILURE_RETRY(ota_write(fd, data + done, len - done));
    if (wrote == -1) {
      PLOG(ERROR) << "Failed to write " << len - done << " bytes";
      return done;
    }
    done += wrote;
  }
  return done;
}

int applypatch(const char* source_filename, const char* target_filename,
               const char* target_sha1_str, size_t /* target_size */,
               const std::vector<std::string>& patch_sha1s,

otafault/Android.bp

deleted100644 → 0
+0 −68
Original line number Diff line number Diff line
// Copyright (C) 2017 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.

cc_library_static {
    name: "libotafault",

    host_supported: true,

    srcs: [
        "config.cpp",
        "ota_io.cpp",
    ],

    static_libs: [
        "libbase",
        "liblog",
        "libziparchive",
    ],

    export_include_dirs: [
        "include",
    ],

    cflags: [
        "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
        "-Wall",
        "-Werror",
        "-Wthread-safety",
        "-Wthread-safety-negative",
    ],

    target: {
        darwin: {
            enabled: false,
        },
    },
}

cc_test {
    name: "otafault_test",

    srcs: ["test.cpp"],

    cflags: [
        "-Wall",
        "-Werror",
    ],

    static_executable: true,

    static_libs: [
        "libotafault",
        "libziparchive",
        "libbase",
        "liblog",
    ],
}

otafault/config.cpp

deleted100644 → 0
+0 −75
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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 "otafault/config.h"

#include <map>
#include <string>

#include <android-base/stringprintf.h>
#include <ziparchive/zip_archive.h>

#include "otafault/ota_io.h"

#define OTAIO_MAX_FNAME_SIZE 128

static ZipArchiveHandle archive;
static bool is_retry = false;
static std::map<std::string, bool> should_inject_cache;

static std::string get_type_path(const char* io_type) {
    return android::base::StringPrintf("%s/%s", OTAIO_BASE_DIR, io_type);
}

void ota_io_init(ZipArchiveHandle za, bool retry) {
    archive = za;
    is_retry = retry;
    ota_set_fault_files();
}

bool should_fault_inject(const char* io_type) {
    // archive will be NULL if we used an entry point other
    // than updater/updater.cpp:main
    if (archive == nullptr || is_retry) {
        return false;
    }
    const std::string type_path = get_type_path(io_type);
    if (should_inject_cache.find(type_path) != should_inject_cache.end()) {
        return should_inject_cache[type_path];
    }
    ZipString zip_type_path(type_path.c_str());
    ZipEntry entry;
    int status = FindEntry(archive, zip_type_path, &entry);
    should_inject_cache[type_path] = (status == 0);
    return (status == 0);
}

bool should_hit_cache() {
    return should_fault_inject(OTAIO_CACHE);
}

std::string fault_fname(const char* io_type) {
    std::string type_path = get_type_path(io_type);
    std::string fname;
    fname.resize(OTAIO_MAX_FNAME_SIZE);
    ZipString zip_type_path(type_path.c_str());
    ZipEntry entry;
    if (FindEntry(archive, zip_type_path, &entry) != 0) {
        return {};
    }
    ExtractToMemory(archive, &entry, reinterpret_cast<uint8_t*>(&fname[0]), OTAIO_MAX_FNAME_SIZE);
    return fname;
}
+0 −72
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.
 */

/*
 * Read configuration files in the OTA package to determine which files, if any, will trigger
 * errors.
 *
 * OTA packages can be modified to trigger errors by adding a top-level directory called
 * .libotafault, which may optionally contain up to three files called READ, WRITE, and FSYNC.
 * Each one of these optional files contains the name of a single file on the device disk which
 * will cause an IO error on the first call of the appropriate I/O action to that file.
 *
 * Example:
 * ota.zip
 *   <normal package contents>
 *   .libotafault
 *     WRITE
 *
 * If the contents of the file WRITE were /system/build.prop, the first write action to
 * /system/build.prop would fail with EIO. Note that READ and FSYNC files are absent, so these
 * actions will not cause an error.
 */

#ifndef _UPDATER_OTA_IO_CFG_H_
#define _UPDATER_OTA_IO_CFG_H_

#include <string>

#include <ziparchive/zip_archive.h>

#define OTAIO_BASE_DIR ".libotafault"
#define OTAIO_READ "READ"
#define OTAIO_WRITE "WRITE"
#define OTAIO_FSYNC "FSYNC"
#define OTAIO_CACHE "CACHE"

/*
 * Initialize libotafault by providing a reference to the OTA package.
 */
void ota_io_init(ZipArchiveHandle zip, bool retry);

/*
 * Return true if a config file is present for the given IO type.
 */
bool should_fault_inject(const char* io_type);

/*
 * Return true if an EIO should occur on the next hit to /cache/saved.file
 * instead of the next hit to the specified file.
 */
bool should_hit_cache();

/*
 * Return the name of the file that should cause an error for the
 * given IO type.
 */
std::string fault_fname(const char* io_type);

#endif
Loading