// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <inttypes.h>

#include "fvm/container.h"

static LZ4F_preferences_t lz4_prefs = {
    .frameInfo = {
        .blockSizeID = LZ4F_max64KB,
        .blockMode = LZ4F_blockIndependent,
    },
    .compressionLevel = 0,
};

zx_status_t SparseContainer::Create(const char* path, size_t slice_size, uint32_t flags,
                                    fbl::unique_ptr<SparseContainer>* out) {
    fbl::AllocChecker ac;
    fbl::unique_ptr<SparseContainer> sparseContainer(new (&ac) SparseContainer(path, slice_size,
                                                                               flags));
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    zx_status_t status;
    if ((status = sparseContainer->Init()) != ZX_OK) {
        return status;
    }

    *out = fbl::move(sparseContainer);
    return ZX_OK;
}

SparseContainer::SparseContainer(const char* path, uint64_t slice_size, uint32_t flags)
    : Container(path, slice_size, flags), valid_(false), disk_size_(0),
      extent_size_(0) {
    fd_.reset(open(path, O_CREAT | O_RDWR, 0666));

    if (!fd_) {
        fprintf(stderr, "Failed to open sparse data path\n");
        return;
    }

    struct stat s;
    if (fstat(fd_.get(), &s) < 0) {
        fprintf(stderr, "Failed to stat %s\n", path);
        return;
    }

    if (s.st_size > 0) {
        disk_size_ = s.st_size;

        if (read(fd_.get(), &image_, sizeof(fvm::sparse_image_t)) != sizeof(fvm::sparse_image_t)) {
            fprintf(stderr, "SparseContainer: Failed to read the sparse header\n");
            return;
        }

        if (image_.flags & fvm::kSparseFlagLz4) {
            return;
        }

        extent_size_ = disk_size_ - image_.header_length;

        for (unsigned i = 0; i < image_.partition_count; i++) {
            partition_info_t partition;
            partitions_.push_back(fbl::move(partition));
            if (read(fd_.get(), &partitions_[i].descriptor, sizeof(fvm::partition_descriptor_t)) !=
                    sizeof(fvm::partition_descriptor_t)) {
                fprintf(stderr, "SparseContainer: Failed to read partition %u\n", i);
                return;
            }

            for (unsigned j = 0; j < partitions_[i].descriptor.extent_count; j++) {
                fvm::extent_descriptor_t extent;
                partitions_[i].extents.push_back(extent);
                if (read(fd_.get(), &partitions_[i].extents[j], sizeof(fvm::extent_descriptor_t)) !=
                        sizeof(fvm::extent_descriptor_t)) {
                    fprintf(stderr, "SparseContainer: Failed to read extent\n");
                    return;
                }
            }
        }

        valid_ = true;
        xprintf("Successfully read from existing sparse data container.\n");
    }
}

SparseContainer::~SparseContainer() = default;

zx_status_t SparseContainer::Init() {
    image_.magic = fvm::kSparseFormatMagic;
    image_.version = fvm::kSparseFormatVersion;
    image_.slice_size = slice_size_;
    image_.partition_count = 0;
    image_.header_length = sizeof(fvm::sparse_image_t);
    image_.flags = flags_;
    partitions_.reset();
    dirty_ = true;
    valid_ = true;
    extent_size_ = 0;
    xprintf("Initialized new sparse data container.\n");
    return ZX_OK;
}

zx_status_t SparseContainer::Verify() const {
    if (!valid_) {
        fprintf(stderr, "SparseContainer: Found invalid container\n");
        return ZX_ERR_INTERNAL;
    }
    if (image_.magic != fvm::kSparseFormatMagic) {
        fprintf(stderr, "SparseContainer: Bad magic\n");
        return ZX_ERR_IO;
    }

    xprintf("Slice size is %" PRIu64 "\n", image_.slice_size);
    xprintf("Found %" PRIu64 " partitions\n", image_.partition_count);

    off_t start = 0;
    off_t end = image_.header_length;
    for (unsigned i = 0; i < image_.partition_count; i++) {
        fbl::Vector<size_t> extent_lengths;
        start = end;
        xprintf("Found partition %u with %u extents\n", i,
               partitions_[i].descriptor.extent_count);

        for (unsigned j = 0; j < partitions_[i].descriptor.extent_count; j++) {
            extent_lengths.push_back(partitions_[i].extents[j].extent_length);
            end += partitions_[i].extents[j].extent_length;
        }

        zx_status_t status;
        disk_format_t part;
        if ((status = Format::Detect(fd_.get(), start, &part)) != ZX_OK) {
            return status;
        }

        fbl::unique_fd dupfd(dup(fd_.get()));
        if (!dupfd) {
            fprintf(stderr, "Failed to duplicate fd\n");
            return ZX_ERR_INTERNAL;
        }

        if ((status = Format::Check(fbl::move(dupfd), start, end, extent_lengths, part)) != ZX_OK) {
            const char* name = reinterpret_cast<const char*>(partitions_[i].descriptor.name);
            fprintf(stderr, "%s fsck returned an error.\n", name);
            return status;
        }
    }

    if (end != disk_size_) {
        fprintf(stderr, "Header + extent sizes (%" PRIu64 ") do not match sparse file size "
                "(%zu)\n", end, disk_size_);
        return ZX_ERR_IO_DATA_INTEGRITY;
    }

    return ZX_OK;
}

zx_status_t SparseContainer::Commit() {
    if (!dirty_ || image_.partition_count == 0) {
        fprintf(stderr, "Commit: Nothing to write.\n");
        return ZX_OK;
    }

    // Reset file length to 0
    if (ftruncate(fd_.get(), 0) != 0) {
        fprintf(stderr, "Failed to truncate fvm container");
        return ZX_ERR_IO;
    }

    // Recalculate and verify header length
    uint64_t header_length = 0;

    if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
        fprintf(stderr, "Seek reset failed\n");
        return ZX_ERR_IO;
    }

    header_length += sizeof(fvm::sparse_image_t);
    if (write(fd_.get(), &image_, sizeof(fvm::sparse_image_t)) != sizeof(fvm::sparse_image_t)) {
        fprintf(stderr, "Write sparse image header failed\n");
        return ZX_ERR_IO;
    }

    for (unsigned i = 0; i < image_.partition_count; i++) {
        fvm::partition_descriptor_t partition = partitions_[i].descriptor;

        header_length += sizeof(fvm::partition_descriptor_t);
        if (write(fd_.get(), &partition, sizeof(fvm::partition_descriptor_t))
            != sizeof(fvm::partition_descriptor_t)) {
            fprintf(stderr, "Write partition failed\n");
            return ZX_ERR_IO;
        }

        for (unsigned j = 0; j < partition.extent_count; j++) {
            fvm::extent_descriptor_t extent = partitions_[i].extents[j];
            header_length += sizeof(fvm::extent_descriptor_t);
            if (write(fd_.get(), &extent, sizeof(fvm::extent_descriptor_t))
                != sizeof(fvm::extent_descriptor_t)) {
                fprintf(stderr, "Write extent failed\n");
                return ZX_ERR_IO;
            }
        }
    }

    if (header_length != image_.header_length) {
        fprintf(stderr, "Header length does not match!\n");
        return ZX_ERR_INTERNAL;
    }

    zx_status_t status;
    compression_t comp;
    if ((status = SetupCompression(&comp, extent_size_)) != ZX_OK) {
        return status;
    }

    // Write each partition out to sparse file
    for (unsigned i = 0; i < image_.partition_count; i++) {
        fvm::partition_descriptor_t partition = partitions_[i].descriptor;
        Format* format = partitions_[i].format.get();

        vslice_info_t vslice_info;
        // Write out each extent in the partition
        for (unsigned j = 0; j < partition.extent_count; j++) {
            if (format->GetVsliceRange(j, &vslice_info) != ZX_OK) {
                fprintf(stderr, "Unable to access partition extent\n");
                return ZX_ERR_OUT_OF_RANGE;
            }

            // Write out each block in the extent
            for (unsigned k = 0; k < vslice_info.block_count; k++) {
                if (format->FillBlock(vslice_info.block_offset + k) != ZX_OK) {
                    fprintf(stderr, "Failed to read block\n");
                    return ZX_ERR_IO;
                }

                if (WriteData(format->Data(), format->BlockSize(), &comp) != ZX_OK) {
                    fprintf(stderr, "Failed to write data to sparse file\n");
                    return ZX_ERR_IO;
                }
            }
        }
    }

    if ((status = FinishCompression(&comp)) != ZX_OK) {
        return status;
    }

    struct stat s;
    if (fstat(fd_.get(), &s) < 0) {
        fprintf(stderr, "Failed to stat container\n");
        return ZX_ERR_IO;
    }

    disk_size_ = s.st_size;
    xprintf("Successfully wrote sparse data to disk.\n");
    return ZX_OK;
}

size_t SparseContainer::SliceSize() const {
    return image_.slice_size;
}

zx_status_t SparseContainer::AddPartition(const char* path, const char* type_name) {
    fbl::unique_ptr<Format> format;
    zx_status_t status;

    if ((status = Format::Create(path, type_name, &format)) != ZX_OK) {
        fprintf(stderr, "Failed to initialize partition\n");
        return status;
    }

    if ((status = AllocatePartition(fbl::move(format))) != ZX_OK) {
        fprintf(stderr, "Sparse partition allocation failed\n");
        return status;
    }

    return ZX_OK;
}

zx_status_t SparseContainer::AllocatePartition(fbl::unique_ptr<Format> format) {
    partition_info_t partition;
    partition.descriptor.magic = fvm::kPartitionDescriptorMagic;
    format->Type(partition.descriptor.type);
    format->Name(reinterpret_cast<char*>(partition.descriptor.name));
    partition.descriptor.extent_count = 0;
    partition.descriptor.flags = flags_ & format->FlagMask();
    image_.header_length += sizeof(fvm::partition_descriptor_t);
    uint32_t part_index = image_.partition_count;

    zx_status_t status;
    if ((status = format->MakeFvmReady(SliceSize(), part_index)) != ZX_OK) {
        return status;
    }

    partitions_.push_back(fbl::move(partition));

    if (++image_.partition_count != partitions_.size()) {
        fprintf(stderr, "Unexpected number of partitions\n");
        return ZX_ERR_INTERNAL;
    }

    vslice_info_t vslice_info;
    unsigned i = 0;
    while ((status = format->GetVsliceRange(i++, &vslice_info)) == ZX_OK) {
        if ((status = AllocateExtent(part_index,
                                     vslice_info.vslice_start / format->BlocksPerSlice(),
                                     vslice_info.slice_count,
                                     vslice_info.block_count * format->BlockSize())) != ZX_OK) {
            return status;
        }
    }

    // This is expected if we have read all the other slices.
    if (status != ZX_ERR_OUT_OF_RANGE) {
        return status;
    }

    partitions_[part_index].format = fbl::move(format);
    return ZX_OK;
}

zx_status_t SparseContainer::AllocateExtent(uint32_t part_index, uint64_t slice_start,
                                            uint64_t slice_count, uint64_t extent_length) {
    if (part_index >= image_.partition_count) {
        fprintf(stderr, "Partition is not yet allocated\n");
        return ZX_ERR_OUT_OF_RANGE;
    }

    partition_info_t* partition = &partitions_[part_index];
    fvm::extent_descriptor_t extent;
    extent.magic = fvm::kExtentDescriptorMagic;
    extent.slice_start = slice_start;
    extent.slice_count = slice_count;
    extent.extent_length = extent_length;
    partition->extents.push_back(extent);

    if (partition->extents.size() != ++partition->descriptor.extent_count) {
        fprintf(stderr, "Unexpected number of extents\n");
        return ZX_ERR_INTERNAL;
    }

    image_.header_length += sizeof(fvm::extent_descriptor_t);
    extent_size_ += extent_length;
    dirty_ = true;
    return ZX_OK;
}

zx_status_t SparseContainer::SetupCompression(compression_t* comp, size_t max_len) {
    if ((flags_ & fvm::kSparseFlagLz4) == 0) {
        return ZX_OK;
    }

    LZ4F_errorCode_t errc = LZ4F_createCompressionContext(&comp->cctx, LZ4F_VERSION);
    if (LZ4F_isError(errc)) {
        fprintf(stderr, "Could not create compression context: %s\n", LZ4F_getErrorName(errc));
        return ZX_ERR_INTERNAL;
    }

    size_t max = LZ4F_compressBound(max_len, &lz4_prefs);
    if (!comp->reset(max)) {
        return ZX_ERR_NO_MEMORY;
    }

    size_t r = LZ4F_compressBegin(comp->cctx, comp->buf(), comp->size(), &lz4_prefs);
    if (LZ4F_isError(r)) {
        fprintf(stderr, "Could not begin compression: %s\n", LZ4F_getErrorName(r));
        return ZX_ERR_INTERNAL;
    }

    comp->offset += r;
    return ZX_OK;
}

zx_status_t SparseContainer::WriteData(const void* data, size_t length, compression_t* comp) {
    if ((flags_ & fvm::kSparseFlagLz4) != 0) {
        size_t r = LZ4F_compressUpdate(comp->cctx, comp->buf(), comp->size(), data, length, NULL);
        if (LZ4F_isError(r)) {
            fprintf(stderr, "Could not compress data: %s\n", LZ4F_getErrorName(r));
            return ZX_ERR_INTERNAL;
        }

        comp->offset += r;
    } else if (write(fd_.get(), data, length) != length) {
        return ZX_ERR_IO;
    }

    return ZX_OK;
}

zx_status_t SparseContainer::FinishCompression(compression_t* comp) {
    if ((flags_ & fvm::kSparseFlagLz4) == 0) {
        return ZX_OK;
    }

    size_t r = LZ4F_compressEnd(comp->cctx, comp->buf(), comp->size(), NULL);
    if (LZ4F_isError(r)) {
        fprintf(stderr, "Could not finish compression: %s\n", LZ4F_getErrorName(r));
        return ZX_ERR_INTERNAL;
    }

    comp->offset += r;
    if (write(fd_.get(), comp->data.get(), comp->offset) != comp->offset) {
        return ZX_ERR_IO;
    }

    LZ4F_errorCode_t errc = LZ4F_freeCompressionContext(comp->cctx);
    if (LZ4F_isError(errc)) {
        fprintf(stderr, "Could not free compression context: %s\n", LZ4F_getErrorName(errc));
        return ZX_ERR_INTERNAL;
    }

    return ZX_OK;
}
