/*
 * Copyright 2018 Google Inc.
 *
 * 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 "flash-ipmi.hpp"

#include <cstdio>
#include <fstream>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>

/* systemd service to kick start a service. */
static constexpr auto systemdService = "org.freedesktop.systemd1";
static constexpr auto systemdRoot = "/org/freedesktop/systemd1";
static constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager";
static constexpr auto verifyTarget = "verify_image.service";

using namespace phosphor::logging;

namespace
{

/**
 * Close a file pointer and set to null.
 *
 * @param[in] fd a pointer to your file handle.
 */
void closeFile(std::FILE** fd)
{
    if (!fd)
    {
        return;
    }

    if (*fd)
    {
        std::fclose(*fd);
        (*fd) = nullptr;
    }
}
} // namespace

void FlashUpdate::closeEverything()
{
    closeFile(&flashFd);
    closeFile(&hashFd);
}

void FlashUpdate::deleteEverything()
{
    /* Assumes you've called closeEverything() already */

    (void)std::remove(tmpPath.c_str());
    (void)std::remove(verifyPath.c_str());

    /* hashPath is optional. */
    if (!hashPath.empty())
    {
        (void)std::remove(hashPath.c_str());
    }
}

FlashUpdate::~FlashUpdate()
{
    /* Close without deleting.  This object can only be destroyed if the ipmi
     * daemon unloads it, by closing down.  In this event, we want the verified
     * file to live on.
     */
    closeEverything();
}

void FlashUpdate::abortEverything()
{
    closeEverything();

    /* Stop the systemd unit if it was running. */
    auto method = bus.new_method_call(systemdService, systemdRoot,
                                      systemdInterface, "StopUnit");
    method.append(verifyTarget);
    method.append("replace");
    bus.call_noreply(method);

    deleteEverything();
    return;
}

bool FlashUpdate::openEverything()
{
    flashFd = std::fopen(tmpPath.c_str(), "wb");
    if (flashFd == nullptr)
    {
        log<level::INFO>("Unable to open staging path",
                         entry("PATH=%s", tmpPath.c_str()));
        return false;
    }

    /* hash path is basically optional. */
    if (!hashPath.empty())
    {
        hashFd = std::fopen(hashPath.c_str(), "wb");
        if (hashFd == nullptr)
        {
            log<level::INFO>("Unable to open hash storage path",
                             entry("PATH=%s", hashPath.c_str()));
            closeFile(&flashFd);
            return false;
        }
    }

    return true;
}

/* Prepare to receive a BMC image and then a signature. */
bool FlashUpdate::start(uint32_t length)
{
    /* Close out and delete everything. */
    abortEverything();

    /* TODO: Validate request->length */
    flashLength = length;

    /* Start over! */
    return openEverything();
}

bool FlashUpdate::writeBlock(std::FILE* fd, uint32_t offset,
                             const std::vector<uint8_t>& bytes)
{
    /* Seek into position, let's assume fseek won't call if offset matches
     * position.
     */
    if (std::fseek(fd, offset, SEEK_SET))
    {
        log<level::ERR>("Unable to seek into file to write bytes.");
        return false;
    }

    /* Write the bytes. */
    auto written = std::fwrite(bytes.data(), 1, bytes.size(), fd);

    if (written != bytes.size())
    {
        log<level::ERR>("Unable to write all the bytes requested.");
        return false;
    }

    (void)std::fflush(fd);
    return true;
}

bool FlashUpdate::flashData(uint32_t offset, const std::vector<uint8_t>& bytes)
{
    if (flashFd)
    {
        return writeBlock(flashFd, offset, bytes);
    }

    return false;
}

bool FlashUpdate::flashFinish()
{
    /* If it's open, close it. */
    if (flashFd)
    {
        closeFile(&flashFd);
        return true;
    }

    return false;
}

bool FlashUpdate::startHash(uint32_t length)
{
    if (!hashFd)
    {
        return false;
    }

    hashLength = length;
    return true;
}

bool FlashUpdate::hashData(uint32_t offset, const std::vector<uint8_t>& bytes)
{
    if (hashFd)
    {
        return writeBlock(hashFd, offset, bytes);
    }

    return false;
}

bool FlashUpdate::hashFinish()
{
    if (hashFd)
    {
        closeFile(&hashFd);
        return true;
    }

    return false;
}

bool FlashUpdate::startDataVerification()
{
    auto method = bus.new_method_call(systemdService, systemdRoot,
                                      systemdInterface, "StartUnit");
    method.append(verifyTarget);
    method.append("replace");
    bus.call_noreply(method);

    return false;
}

bool FlashUpdate::abortUpdate()
{
    abortEverything();
    return true;
}

VerifyCheckResponse FlashUpdate::checkVerify()
{
    auto result = VerifyCheckResponse::other;
    std::ifstream ifs;
    ifs.open(verifyPath);
    if (ifs.good())
    {
        std::string status;
        /*
         * Check for the contents of the file, excepting:
         * running, success, or failed.
         */
        ifs >> status;
        if (status == "running")
        {
            result = VerifyCheckResponse::running;
        }
        else if (status == "success")
        {
            result = VerifyCheckResponse::success;
        }
        else if (status == "failed")
        {
            result = VerifyCheckResponse::failed;
        }
    }

    return result;
}
