// Copyright (c) 2010 The Chromium 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 <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <gio/gio.h>
#include <gio/gunixinputstream.h>
#include <gio/gunixoutputstream.h>
#include <glib.h>
#include "update_engine/filesystem_iterator.h"
#include "update_engine/subprocess.h"
#include "update_engine/utils.h"

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

namespace chromeos_update_engine {

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

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();

  if (install_plan_.is_full_update) {
    // No copy needed. Done!
    if (HasOutputPipe())
      SetOutputObject(install_plan_);
    abort_action_completer.set_code(kActionCodeSuccess);
    return;
  }

  string source = copy_source_;
  if (source.empty()) {
    source = copying_kernel_install_path_ ?
        utils::BootKernelDevice(utils::BootDevice()) :
        utils::BootDevice();
  }

  const string destination = copying_kernel_install_path_ ?
      install_plan_.kernel_install_path :
      install_plan_.install_path;

  int src_fd = open(source.c_str(), O_RDONLY);
  if (src_fd < 0) {
    PLOG(ERROR) << "Unable to open " << source << " for reading:";
    return;
  }
  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;
  }

  src_stream_ = g_unix_input_stream_new(src_fd, TRUE);
  dst_stream_ = g_unix_output_stream_new(dst_fd, TRUE);

  buffer_.resize(kCopyFileBufferSize);

  // Set up the first read
  canceller_ = g_cancellable_new();

  g_input_stream_read_async(src_stream_,
                            &buffer_[0],
                            buffer_.size(),
                            G_PRIORITY_DEFAULT,
                            canceller_,
                            &FilesystemCopierAction::StaticAsyncReadyCallback,
                            this);
  read_in_flight_ = true;

  abort_action_completer.set_should_complete(false);
}

void FilesystemCopierAction::TerminateProcessing() {
  if (canceller_) {
    g_cancellable_cancel(canceller_);
  }
}

void FilesystemCopierAction::Cleanup(bool success, bool was_cancelled) {
  g_object_unref(src_stream_);
  src_stream_ = NULL;
  g_object_unref(dst_stream_);
  dst_stream_ = NULL;
  if (was_cancelled)
    return;
  if (success && HasOutputPipe())
    SetOutputObject(install_plan_);
  processor_->ActionComplete(
      this,
      success ? kActionCodeSuccess : kActionCodeError);
}

void FilesystemCopierAction::AsyncReadyCallback(GObject *source_object,
                                                GAsyncResult *res) {
  GError* error = NULL;
  CHECK(canceller_);
  bool was_cancelled = g_cancellable_is_cancelled(canceller_) == TRUE;
  g_object_unref(canceller_);
  canceller_ = NULL;

  if (read_in_flight_) {
    ssize_t bytes_read = g_input_stream_read_finish(src_stream_, res, &error);
    if (bytes_read < 0) {
      LOG(ERROR) << "Read failed:" << utils::GetGErrorMessage(error);
      Cleanup(false, was_cancelled);
      return;
    }

    if (bytes_read == 0) {
      // We're done!
      Cleanup(true, was_cancelled);
      return;
    }
    // Kick off a write
    read_in_flight_ = false;
    buffer_valid_size_ = bytes_read;
    canceller_ = g_cancellable_new();
    g_output_stream_write_async(
        dst_stream_,
        &buffer_[0],
        bytes_read,
        G_PRIORITY_DEFAULT,
        canceller_,
        &FilesystemCopierAction::StaticAsyncReadyCallback,
        this);
    return;
  }

  ssize_t bytes_written = g_output_stream_write_finish(dst_stream_,
                                                       res,
                                                       &error);
  if (bytes_written < static_cast<ssize_t>(buffer_valid_size_)) {
    if (bytes_written < 0) {
      LOG(ERROR) << "Write failed:" << utils::GetGErrorMessage(error);
    } else {
      LOG(ERROR) << "Write was short: wrote " << bytes_written
                 << " but expected to write " << buffer_valid_size_;
    }
    Cleanup(false, was_cancelled);
    return;
  }

  // Kick off a read
  read_in_flight_ = true;
  canceller_ = g_cancellable_new();
  g_input_stream_read_async(
      src_stream_,
      &buffer_[0],
      buffer_.size(),
      G_PRIORITY_DEFAULT,
      canceller_,
      &FilesystemCopierAction::StaticAsyncReadyCallback,
      this);
}

}  // namespace chromeos_update_engine
