// Copyright (c) 2012 The Chromium OS 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 "update_engine/filesystem_copier_action.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <cstdlib>
#include <map>
#include <string>
#include <vector>

#include <gio/gio.h>
#include <gio/gunixinputstream.h>
#include <gio/gunixoutputstream.h>
#include <glib.h>

#include "update_engine/glib_utils.h"
#include "update_engine/hardware_interface.h"
#include "update_engine/subprocess.h"
#include "update_engine/system_state.h"
#include "update_engine/utils.h"

using std::map;
using std::string;
using std::vector;

namespace chromeos_update_engine {

namespace {
const off_t kCopyFileBufferSize = 128 * 1024;
}  // namespace

FilesystemCopierAction::FilesystemCopierAction(
    SystemState* system_state,
    bool copying_kernel_install_path,
    bool verify_hash)
    : copying_kernel_install_path_(copying_kernel_install_path),
      verify_hash_(verify_hash),
      src_stream_(nullptr),
      dst_stream_(nullptr),
      read_done_(false),
      failed_(false),
      cancelled_(false),
      filesystem_size_(kint64max),
      system_state_(system_state) {
  // A lot of code works on the implicit assumption that processing is done on
  // exactly 2 ping-pong buffers.
  COMPILE_ASSERT(arraysize(buffer_) == 2 &&
                 arraysize(buffer_state_) == 2 &&
                 arraysize(buffer_valid_size_) == 2 &&
                 arraysize(canceller_) == 2,
                 ping_pong_buffers_not_two);
  for (int i = 0; i < 2; ++i) {
    buffer_state_[i] = kBufferStateEmpty;
    buffer_valid_size_[i] = 0;
    canceller_[i] = nullptr;
  }
}

void FilesystemCopierAction::PerformAction() {
  // Will tell the ActionProcessor we've failed if we return.
  ScopedActionCompleter abort_action_completer(processor_, this);

  if (!HasInputObject()) {
    LOG(ERROR) << "FilesystemCopierAction missing input object.";
    return;
  }
  install_plan_ = GetInputObject();

  // No need to copy on a resume.
  if (!verify_hash_ && install_plan_.is_resume) {
    // No copy or hash verification needed. Done!
    LOG(INFO) << "filesystem copying skipped on resumed update.";
    if (HasOutputPipe())
      SetOutputObject(install_plan_);
    abort_action_completer.set_code(ErrorCode::kSuccess);
    return;
  }

  if (copying_kernel_install_path_) {
    if (!system_state_->hardware()->MarkKernelUnbootable(
        install_plan_.kernel_install_path)) {
      PLOG(ERROR) << "Unable to clear kernel GPT boot flags: " <<
          install_plan_.kernel_install_path;
    }
  }

  if (!verify_hash_ && install_plan_.is_full_update) {
    // No copy or hash verification needed. Done!
    LOG(INFO) << "filesystem copying skipped on full update.";
    if (HasOutputPipe())
      SetOutputObject(install_plan_);
    abort_action_completer.set_code(ErrorCode::kSuccess);
    return;
  }

  const string destination = copying_kernel_install_path_ ?
      install_plan_.kernel_install_path :
      install_plan_.install_path;
  string source = verify_hash_ ? destination : copy_source_;
  if (source.empty()) {
    source = copying_kernel_install_path_ ?
        utils::KernelDeviceOfBootDevice(
            system_state_->hardware()->BootDevice()) :
        system_state_->hardware()->BootDevice();
  }
  int src_fd = open(source.c_str(), O_RDONLY);
  if (src_fd < 0) {
    PLOG(ERROR) << "Unable to open " << source << " for reading:";
    return;
  }

  if (!verify_hash_) {
    int dst_fd = open(destination.c_str(),
                      O_WRONLY | O_TRUNC | O_CREAT,
                    0644);
    if (dst_fd < 0) {
      close(src_fd);
      PLOG(ERROR) << "Unable to open " << install_plan_.install_path
                  << " for writing:";
      return;
    }

    dst_stream_ = g_unix_output_stream_new(dst_fd, TRUE);
  }

  DetermineFilesystemSize(src_fd);
  src_stream_ = g_unix_input_stream_new(src_fd, TRUE);

  for (int i = 0; i < 2; i++) {
    buffer_[i].resize(kCopyFileBufferSize);
    canceller_[i] = g_cancellable_new();
  }

  // Start the first read.
  SpawnAsyncActions();

  abort_action_completer.set_should_complete(false);
}

void FilesystemCopierAction::TerminateProcessing() {
  for (int i = 0; i < 2; i++) {
    if (canceller_[i]) {
      g_cancellable_cancel(canceller_[i]);
    }
  }
}

bool FilesystemCopierAction::IsCleanupPending() const {
  return (src_stream_ != nullptr);
}

void FilesystemCopierAction::Cleanup(ErrorCode code) {
  for (int i = 0; i < 2; i++) {
    g_object_unref(canceller_[i]);
    canceller_[i] = nullptr;
  }
  g_object_unref(src_stream_);
  src_stream_ = nullptr;
  if (dst_stream_) {
    g_object_unref(dst_stream_);
    dst_stream_ = nullptr;
  }
  if (cancelled_)
    return;
  if (code == ErrorCode::kSuccess && HasOutputPipe())
    SetOutputObject(install_plan_);
  processor_->ActionComplete(this, code);
}

void FilesystemCopierAction::AsyncReadReadyCallback(GObject *source_object,
                                                    GAsyncResult *res) {
  int index = buffer_state_[0] == kBufferStateReading ? 0 : 1;
  CHECK(buffer_state_[index] == kBufferStateReading);

  GError* error = nullptr;
  CHECK(canceller_[index]);
  cancelled_ = g_cancellable_is_cancelled(canceller_[index]) == TRUE;

  ssize_t bytes_read = g_input_stream_read_finish(src_stream_, res, &error);
  if (bytes_read < 0) {
    LOG(ERROR) << "Read failed: " << utils::GetAndFreeGError(&error);
    failed_ = true;
    buffer_state_[index] = kBufferStateEmpty;
  } else if (bytes_read == 0) {
    read_done_ = true;
    buffer_state_[index] = kBufferStateEmpty;
  } else {
    buffer_valid_size_[index] = bytes_read;
    buffer_state_[index] = kBufferStateFull;
    filesystem_size_ -= bytes_read;
  }
  SpawnAsyncActions();

  if (bytes_read > 0) {
    // If read_done_ is set, SpawnAsyncActions may finalize the hash so the hash
    // update below would happen too late.
    CHECK(!read_done_);
    if (!hasher_.Update(buffer_[index].data(), bytes_read)) {
      LOG(ERROR) << "Unable to update the hash.";
      failed_ = true;
    }
    if (verify_hash_) {
      buffer_state_[index] = kBufferStateEmpty;
    }
  }
}

void FilesystemCopierAction::StaticAsyncReadReadyCallback(
    GObject *source_object,
    GAsyncResult *res,
    gpointer user_data) {
  reinterpret_cast<FilesystemCopierAction*>(user_data)->
      AsyncReadReadyCallback(source_object, res);
}

void FilesystemCopierAction::AsyncWriteReadyCallback(GObject *source_object,
                                                     GAsyncResult *res) {
  int index = buffer_state_[0] == kBufferStateWriting ? 0 : 1;
  CHECK(buffer_state_[index] == kBufferStateWriting);
  buffer_state_[index] = kBufferStateEmpty;

  GError* error = nullptr;
  CHECK(canceller_[index]);
  cancelled_ = g_cancellable_is_cancelled(canceller_[index]) == TRUE;

  ssize_t bytes_written = g_output_stream_write_finish(dst_stream_,
                                                       res,
                                                       &error);

  if (bytes_written < static_cast<ssize_t>(buffer_valid_size_[index])) {
    if (bytes_written < 0) {
      LOG(ERROR) << "Write error: " << utils::GetAndFreeGError(&error);
    } else {
      LOG(ERROR) << "Wrote too few bytes: " << bytes_written
                 << " < " << buffer_valid_size_[index];
    }
    failed_ = true;
  }

  SpawnAsyncActions();
}

void FilesystemCopierAction::StaticAsyncWriteReadyCallback(
    GObject *source_object,
    GAsyncResult *res,
    gpointer user_data) {
  reinterpret_cast<FilesystemCopierAction*>(user_data)->
      AsyncWriteReadyCallback(source_object, res);
}

void FilesystemCopierAction::SpawnAsyncActions() {
  bool reading = false;
  bool writing = false;
  for (int i = 0; i < 2; i++) {
    if (buffer_state_[i] == kBufferStateReading) {
      reading = true;
    }
    if (buffer_state_[i] == kBufferStateWriting) {
      writing = true;
    }
  }
  if (failed_ || cancelled_) {
    if (!reading && !writing) {
      Cleanup(ErrorCode::kError);
    }
    return;
  }
  for (int i = 0; i < 2; i++) {
    if (!reading && !read_done_ && buffer_state_[i] == kBufferStateEmpty) {
      int64_t bytes_to_read = std::min(static_cast<int64_t>(buffer_[0].size()),
                                       filesystem_size_);
      g_input_stream_read_async(
          src_stream_,
          buffer_[i].data(),
          bytes_to_read,
          G_PRIORITY_DEFAULT,
          canceller_[i],
          &FilesystemCopierAction::StaticAsyncReadReadyCallback,
          this);
      reading = true;
      buffer_state_[i] = kBufferStateReading;
    } else if (!writing && !verify_hash_ &&
               buffer_state_[i] == kBufferStateFull) {
      g_output_stream_write_async(
          dst_stream_,
          buffer_[i].data(),
          buffer_valid_size_[i],
          G_PRIORITY_DEFAULT,
          canceller_[i],
          &FilesystemCopierAction::StaticAsyncWriteReadyCallback,
          this);
      writing = true;
      buffer_state_[i] = kBufferStateWriting;
    }
  }
  if (!reading && !writing) {
    // We're done!
    ErrorCode code = ErrorCode::kSuccess;
    if (hasher_.Finalize()) {
      LOG(INFO) << "Hash: " << hasher_.hash();
      if (verify_hash_) {
        if (copying_kernel_install_path_) {
          if (install_plan_.kernel_hash != hasher_.raw_hash()) {
            code = ErrorCode::kNewKernelVerificationError;
            LOG(ERROR) << "New kernel verification failed.";
          }
        } else {
          if (install_plan_.rootfs_hash != hasher_.raw_hash()) {
            code = ErrorCode::kNewRootfsVerificationError;
            LOG(ERROR) << "New rootfs verification failed.";
          }
        }
      } else {
        if (copying_kernel_install_path_) {
          install_plan_.kernel_hash = hasher_.raw_hash();
        } else {
          install_plan_.rootfs_hash = hasher_.raw_hash();
        }
      }
    } else {
      LOG(ERROR) << "Unable to finalize the hash.";
      code = ErrorCode::kError;
    }
    Cleanup(code);
  }
}

void FilesystemCopierAction::DetermineFilesystemSize(int fd) {
  if (verify_hash_) {
    filesystem_size_ = copying_kernel_install_path_ ?
        install_plan_.kernel_size : install_plan_.rootfs_size;
    LOG(INFO) << "Filesystem size: " << filesystem_size_;
    return;
  }
  filesystem_size_ = kint64max;
  int block_count = 0, block_size = 0;
  if (!copying_kernel_install_path_ &&
      utils::GetFilesystemSizeFromFD(fd, &block_count, &block_size)) {
    filesystem_size_ = static_cast<int64_t>(block_count) * block_size;
    LOG(INFO) << "Filesystem size: " << filesystem_size_ << " bytes ("
              << block_count << "x" << block_size << ").";
  }
}

}  // namespace chromeos_update_engine
