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

#define LOG_TAG "Checkpoint"
#include "Checkpoint.h"
#include "FsCrypt.h"
#include "KeyStorage.h"
#include "VoldUtil.h"
#include "VolumeManager.h"

#include <fstream>
#include <list>
#include <memory>
#include <string>
#include <thread>
#include <vector>

#include <BootControlClient.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/unique_fd.h>
#include <cutils/android_reboot.h>
#include <fcntl.h>
#include <fs_mgr.h>
#include <linux/fs.h>
#include <mntent.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <unistd.h>

using android::base::GetBoolProperty;
using android::base::GetUintProperty;
using android::base::SetProperty;
using android::binder::Status;
using android::fs_mgr::Fstab;
using android::fs_mgr::ReadFstabFromFile;
using android::hal::BootControlClient;

namespace android {
namespace vold {

namespace {
const std::string kMetadataCPFile = "/metadata/vold/checkpoint";

binder::Status error(const std::string& msg) {
    PLOG(ERROR) << msg;
    return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str()));
}

binder::Status error(int error, const std::string& msg) {
    LOG(ERROR) << msg;
    return binder::Status::fromServiceSpecificError(error, String8(msg.c_str()));
}

bool setBowState(std::string const& block_device, std::string const& state) {
    std::string bow_device = fs_mgr_find_bow_device(block_device);
    if (bow_device.empty()) return false;

    if (!android::base::WriteStringToFile(state, bow_device + "/bow/state")) {
        PLOG(ERROR) << "Failed to write to file " << bow_device + "/bow/state";
        return false;
    }

    return true;
}

// Do any work that was deferred until the userdata filesystem checkpoint was
// committed.  This work involves the deletion of resources that aren't covered
// by the userdata filesystem checkpoint, e.g. Keystore keys.
void DoCheckpointCommittedWork() {
    // Take the crypt lock to provide synchronization with the Binder calls that
    // operate on key directories.
    std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getCryptLock());

    DeferredCommitKeystoreKeys();
    fscrypt_deferred_fixate_ce_keys();
}

}  // namespace

Status cp_supportsCheckpoint(bool& result) {
    result = false;

    for (const auto& entry : fstab_default) {
        if (entry.fs_mgr_flags.checkpoint_blk || entry.fs_mgr_flags.checkpoint_fs) {
            result = true;
            return Status::ok();
        }
    }
    return Status::ok();
}

Status cp_supportsBlockCheckpoint(bool& result) {
    result = false;

    for (const auto& entry : fstab_default) {
        if (entry.fs_mgr_flags.checkpoint_blk) {
            result = true;
            return Status::ok();
        }
    }
    return Status::ok();
}

Status cp_supportsFileCheckpoint(bool& result) {
    result = false;

    for (const auto& entry : fstab_default) {
        if (entry.fs_mgr_flags.checkpoint_fs) {
            result = true;
            return Status::ok();
        }
    }
    return Status::ok();
}

Status cp_startCheckpoint(int retry) {
    bool result;
    if (!cp_supportsCheckpoint(result).isOk() || !result)
        return error(ENOTSUP, "Checkpoints not supported");

    if (retry < -1) return error(EINVAL, "Retry count must be more than -1");
    std::string content = std::to_string(retry + 1);
    if (retry == -1) {
        auto module = BootControlClient::WaitForService();
        if (module) {
            std::string suffix = module->GetSuffix(module->GetCurrentSlot());
            if (!suffix.empty()) content += " " + suffix;
        }
    }
    if (!android::base::WriteStringToFile(content, kMetadataCPFile))
        return error("Failed to write checkpoint file");
    return Status::ok();
}

namespace {

volatile bool isCheckpointing = false;
volatile bool isBow = true;

volatile bool needsCheckpointWasCalled = false;

// Protects isCheckpointing, needsCheckpointWasCalled and code that makes decisions based on status
// of isCheckpointing
std::mutex isCheckpointingLock;
}

Status cp_commitChanges() {
    std::lock_guard<std::mutex> lock(isCheckpointingLock);

    if (!isCheckpointing) {
        return Status::ok();
    }
    if (android::base::GetProperty("persist.vold.dont_commit_checkpoint", "0") == "1") {
        LOG(WARNING)
            << "NOT COMMITTING CHECKPOINT BECAUSE persist.vold.dont_commit_checkpoint IS 1";
        return Status::ok();
    }
    auto module = BootControlClient::WaitForService();
    if (module) {
        auto cr = module->MarkBootSuccessful();
        if (!cr.success)
            return error(EINVAL, "Error marking booted successfully: " + std::string(cr.errMsg));
        LOG(INFO) << "Marked slot as booted successfully.";
        // Clears the warm reset flag for next reboot.
        if (!SetProperty("ota.warm_reset", "0")) {
            LOG(WARNING) << "Failed to reset the warm reset flag";
        }
    } else {
        LOG(ERROR) << "Failed to get BootControl HAL, not marking slot as successful.";
    }
    // Must take action for list of mounted checkpointed things here
    // To do this, we walk the list of mounted file systems.
    // But we also need to get the matching fstab entries to see
    // the original flags
    std::string err_str;

    Fstab mounts;
    if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
        return error(EINVAL, "Failed to get /proc/mounts");
    }

    // Walk mounted file systems
    for (const auto& mount_rec : mounts) {
        const auto fstab_rec =
                GetEntryForMountPoint(&fstab_default, mount_rec.mount_point, mount_rec.fs_type);
        if (!fstab_rec) continue;

        if (fstab_rec->fs_mgr_flags.checkpoint_fs) {
            if (fstab_rec->fs_type == "f2fs") {
                std::string options = mount_rec.fs_options + ",checkpoint=enable";
                if (mount(mount_rec.blk_device.c_str(), mount_rec.mount_point.c_str(), "none",
                          MS_REMOUNT | fstab_rec->flags, options.c_str())) {
                    return error(EINVAL, "Failed to remount");
                }
            }
        } else if (fstab_rec->fs_mgr_flags.checkpoint_blk && isBow) {
            if (!setBowState(mount_rec.blk_device, "2"))
                return error(EINVAL, "Failed to set bow state");
        }
    }
    SetProperty("vold.checkpoint_committed", "1");
    LOG(INFO) << "Checkpoint has been committed.";
    isCheckpointing = false;
    if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
        return error(err_str.c_str());

    std::thread(DoCheckpointCommittedWork).detach();
    return Status::ok();
}

namespace {
void abort_metadata_file() {
    std::string oldContent, newContent;
    int retry = 0;
    struct stat st;
    int result = stat(kMetadataCPFile.c_str(), &st);

    // If the file doesn't exist, we aren't managing a checkpoint retry counter
    if (result != 0) return;
    if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
        PLOG(ERROR) << "Failed to read checkpoint file";
        return;
    }
    std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));

    if (!android::base::ParseInt(retryContent, &retry)) {
        PLOG(ERROR) << "Could not parse retry count";
        return;
    }
    if (retry > 0) {
        newContent = "0";
        if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
            PLOG(ERROR) << "Could not write checkpoint file";
    }
}
}  // namespace

void cp_abortChanges(const std::string& message, bool retry) {
    if (!cp_needsCheckpoint()) return;
    if (!retry) abort_metadata_file();
    android_reboot(ANDROID_RB_RESTART2, 0, message.c_str());
}

bool cp_needsRollback() {
    std::string content;
    bool ret;

    ret = android::base::ReadFileToString(kMetadataCPFile, &content);
    if (ret) {
        if (content == "0") return true;
        if (content.substr(0, 3) == "-1 ") {
            std::string oldSuffix = content.substr(3);
            auto module = BootControlClient::WaitForService();
            std::string newSuffix;

            if (module) {
                newSuffix = module->GetSuffix(module->GetCurrentSlot());
                if (oldSuffix == newSuffix) return true;
            }
        }
    }
    return false;
}

bool cp_needsCheckpoint() {
    std::lock_guard<std::mutex> lock(isCheckpointingLock);

    // Make sure we only return true during boot. See b/138952436 for discussion
    if (needsCheckpointWasCalled) return isCheckpointing;
    needsCheckpointWasCalled = true;

    bool ret;
    std::string content;
    auto module = BootControlClient::WaitForService();

    if (isCheckpointing) return isCheckpointing;
    // In case of INVALID slot or other failures, we do not perform checkpoint.
    if (module && !module->IsSlotMarkedSuccessful(module->GetCurrentSlot()).value_or(true)) {
        isCheckpointing = true;
        return true;
    }
    ret = android::base::ReadFileToString(kMetadataCPFile, &content);
    if (ret) {
        ret = content != "0";
        isCheckpointing = ret;
        return ret;
    }
    return false;
}

bool cp_isCheckpointing() {
    return isCheckpointing;
}

namespace {
const std::string kSleepTimeProp = "ro.sys.cp_msleeptime";
const uint32_t msleeptime_default = 1000;  // 1 s
const uint32_t max_msleeptime = 3600000;   // 1 h

const std::string kMinFreeBytesProp = "ro.sys.cp_min_free_bytes";
const uint64_t min_free_bytes_default = 100 * (1 << 20);  // 100 MiB

const std::string kCommitOnFullProp = "ro.sys.cp_commit_on_full";
const bool commit_on_full_default = true;

static void cp_healthDaemon(std::string mnt_pnt, std::string blk_device, bool is_fs_cp) {
    struct statvfs data;
    uint32_t msleeptime = GetUintProperty(kSleepTimeProp, msleeptime_default, max_msleeptime);
    uint64_t min_free_bytes =
        GetUintProperty(kMinFreeBytesProp, min_free_bytes_default, (uint64_t)-1);
    bool commit_on_full = GetBoolProperty(kCommitOnFullProp, commit_on_full_default);

    struct timespec req;
    req.tv_sec = msleeptime / 1000;
    msleeptime %= 1000;
    req.tv_nsec = msleeptime * 1000000;
    while (isCheckpointing) {
        uint64_t free_bytes = 0;
        if (is_fs_cp) {
            statvfs(mnt_pnt.c_str(), &data);
            free_bytes = ((uint64_t) data.f_bavail) * data.f_frsize;
        } else {
            std::string bow_device = fs_mgr_find_bow_device(blk_device);
            if (!bow_device.empty()) {
                std::string content;
                if (android::base::ReadFileToString(bow_device + "/bow/free", &content)) {
                    free_bytes = std::strtoull(content.c_str(), NULL, 10);
                }
            }
        }
        if (free_bytes < min_free_bytes) {
            if (commit_on_full) {
                LOG(INFO) << "Low space for checkpointing. Commiting changes";
                cp_commitChanges();
                break;
            } else {
                LOG(INFO) << "Low space for checkpointing. Rebooting";
                cp_abortChanges("checkpoint,low_space", false);
                break;
            }
        }
        nanosleep(&req, NULL);
    }
}

}  // namespace

Status cp_prepareCheckpoint() {
    // Log to notify CTS - see b/137924328 for context
    LOG(INFO) << "cp_prepareCheckpoint called";
    std::lock_guard<std::mutex> lock(isCheckpointingLock);
    if (!isCheckpointing) {
        return Status::ok();
    }

    Fstab mounts;
    if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
        return error(EINVAL, "Failed to get /proc/mounts");
    }

    for (const auto& mount_rec : mounts) {
        const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
        if (!fstab_rec) continue;

        if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
            android::base::unique_fd fd(
                TEMP_FAILURE_RETRY(open(mount_rec.mount_point.c_str(), O_RDONLY | O_CLOEXEC)));
            if (fd == -1) {
                PLOG(ERROR) << "Failed to open mount point" << mount_rec.mount_point;
                continue;
            }

            struct fstrim_range range = {};
            range.len = ULLONG_MAX;
            nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
            if (ioctl(fd, FITRIM, &range)) {
                PLOG(ERROR) << "Failed to trim " << mount_rec.mount_point;
                continue;
            }
            nsecs_t time = systemTime(SYSTEM_TIME_BOOTTIME) - start;
            LOG(INFO) << "Trimmed " << range.len << " bytes on " << mount_rec.mount_point << " in "
                      << nanoseconds_to_milliseconds(time) << "ms for checkpoint";

            isBow &= setBowState(mount_rec.blk_device, "1");
        }
        if (fstab_rec->fs_mgr_flags.checkpoint_blk || fstab_rec->fs_mgr_flags.checkpoint_fs) {
            std::thread(cp_healthDaemon, std::string(mount_rec.mount_point),
                        std::string(mount_rec.blk_device),
                        fstab_rec->fs_mgr_flags.checkpoint_fs == 1)
                .detach();
        }
    }
    return Status::ok();
}

namespace {
const int kSectorSize = 512;

typedef uint64_t sector_t;

struct log_entry {
    sector_t source;  // in sectors of size kSectorSize
    sector_t dest;    // in sectors of size kSectorSize
    uint32_t size;    // in bytes
    uint32_t checksum;
} __attribute__((packed));

struct log_sector_v1_0 {
    uint32_t magic;
    uint16_t header_version;
    uint16_t header_size;
    uint32_t block_size;
    uint32_t count;
    uint32_t sequence;
    uint64_t sector0;
} __attribute__((packed));

// MAGIC is BOW in ascii
const int kMagic = 0x00574f42;
// Partially restored MAGIC is WOB in ascii
const int kPartialRestoreMagic = 0x00424f57;

void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
    static uint32_t table[0x100] = {
        0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
        0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
        0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
        0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
        0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
        0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
        0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
        0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
        0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
        0xB6662D3D,

        0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
        0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
        0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
        0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
        0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
        0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
        0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
        0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
        0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
        0xC0BA6CAD,

        0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
        0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
        0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
        0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
        0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
        0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
        0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
        0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
        0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
        0x5BDEAE1D,

        0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
        0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
        0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
        0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
        0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
        0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
        0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
        0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
        0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
        0x2D02EF8D};

    for (size_t i = 0; i < n_bytes; ++i) {
        *crc ^= ((uint8_t*)data)[i];
        *crc = table[(uint8_t)*crc] ^ *crc >> 8;
    }
}

// A map of relocations.
// The map must be initialized so that relocations[0] = 0
// During restore, we replay the log records in reverse, copying from dest to
// source
// To validate, we must be able to read the 'dest' sectors as though they had
// been copied but without actually copying. This map represents how the sectors
// would have been moved. To read a sector s, find the index <= s and read
// relocations[index] + s - index
typedef std::map<sector_t, sector_t> Relocations;

void relocate(Relocations& relocations, sector_t dest, sector_t source, int count) {
    // Find first one we're equal to or greater than
    auto s = --relocations.upper_bound(source);

    // Take slice
    Relocations slice;
    slice[dest] = source - s->first + s->second;
    ++s;

    // Add rest of elements
    for (; s != relocations.end() && s->first < source + count; ++s)
        slice[dest - source + s->first] = s->second;

    // Split range at end of dest
    auto dest_end = --relocations.upper_bound(dest + count);
    relocations[dest + count] = dest + count - dest_end->first + dest_end->second;

    // Remove all elements in [dest, dest + count)
    relocations.erase(relocations.lower_bound(dest), relocations.lower_bound(dest + count));

    // Add new elements
    relocations.insert(slice.begin(), slice.end());
}

// A map of sectors that have been written to.
// The final entry must always be False.
// When we restart the restore after an interruption, we must take care that
// when we copy from dest to source, that the block we copy to was not
// previously copied from.
// i e. A->B C->A; If we replay this sequence, we end up copying C->B
// We must save our partial result whenever we finish a page, or when we copy
// to a location that was copied from earlier (our source is an earlier dest)
typedef std::map<sector_t, bool> Used_Sectors;

bool checkCollision(Used_Sectors& used_sectors, sector_t start, sector_t end) {
    auto second_overlap = used_sectors.upper_bound(start);
    auto first_overlap = --second_overlap;

    if (first_overlap->second) {
        return true;
    } else if (second_overlap != used_sectors.end() && second_overlap->first < end) {
        return true;
    }
    return false;
}

void markUsed(Used_Sectors& used_sectors, sector_t start, sector_t end) {
    auto start_pos = used_sectors.insert_or_assign(start, true).first;
    auto end_pos = used_sectors.insert_or_assign(end, false).first;

    if (start_pos == used_sectors.begin() || !std::prev(start_pos)->second) {
        start_pos++;
    }
    if (std::next(end_pos) != used_sectors.end() && !std::next(end_pos)->second) {
        end_pos++;
    }
    if (start_pos->first < end_pos->first) {
        used_sectors.erase(start_pos, end_pos);
    }
}

// Restores the given log_entry's data from dest -> source
// If that entry is a log sector, set the magic to kPartialRestoreMagic and flush.
void restoreSector(int device_fd, Used_Sectors& used_sectors, std::vector<char>& ls_buffer,
                   log_entry* le, std::vector<char>& buffer) {
    log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);
    uint32_t index = le - ((log_entry*)&ls_buffer[ls.header_size]);
    int count = (le->size - 1) / kSectorSize + 1;

    if (checkCollision(used_sectors, le->source, le->source + count)) {
        fsync(device_fd);
        lseek64(device_fd, 0, SEEK_SET);
        ls.count = index + 1;
        ls.magic = kPartialRestoreMagic;
        write(device_fd, &ls_buffer[0], ls.block_size);
        fsync(device_fd);
        used_sectors.clear();
        used_sectors[0] = false;
    }

    markUsed(used_sectors, le->dest, le->dest + count);

    if (index == 0 && ls.sequence != 0) {
        log_sector_v1_0* next = reinterpret_cast<log_sector_v1_0*>(&buffer[0]);
        if (next->magic == kMagic) {
            next->magic = kPartialRestoreMagic;
        }
    }

    lseek64(device_fd, le->source * kSectorSize, SEEK_SET);
    write(device_fd, &buffer[0], le->size);

    if (index == 0) {
        fsync(device_fd);
    }
}

// Read from the device
// If we are validating, the read occurs as though the relocations had happened
// returns the amount asked for or an empty buffer on error. Partial reads are considered a failure
std::vector<char> relocatedRead(int device_fd, Relocations const& relocations, bool validating,
                                sector_t sector, uint32_t size, uint32_t block_size) {
    if (!validating) {
        std::vector<char> buffer(size);
        off64_t offset = sector * kSectorSize;
        if (lseek64(device_fd, offset, SEEK_SET) != offset) {
            return std::vector<char>();
        }
        if (read(device_fd, &buffer[0], size) != static_cast<ssize_t>(size)) {
            return std::vector<char>();
        }
        return buffer;
    }

    std::vector<char> buffer(size);
    for (uint32_t i = 0; i < size; i += block_size, sector += block_size / kSectorSize) {
        auto relocation = --relocations.upper_bound(sector);
        off64_t offset = (sector + relocation->second - relocation->first) * kSectorSize;
        if (lseek64(device_fd, offset, SEEK_SET) != offset) {
            return std::vector<char>();
        }
        if (read(device_fd, &buffer[i], block_size) != static_cast<ssize_t>(block_size)) {
            return std::vector<char>();
        }
    }

    return buffer;
}

}  // namespace

Status cp_restoreCheckpoint(const std::string& blockDevice, int restore_limit) {
    bool validating = true;
    std::string action = "Validating";
    int restore_count = 0;

    for (;;) {
        Relocations relocations;
        relocations[0] = 0;
        Status status = Status::ok();

        LOG(INFO) << action << " checkpoint on " << blockDevice;
        base::unique_fd device_fd(open(blockDevice.c_str(), O_RDWR | O_CLOEXEC));
        if (device_fd < 0) return error("Cannot open " + blockDevice);

        log_sector_v1_0 original_ls;
        if (read(device_fd, reinterpret_cast<char*>(&original_ls), sizeof(original_ls)) !=
            sizeof(original_ls)) {
            return error(EINVAL, "Cannot read sector");
        }
        if (original_ls.magic == kPartialRestoreMagic) {
            validating = false;
            action = "Restoring";
        } else if (original_ls.magic != kMagic) {
            return error(EINVAL, "No magic");
        }

        if (original_ls.block_size < sizeof(log_sector_v1_0)) {
            return error(EINVAL, "Block size is invalid");
        }

        LOG(INFO) << action << " " << original_ls.sequence << " log sectors";

        for (int sequence = original_ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
            auto ls_buffer = relocatedRead(device_fd, relocations, validating, 0,
                                           original_ls.block_size, original_ls.block_size);
            if (ls_buffer.size() != original_ls.block_size) {
                status = error(EINVAL, "Failed to read log sector");
                break;
            }
            log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);

            Used_Sectors used_sectors;
            used_sectors[0] = false;

            if (ls.magic != kMagic && (ls.magic != kPartialRestoreMagic || validating)) {
                status = error(EINVAL, "No magic");
                break;
            }

            if (ls.block_size != original_ls.block_size) {
                status = error(EINVAL, "Block size mismatch");
                break;
            }

            if ((int)ls.sequence != sequence) {
                status = error(EINVAL, "Expecting log sector " + std::to_string(sequence) +
                                           " but got " + std::to_string(ls.sequence));
                break;
            }

            if (ls.header_size < sizeof(log_sector_v1_0) || ls.header_size > ls.block_size) {
                status = error(EINVAL, "Log sector header size is invalid");
                break;
            }
            if (ls.count < 1 || ls.count > (ls.block_size - ls.header_size) / sizeof(log_entry)) {
                status = error(EINVAL, "Log sector count is invalid");
                break;
            }
            LOG(INFO) << action << " from log sector " << ls.sequence;
            for (log_entry* le =
                     reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]) + ls.count - 1;
                 le >= reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]); --le) {
                // This is very noisy - limit to DEBUG only
                LOG(VERBOSE) << action << " " << le->size << " bytes from sector " << le->dest
                             << " to " << le->source << " with checksum " << std::hex
                             << le->checksum;

                if (ls.block_size > UINT_MAX - le->size || le->size < ls.block_size) {
                    status = error(EINVAL, "log entry is invalid");
                    break;
                }
                auto buffer = relocatedRead(device_fd, relocations, validating, le->dest, le->size,
                                            ls.block_size);
                if (buffer.size() != le->size) {
                    status = error(EINVAL, "Failed to read sector");
                    break;
                }
                uint32_t checksum = le->source / (ls.block_size / kSectorSize);
                for (size_t i = 0; i < le->size; i += ls.block_size) {
                    crc32(&buffer[i], ls.block_size, &checksum);
                }

                if (le->checksum && checksum != le->checksum) {
                    status = error(EINVAL, "Checksums don't match");
                    break;
                }

                if (validating) {
                    relocate(relocations, le->source, le->dest, (le->size - 1) / kSectorSize + 1);
                } else {
                    restoreSector(device_fd, used_sectors, ls_buffer, le, buffer);
                    restore_count++;
                    if (restore_limit && restore_count >= restore_limit) {
                        status = error(EAGAIN, "Hit the test limit");
                        break;
                    }
                }
            }
        }

        if (!status.isOk()) {
            if (!validating) {
                LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
                return status;
            }

            LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
            auto buffer = relocatedRead(device_fd, relocations, false, original_ls.sector0,
                                        original_ls.block_size, original_ls.block_size);
            if (buffer.size() != original_ls.block_size) {
                return error(EINVAL, "Failed to read original sector");
            }

            if (lseek64(device_fd, 0, SEEK_SET) != 0) {
                return error(EINVAL, "Failed to seek to sector 0");
            }
            if (write(device_fd, &buffer[0], original_ls.block_size) !=
                static_cast<ssize_t>(original_ls.block_size)) {
                return error(EINVAL, "Failed to write original sector");
            }
            return Status::ok();
        }

        if (!validating) break;

        validating = false;
        action = "Restoring";
    }

    return Status::ok();
}

Status cp_markBootAttempt() {
    std::string oldContent, newContent;
    int retry = 0;
    struct stat st;
    int result = stat(kMetadataCPFile.c_str(), &st);

    // If the file doesn't exist, we aren't managing a checkpoint retry counter
    if (result != 0) return Status::ok();
    if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent))
        return error("Failed to read checkpoint file");
    std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));

    if (!android::base::ParseInt(retryContent, &retry))
        return error(EINVAL, "Could not parse retry count");
    if (retry > 0) {
        retry--;

        newContent = std::to_string(retry);
        if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
            return error("Could not write checkpoint file");
    }
    return Status::ok();
}

void cp_resetCheckpoint() {
    std::lock_guard<std::mutex> lock(isCheckpointingLock);
    needsCheckpointWasCalled = false;
}

}  // namespace vold
}  // namespace android
