/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "fs_mgr_dm_linear.h"

#include <inttypes.h>
#include <linux/dm-ioctl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>

#include <sstream>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <liblp/reader.h>

#include "fs_mgr_priv.h"
#include "fs_mgr_priv_dm_ioctl.h"

namespace android {
namespace fs_mgr {

std::string LogicalPartitionExtent::Serialize() const {
    // Note: we need to include an explicit null-terminator.
    std::string argv =
        android::base::StringPrintf("%s %" PRIu64, block_device_.c_str(), first_sector_);
    argv.push_back(0);

    // The kernel expects each target to be aligned.
    size_t spec_bytes = sizeof(struct dm_target_spec) + argv.size();
    size_t padding = ((spec_bytes + 7) & ~7) - spec_bytes;
    for (size_t i = 0; i < padding; i++) {
        argv.push_back(0);
    }

    struct dm_target_spec spec;
    spec.sector_start = logical_sector_;
    spec.length = num_sectors_;
    spec.status = 0;
    strcpy(spec.target_type, "linear");
    spec.next = sizeof(struct dm_target_spec) + argv.size();

    return std::string((char*)&spec, sizeof(spec)) + argv;
}

static bool LoadDmTable(int dm_fd, const LogicalPartition& partition) {
    // Combine all dm_target_spec buffers together.
    std::string target_string;
    for (const auto& extent : partition.extents) {
        target_string += extent.Serialize();
    }

    // Allocate the ioctl buffer.
    size_t buffer_size = sizeof(struct dm_ioctl) + target_string.size();
    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(buffer_size);

    // Initialize the ioctl buffer header, then copy our target specs in.
    struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer.get());
    fs_mgr_dm_ioctl_init(io, buffer_size, partition.name);
    io->target_count = partition.extents.size();
    if (partition.attributes & kPartitionReadonly) {
        io->flags |= DM_READONLY_FLAG;
    }
    memcpy(io + 1, target_string.c_str(), target_string.size());

    if (ioctl(dm_fd, DM_TABLE_LOAD, io)) {
        PERROR << "Failed ioctl() on DM_TABLE_LOAD, partition " << partition.name;
        return false;
    }
    return true;
}

static bool LoadTablesAndActivate(int dm_fd, const LogicalPartition& partition) {
    if (!LoadDmTable(dm_fd, partition)) {
        return false;
    }

    struct dm_ioctl io;
    return fs_mgr_dm_resume_table(&io, partition.name, dm_fd);
}

static bool CreateDmDeviceForPartition(int dm_fd, const LogicalPartition& partition) {
    struct dm_ioctl io;
    if (!fs_mgr_dm_create_device(&io, partition.name, dm_fd)) {
        return false;
    }
    if (!LoadTablesAndActivate(dm_fd, partition)) {
        // Remove the device rather than leave it in an inactive state.
        fs_mgr_dm_destroy_device(&io, partition.name, dm_fd);
        return false;
    }

    LINFO << "Created device-mapper device: " << partition.name;
    return true;
}

bool CreateLogicalPartitions(const LogicalPartitionTable& table) {
    android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDWR));
    if (dm_fd < 0) {
        PLOG(ERROR) << "failed to open /dev/device-mapper";
        return false;
    }
    for (const auto& partition : table.partitions) {
        if (!CreateDmDeviceForPartition(dm_fd, partition)) {
            LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name;
            return false;
        }
    }
    return true;
}

std::unique_ptr<LogicalPartitionTable> LoadPartitionsFromDeviceTree() {
    return nullptr;
}

bool CreateLogicalPartitions(const std::string& block_device) {
    uint32_t slot = SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
    auto metadata = ReadMetadata(block_device.c_str(), slot);
    if (!metadata) {
        LOG(ERROR) << "Could not read partition table.";
        return true;
    }

    LogicalPartitionTable table;
    for (const auto& partition : metadata->partitions) {
        LogicalPartition new_partition;
        new_partition.name = GetPartitionName(partition);
        new_partition.attributes = partition.attributes;
        for (size_t i = 0; i < partition.num_extents; i++) {
            const auto& extent = metadata->extents[partition.first_extent_index + i];
            new_partition.extents.emplace_back(new_partition.num_sectors, extent.target_data,
                                               extent.num_sectors, block_device.c_str());
            new_partition.num_sectors += extent.num_sectors;
        }
        table.partitions.push_back(new_partition);
    }

    return CreateLogicalPartitions(table);
}

}  // namespace fs_mgr
}  // namespace android
