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

#include "reader.h"

#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>

#include <functional>

#include <android-base/file.h>
#include <android-base/unique_fd.h>

#include "utility.h"

namespace android {
namespace fs_mgr {

// Helper class for reading descriptors and memory buffers in the same manner.
class Reader {
  public:
    virtual ~Reader(){};
    virtual bool ReadFully(void* buffer, size_t length) = 0;
};

class FileReader final : public Reader {
  public:
    explicit FileReader(int fd) : fd_(fd) {}
    bool ReadFully(void* buffer, size_t length) override {
        return android::base::ReadFully(fd_, buffer, length);
    }

  private:
    int fd_;
};

class MemoryReader final : public Reader {
  public:
    MemoryReader(const void* buffer, size_t size)
        : buffer_(reinterpret_cast<const uint8_t*>(buffer)), size_(size), pos_(0) {}
    bool ReadFully(void* out, size_t length) override {
        if (size_ - pos_ < length) {
            errno = EINVAL;
            return false;
        }
        memcpy(out, buffer_ + pos_, length);
        pos_ += length;
        return true;
    }

  private:
    const uint8_t* buffer_;
    size_t size_;
    size_t pos_;
};

bool ParseGeometry(const void* buffer, LpMetadataGeometry* geometry) {
    static_assert(sizeof(*geometry) <= LP_METADATA_GEOMETRY_SIZE);
    memcpy(geometry, buffer, sizeof(*geometry));

    // Check the magic signature.
    if (geometry->magic != LP_METADATA_GEOMETRY_MAGIC) {
        LERROR << "Logical partition metadata has invalid geometry magic signature.";
        return false;
    }
    // Reject if the struct size is larger than what we compiled. This is so we
    // can compute a checksum with the |struct_size| field rather than using
    // sizeof.
    if (geometry->struct_size > sizeof(LpMetadataGeometry)) {
        LERROR << "Logical partition metadata has unrecognized fields.";
        return false;
    }
    // Recompute and check the CRC32.
    {
        LpMetadataGeometry temp = *geometry;
        memset(&temp.checksum, 0, sizeof(temp.checksum));
        SHA256(&temp, temp.struct_size, temp.checksum);
        if (memcmp(temp.checksum, geometry->checksum, sizeof(temp.checksum)) != 0) {
            LERROR << "Logical partition metadata has invalid geometry checksum.";
            return false;
        }
    }
    // Check that the struct size is equal (this will have to change if we ever
    // change the struct size in a release).
    if (geometry->struct_size != sizeof(LpMetadataGeometry)) {
        LERROR << "Logical partition metadata has invalid struct size.";
        return false;
    }
    if (geometry->metadata_slot_count == 0) {
        LERROR << "Logical partition metadata has invalid slot count.";
        return false;
    }
    if (geometry->metadata_max_size % LP_SECTOR_SIZE != 0) {
        LERROR << "Metadata max size is not sector-aligned.";
        return false;
    }

    // Check that the metadata area and logical partition areas don't overlap.
    int64_t end_of_metadata =
            GetPrimaryMetadataOffset(*geometry, geometry->metadata_slot_count - 1) +
            geometry->metadata_max_size;
    if (uint64_t(end_of_metadata) > geometry->first_logical_sector * LP_SECTOR_SIZE) {
        LERROR << "Logical partition metadata overlaps with logical partition contents.";
        return false;
    }
    return true;
}

bool ReadPrimaryGeometry(int fd, LpMetadataGeometry* geometry) {
    // Read the first 4096 bytes.
    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
    if (SeekFile64(fd, 0, SEEK_SET) < 0) {
        PERROR << __PRETTY_FUNCTION__ << "lseek failed";
        return false;
    }
    if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
        PERROR << __PRETTY_FUNCTION__ << "read " << LP_METADATA_GEOMETRY_SIZE << " bytes failed";
        return false;
    }
    return ParseGeometry(buffer.get(), geometry);
}

bool ReadBackupGeometry(int fd, LpMetadataGeometry* geometry) {
    // Try the backup copy in the last 4096 bytes.
    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
    if (SeekFile64(fd, -LP_METADATA_GEOMETRY_SIZE, SEEK_END) < 0) {
        PERROR << __PRETTY_FUNCTION__ << "lseek failed, offset " << -LP_METADATA_GEOMETRY_SIZE;
        return false;
    }
    if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
        PERROR << __PRETTY_FUNCTION__ << "backup read " << LP_METADATA_GEOMETRY_SIZE
               << " bytes failed";
        return false;
    }
    return ParseGeometry(buffer.get(), geometry);
}

// Read and validate geometry information from a block device that holds
// logical partitions. If the information is corrupted, this will attempt
// to read it from a secondary backup location.
bool ReadLogicalPartitionGeometry(int fd, LpMetadataGeometry* geometry) {
    if (ReadPrimaryGeometry(fd, geometry)) {
        return true;
    }
    return ReadBackupGeometry(fd, geometry);
}

static bool ValidateTableBounds(const LpMetadataHeader& header,
                                const LpMetadataTableDescriptor& table) {
    if (table.offset > header.tables_size) {
        return false;
    }
    uint64_t table_size = uint64_t(table.num_entries) * table.entry_size;
    if (header.tables_size - table.offset < table_size) {
        return false;
    }
    return true;
}

static bool ValidateMetadataHeader(const LpMetadataHeader& header) {
    // To compute the header's checksum, we have to temporarily set its checksum
    // field to 0.
    {
        LpMetadataHeader temp = header;
        memset(&temp.header_checksum, 0, sizeof(temp.header_checksum));
        SHA256(&temp, sizeof(temp), temp.header_checksum);
        if (memcmp(temp.header_checksum, header.header_checksum, sizeof(temp.header_checksum)) != 0) {
            LERROR << "Logical partition metadata has invalid checksum.";
            return false;
        }
    }

    // Do basic validation of key metadata bits.
    if (header.magic != LP_METADATA_HEADER_MAGIC) {
        LERROR << "Logical partition metadata has invalid magic value.";
        return false;
    }
    // Check that the version is compatible.
    if (header.major_version != LP_METADATA_MAJOR_VERSION ||
        header.minor_version > LP_METADATA_MINOR_VERSION) {
        LERROR << "Logical partition metadata has incompatible version.";
        return false;
    }
    if (!ValidateTableBounds(header, header.partitions) ||
        !ValidateTableBounds(header, header.extents) ||
        !ValidateTableBounds(header, header.groups)) {
        LERROR << "Logical partition metadata has invalid table bounds.";
        return false;
    }
    // Check that table entry sizes can accomodate their respective structs. If
    // table sizes change, these checks will have to be adjusted.
    if (header.partitions.entry_size != sizeof(LpMetadataPartition)) {
        LERROR << "Logical partition metadata has invalid partition table entry size.";
        return false;
    }
    if (header.extents.entry_size != sizeof(LpMetadataExtent)) {
        LERROR << "Logical partition metadata has invalid extent table entry size.";
        return false;
    }
    if (header.groups.entry_size != sizeof(LpMetadataPartitionGroup)) {
        LERROR << "Logical partition metadata has invalid group table entry size.";
        return false;
    }
    return true;
}

// Parse and validate all metadata at the current position in the given file
// descriptor.
static std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry,
                                                 Reader* reader) {
    // First read and validate the header.
    std::unique_ptr<LpMetadata> metadata = std::make_unique<LpMetadata>();
    if (!reader->ReadFully(&metadata->header, sizeof(metadata->header))) {
        PERROR << __PRETTY_FUNCTION__ << "read " << sizeof(metadata->header) << "bytes failed";
        return nullptr;
    }
    if (!ValidateMetadataHeader(metadata->header)) {
        return nullptr;
    }
    metadata->geometry = geometry;

    LpMetadataHeader& header = metadata->header;

    // Read the metadata payload. Allocation is fallible in case the metadata is
    // corrupt and has some huge value.
    std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[header.tables_size]);
    if (!buffer) {
        LERROR << "Out of memory reading logical partition tables.";
        return nullptr;
    }
    if (!reader->ReadFully(buffer.get(), header.tables_size)) {
        PERROR << __PRETTY_FUNCTION__ << "read " << header.tables_size << "bytes failed";
        return nullptr;
    }

    uint8_t checksum[32];
    SHA256(buffer.get(), header.tables_size, checksum);
    if (memcmp(checksum, header.tables_checksum, sizeof(checksum)) != 0) {
        LERROR << "Logical partition metadata has invalid table checksum.";
        return nullptr;
    }

    // ValidateTableSize ensured that |cursor| is valid for the number of
    // entries in the table.
    uint8_t* cursor = buffer.get() + header.partitions.offset;
    for (size_t i = 0; i < header.partitions.num_entries; i++) {
        LpMetadataPartition partition;
        memcpy(&partition, cursor, sizeof(partition));
        cursor += header.partitions.entry_size;

        if (partition.attributes & ~LP_PARTITION_ATTRIBUTE_MASK) {
            LERROR << "Logical partition has invalid attribute set.";
            return nullptr;
        }
        if (partition.first_extent_index + partition.num_extents > header.extents.num_entries) {
            LERROR << "Logical partition has invalid extent list.";
            return nullptr;
        }
        if (partition.group_index >= header.groups.num_entries) {
            LERROR << "Logical partition has invalid group index.";
            return nullptr;
        }

        metadata->partitions.push_back(partition);
    }

    cursor = buffer.get() + header.extents.offset;
    for (size_t i = 0; i < header.extents.num_entries; i++) {
        LpMetadataExtent extent;
        memcpy(&extent, cursor, sizeof(extent));
        cursor += header.extents.entry_size;

        metadata->extents.push_back(extent);
    }

    cursor = buffer.get() + header.groups.offset;
    for (size_t i = 0; i < header.groups.num_entries; i++) {
        LpMetadataPartitionGroup group = {};
        memcpy(&group, cursor, sizeof(group));
        cursor += header.groups.entry_size;

        metadata->groups.push_back(group);
    }

    return metadata;
}

std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, const void* buffer,
                                          size_t size) {
    MemoryReader reader(buffer, size);
    return ParseMetadata(geometry, &reader);
}

std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, int fd) {
    FileReader reader(fd);
    return ParseMetadata(geometry, &reader);
}

std::unique_ptr<LpMetadata> ReadPrimaryMetadata(int fd, const LpMetadataGeometry& geometry,
                                                uint32_t slot_number) {
    int64_t offset = GetPrimaryMetadataOffset(geometry, slot_number);
    if (SeekFile64(fd, offset, SEEK_SET) < 0) {
        PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << offset;
        return nullptr;
    }
    return ParseMetadata(geometry, fd);
}

std::unique_ptr<LpMetadata> ReadBackupMetadata(int fd, const LpMetadataGeometry& geometry,
                                               uint32_t slot_number) {
    int64_t offset = GetBackupMetadataOffset(geometry, slot_number);
    if (SeekFile64(fd, offset, SEEK_END) < 0) {
        PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << offset;
        return nullptr;
    }
    return ParseMetadata(geometry, fd);
}

std::unique_ptr<LpMetadata> ReadMetadata(int fd, uint32_t slot_number) {
    LpMetadataGeometry geometry;
    if (!ReadLogicalPartitionGeometry(fd, &geometry)) {
        return nullptr;
    }

    if (slot_number >= geometry.metadata_slot_count) {
        LERROR << __PRETTY_FUNCTION__ << "invalid metadata slot number";
        return nullptr;
    }

    // Read the primary copy, and if that fails, try the backup.
    std::unique_ptr<LpMetadata> metadata = ReadPrimaryMetadata(fd, geometry, slot_number);
    if (metadata) {
        return metadata;
    }
    return ReadBackupMetadata(fd, geometry, slot_number);
}

std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot_number) {
    android::base::unique_fd fd(open(block_device, O_RDONLY));
    if (fd < 0) {
        PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
        return nullptr;
    }
    return ReadMetadata(fd, slot_number);
}

static std::string NameFromFixedArray(const char* name, size_t buffer_size) {
    // If the end of the buffer has a null character, it's safe to assume the
    // buffer is null terminated. Otherwise, we cap the string to the input
    // buffer size.
    if (name[buffer_size - 1] == '\0') {
        return std::string(name);
    }
    return std::string(name, buffer_size);
}

std::string GetPartitionName(const LpMetadataPartition& partition) {
    return NameFromFixedArray(partition.name, sizeof(partition.name));
}

std::string GetPartitionGroupName(const LpMetadataPartitionGroup& group) {
    return NameFromFixedArray(group.name, sizeof(group.name));
}

}  // namespace fs_mgr
}  // namespace android
