//
// Copyright (C) 2012 The Android Open Source Project
//
// 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 <inttypes.h>
#include <sysexits.h>
#include <unistd.h>

#include <string>

#include <base/bind.h>
#include <base/command_line.h>
#include <base/logging.h>
#include <base/macros.h>
#include <chromeos/daemons/dbus_daemon.h>
#include <chromeos/dbus/service_constants.h>
#include <chromeos/flag_helper.h>
#include <dbus/bus.h>

#include "update_engine/dbus_constants.h"
#include "update_engine/dbus-proxies.h"

using chromeos_update_engine::kAttemptUpdateFlagNonInteractive;
using chromeos_update_engine::kUpdateEngineServiceName;
using std::string;

namespace {

// Constant to signal that we need to continue running the daemon after
// initialization.
const int kContinueRunning = -1;

class UpdateEngineClient : public chromeos::DBusDaemon {
 public:
  UpdateEngineClient(int argc, char** argv) : argc_(argc), argv_(argv) {}
  ~UpdateEngineClient() override = default;

 protected:
  int OnInit() override {
    int ret = DBusDaemon::OnInit();
    if (ret != EX_OK)
      return ret;
    if (!InitProxy())
      return 1;
    // Wait for the UpdateEngine to be available or timeout.
    proxy_->GetObjectProxy()->WaitForServiceToBeAvailable(
        base::Bind(&UpdateEngineClient::OnServiceAvailable,
                   base::Unretained(this)));
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&UpdateEngineClient::OnServiceAvailableTimeout,
                   base::Unretained(this)),
        base::TimeDelta::FromSeconds(10));
    return EX_OK;
  }

 private:
  bool InitProxy();

  // Callback called when the UpdateEngine service becomes available.
  void OnServiceAvailable(bool service_is_available);

  // Callback called when the UpdateEngine service doesn't become available
  // after a timeout.
  void OnServiceAvailableTimeout();


  // Callback called when a StatusUpdate signal is received.
  void OnStatusUpdateSignal(int64_t last_checked_time,
                            double progress,
                            const string& current_operation,
                            const string& new_version,
                            int64_t new_size);
  // Callback called when the OnStatusUpdateSignal() handler is registered.
  void OnStatusUpdateSignalRegistration(const string& interface,
                                        const string& signal_name,
                                        bool success);

  // Registers a callback that prints on stderr the received StatusUpdate
  // signals.
  // The daemon should continue running for this to work.
  void WatchForUpdates();

  void ResetStatus();

  // Show the status of the update engine in stdout.
  // Blocking call. Exits the program with error 1 in case of an error.
  void ShowStatus();

  // Return the current operation status, such as UPDATE_STATUS_IDLE.
  // Blocking call. Exits the program with error 1 in case of an error.
  string GetCurrentOperation();

  void Rollback(bool rollback);
  string GetRollbackPartition();
  string GetKernelDevices();
  void CheckForUpdates(const string& app_version,
                       const string& omaha_url,
                       bool interactive);

  // Reboot the device if a reboot is needed.
  // Blocking call. Ignores failures.
  void RebootIfNeeded();

  // Getter and setter for the target channel. If |get_current_channel| is true,
  // the current channel instead of the target channel will be returned.
  // Blocking call. Exits the program with error 1 in case of an error.
  void SetTargetChannel(const string& target_channel, bool allow_powerwash);
  string GetChannel(bool get_current_channel);

  // Getter and setter for the updates over cellular connections.
  // Blocking call. Exits the program with error 1 in case of an error.
  void SetUpdateOverCellularPermission(bool allowed);
  bool GetUpdateOverCellularPermission();

  // Getter and setter for the updates from P2P permission.
  // Blocking call. Exits the program with error 1 in case of an error.
  void SetP2PUpdatePermission(bool enabled);
  bool GetP2PUpdatePermission();

  // This is similar to watching for updates but rather than registering
  // a signal watch, actively poll the daemon just in case it stops
  // sending notifications.
  void WaitForUpdateComplete();
  void OnUpdateCompleteCheck(int64_t last_checked_time,
                             double progress,
                             const string& current_operation,
                             const string& new_version,
                             int64_t new_size);

  // Blocking call. Exits the program with error 1 in case of an error.
  void ShowPrevVersion();

  // Returns whether the current status is such that a reboot is needed.
  // Blocking call. Exits the program with error 1 in case of an error.
  bool GetIsRebootNeeded();

  // Blocks until a reboot is needed. If the reboot is needed, exits the program
  // with 0. Otherwise it exits the program with 1 if an error occurs before
  // the reboot is needed.
  void WaitForRebootNeeded();
  void OnRebootNeededCheck(int64_t last_checked_time,
                           double progress,
                           const string& current_operation,
                           const string& new_version,
                           int64_t new_size);
  // Callback called when the OnRebootNeededCheck() handler is registered. This
  // is useful to check at this point if the reboot is needed, without loosing
  // any StatusUpdate signals and avoiding the race condition.
  void OnRebootNeededCheckRegistration(const string& interface,
                                       const string& signal_name,
                                       bool success);

  // Main method that parses and triggers all the actions based on the passed
  // flags.
  int ProcessFlags();

  // DBus Proxy to the update_engine daemon object used for all the calls.
  std::unique_ptr<org::chromium::UpdateEngineInterfaceProxy> proxy_;

  // Copy of argc and argv passed to main().
  int argc_;
  char** argv_;

  // Tell whether the UpdateEngine service is available after startup.
  bool service_is_available_{false};

  DISALLOW_COPY_AND_ASSIGN(UpdateEngineClient);
};

bool UpdateEngineClient::InitProxy() {
  proxy_.reset(new org::chromium::UpdateEngineInterfaceProxy(bus_));

  if (!proxy_->GetObjectProxy()) {
    LOG(ERROR) << "Error getting dbus proxy for " << kUpdateEngineServiceName;
    return false;
  }
  return true;
}

void UpdateEngineClient::OnServiceAvailable(bool service_is_available) {
  service_is_available_ = service_is_available;
  if (!service_is_available) {
    LOG(ERROR) << "UpdateEngineService not available.";
    QuitWithExitCode(-1);
  }
  int ret = ProcessFlags();
  if (ret != kContinueRunning)
    QuitWithExitCode(ret);
}

void UpdateEngineClient::OnServiceAvailableTimeout() {
  if (!service_is_available_) {
    LOG(ERROR) << "Waiting for UpdateEngineService timeout. Is update_engine "
                  "daemon running?";
    QuitWithExitCode(-1);
  }
}

void UpdateEngineClient::OnStatusUpdateSignal(
    int64_t last_checked_time,
    double progress,
    const string& current_operation,
    const string& new_version,
    int64_t new_size) {
  LOG(INFO) << "Got status update:";
  LOG(INFO) << "  last_checked_time: " << last_checked_time;
  LOG(INFO) << "  progress: " << progress;
  LOG(INFO) << "  current_operation: " << current_operation;
  LOG(INFO) << "  new_version: " << new_version;
  LOG(INFO) << "  new_size: " << new_size;
}

void UpdateEngineClient::OnStatusUpdateSignalRegistration(
    const string& interface,
    const string& signal_name,
    bool success) {
  VLOG(1) << "OnStatusUpdateSignalRegistration(" << interface << ", "
          << signal_name << ", " << success << ");";
  if (!success) {
    LOG(ERROR) << "Couldn't connect to the " << signal_name << " signal.";
    exit(1);
  }
}

void UpdateEngineClient::WatchForUpdates() {
  proxy_->RegisterStatusUpdateSignalHandler(
      base::Bind(&UpdateEngineClient::OnStatusUpdateSignal,
                 base::Unretained(this)),
      base::Bind(&UpdateEngineClient::OnStatusUpdateSignalRegistration,
                 base::Unretained(this)));
}

void UpdateEngineClient::ResetStatus() {
  bool ret = proxy_->ResetStatus(nullptr);
  CHECK(ret) << "ResetStatus() failed.";
}

void UpdateEngineClient::ShowStatus() {
  int64_t last_checked_time = 0;
  double progress = 0.0;
  string current_op;
  string new_version;
  int64_t new_size = 0;

  bool ret = proxy_->GetStatus(
      &last_checked_time, &progress, &current_op, &new_version, &new_size,
      nullptr);
  CHECK(ret) << "GetStatus() failed";
  printf("LAST_CHECKED_TIME=%" PRIi64 "\nPROGRESS=%f\nCURRENT_OP=%s\n"
         "NEW_VERSION=%s\nNEW_SIZE=%" PRIi64 "\n",
         last_checked_time,
         progress,
         current_op.c_str(),
         new_version.c_str(),
         new_size);
}

string UpdateEngineClient::GetCurrentOperation() {
  int64_t last_checked_time = 0;
  double progress = 0.0;
  string current_op;
  string new_version;
  int64_t new_size = 0;

  bool ret = proxy_->GetStatus(
      &last_checked_time, &progress, &current_op, &new_version, &new_size,
      nullptr);
  CHECK(ret) << "GetStatus() failed";
  return current_op;
}

void UpdateEngineClient::Rollback(bool rollback) {
  bool ret = proxy_->AttemptRollback(rollback, nullptr);
  CHECK(ret) << "Rollback request failed.";
}

string UpdateEngineClient::GetRollbackPartition() {
  string rollback_partition;
  bool ret = proxy_->GetRollbackPartition(&rollback_partition, nullptr);
  CHECK(ret) << "Error while querying rollback partition availabilty.";
  return rollback_partition;
}

string UpdateEngineClient::GetKernelDevices() {
  string kernel_devices;
  bool ret = proxy_->GetKernelDevices(&kernel_devices, nullptr);
  CHECK(ret) << "Error while getting a list of kernel devices";
  return kernel_devices;
}

void UpdateEngineClient::CheckForUpdates(const string& app_version,
                                         const string& omaha_url,
                                         bool interactive) {
  int32_t flags = interactive ? 0 : kAttemptUpdateFlagNonInteractive;
  bool ret = proxy_->AttemptUpdateWithFlags(app_version, omaha_url, flags,
                                            nullptr);
  CHECK(ret) << "Error checking for update.";
}

void UpdateEngineClient::RebootIfNeeded() {
  bool ret = proxy_->RebootIfNeeded(nullptr);
  if (!ret) {
    // Reboot error code doesn't necessarily mean that a reboot
    // failed. For example, D-Bus may be shutdown before we receive the
    // result.
    LOG(INFO) << "RebootIfNeeded() failure ignored.";
  }
}

void UpdateEngineClient::SetTargetChannel(const string& target_channel,
                                          bool allow_powerwash) {
  bool ret = proxy_->SetChannel(target_channel, allow_powerwash, nullptr);
  CHECK(ret) << "Error setting the channel.";
  LOG(INFO) << "Channel permanently set to: " << target_channel;
}

string UpdateEngineClient::GetChannel(bool get_current_channel) {
  string channel;
  bool ret = proxy_->GetChannel(get_current_channel, &channel, nullptr);
  CHECK(ret) << "Error getting the channel.";
  return channel;
}

void UpdateEngineClient::SetUpdateOverCellularPermission(bool allowed) {
  bool ret = proxy_->SetUpdateOverCellularPermission(allowed, nullptr);
  CHECK(ret) << "Error setting the update over cellular setting.";
}

bool UpdateEngineClient::GetUpdateOverCellularPermission() {
  bool allowed;
  bool ret = proxy_->GetUpdateOverCellularPermission(&allowed, nullptr);
  CHECK(ret) << "Error getting the update over cellular setting.";
  return allowed;
}

void UpdateEngineClient::SetP2PUpdatePermission(bool enabled) {
  bool ret = proxy_->SetP2PUpdatePermission(enabled, nullptr);
  CHECK(ret) << "Error setting the peer-to-peer update setting.";
}

bool UpdateEngineClient::GetP2PUpdatePermission() {
  bool enabled;
  bool ret = proxy_->GetP2PUpdatePermission(&enabled, nullptr);
  CHECK(ret) << "Error getting the peer-to-peer update setting.";
  return enabled;
}

void UpdateEngineClient::OnUpdateCompleteCheck(
    int64_t /* last_checked_time */,
    double /* progress */,
    const string& current_operation,
    const string& /* new_version */,
    int64_t /* new_size */) {
  if (current_operation == update_engine::kUpdateStatusIdle) {
    LOG(ERROR) << "Update failed, current operations is " << current_operation;
    exit(1);
  }
  if (current_operation == update_engine::kUpdateStatusUpdatedNeedReboot) {
    LOG(INFO) << "Update succeeded -- reboot needed.";
    exit(0);
  }
}

void UpdateEngineClient::WaitForUpdateComplete() {
  proxy_->RegisterStatusUpdateSignalHandler(
      base::Bind(&UpdateEngineClient::OnUpdateCompleteCheck,
                 base::Unretained(this)),
      base::Bind(&UpdateEngineClient::OnStatusUpdateSignalRegistration,
                 base::Unretained(this)));
}

void UpdateEngineClient::ShowPrevVersion() {
  string prev_version = nullptr;

  bool ret = proxy_->GetPrevVersion(&prev_version, nullptr);;
  if (!ret) {
    LOG(ERROR) << "Error getting previous version.";
  } else {
    LOG(INFO) << "Previous version = " << prev_version;
  }
}

bool UpdateEngineClient::GetIsRebootNeeded() {
  return GetCurrentOperation() == update_engine::kUpdateStatusUpdatedNeedReboot;
}

void UpdateEngineClient::OnRebootNeededCheck(
    int64_t /* last_checked_time */,
    double /* progress */,
    const string& current_operation,
    const string& /* new_version */,
    int64_t /* new_size */) {
  if (current_operation == update_engine::kUpdateStatusUpdatedNeedReboot) {
    LOG(INFO) << "Reboot needed.";
    exit(0);
  }
}

void UpdateEngineClient::OnRebootNeededCheckRegistration(
    const string& interface,
    const string& signal_name,
    bool success) {
  if (GetIsRebootNeeded())
    exit(0);
  if (!success) {
    LOG(ERROR) << "Couldn't connect to the " << signal_name << " signal.";
    exit(1);
  }
}

// Blocks until a reboot is needed. Returns true if waiting succeeded,
// false if an error occurred.
void UpdateEngineClient::WaitForRebootNeeded() {
  proxy_->RegisterStatusUpdateSignalHandler(
      base::Bind(&UpdateEngineClient::OnUpdateCompleteCheck,
                 base::Unretained(this)),
      base::Bind(&UpdateEngineClient::OnStatusUpdateSignalRegistration,
                 base::Unretained(this)));
  if (GetIsRebootNeeded())
    exit(0);
}

int UpdateEngineClient::ProcessFlags() {
  DEFINE_string(app_version, "", "Force the current app version.");
  DEFINE_string(channel, "",
                "Set the target channel. The device will be powerwashed if the "
                "target channel is more stable than the current channel unless "
                "--nopowerwash is specified.");
  DEFINE_bool(check_for_update, false, "Initiate check for updates.");
  DEFINE_bool(follow, false, "Wait for any update operations to complete."
              "Exit status is 0 if the update succeeded, and 1 otherwise.");
  DEFINE_bool(interactive, true, "Mark the update request as interactive.");
  DEFINE_string(omaha_url, "", "The URL of the Omaha update server.");
  DEFINE_string(p2p_update, "",
                "Enables (\"yes\") or disables (\"no\") the peer-to-peer update"
                " sharing.");
  DEFINE_bool(powerwash, true, "When performing rollback or channel change, "
              "do a powerwash or allow it respectively.");
  DEFINE_bool(reboot, false, "Initiate a reboot if needed.");
  DEFINE_bool(is_reboot_needed, false, "Exit status 0 if reboot is needed, "
              "2 if reboot is not needed or 1 if an error occurred.");
  DEFINE_bool(block_until_reboot_is_needed, false, "Blocks until reboot is "
              "needed. Returns non-zero exit status if an error occurred.");
  DEFINE_bool(reset_status, false, "Sets the status in update_engine to idle.");
  DEFINE_bool(rollback, false,
              "Perform a rollback to the previous partition. The device will "
              "be powerwashed unless --nopowerwash is specified.");
  DEFINE_bool(can_rollback, false, "Shows whether rollback partition "
              "is available.");
  DEFINE_bool(show_channel, false, "Show the current and target channels.");
  DEFINE_bool(show_p2p_update, false,
              "Show the current setting for peer-to-peer update sharing.");
  DEFINE_bool(show_update_over_cellular, false,
              "Show the current setting for updates over cellular networks.");
  DEFINE_bool(status, false, "Print the status to stdout.");
  DEFINE_bool(update, false, "Forces an update and waits for it to complete. "
              "Implies --follow.");
  DEFINE_string(update_over_cellular, "",
                "Enables (\"yes\") or disables (\"no\") the updates over "
                "cellular networks.");
  DEFINE_bool(watch_for_updates, false,
              "Listen for status updates and print them to the screen.");
  DEFINE_bool(prev_version, false,
              "Show the previous OS version used before the update reboot.");
  DEFINE_bool(show_kernels, false, "Show the list of kernel patritions and "
              "whether each of them is bootable or not");

  // Boilerplate init commands.
  base::CommandLine::Init(argc_, argv_);
  chromeos::FlagHelper::Init(argc_, argv_, "Chromium OS Update Engine Client");

  // Ensure there are no positional arguments.
  const std::vector<string> positional_args =
      base::CommandLine::ForCurrentProcess()->GetArgs();
  if (!positional_args.empty()) {
    LOG(ERROR) << "Found a positional argument '" << positional_args.front()
               << "'. If you want to pass a value to a flag, pass it as "
                  "--flag=value.";
    return 1;
  }

  // Update the status if requested.
  if (FLAGS_reset_status) {
    LOG(INFO) << "Setting Update Engine status to idle ...";
    ResetStatus();
    LOG(INFO) << "ResetStatus succeeded; to undo partition table changes run:\n"
                 "(D=$(rootdev -d) P=$(rootdev -s); cgpt p -i$(($(echo ${P#$D} "
                 "| sed 's/^[^0-9]*//')-1)) $D;)";
  }

  // Changes the current update over cellular network setting.
  if (!FLAGS_update_over_cellular.empty()) {
    bool allowed = FLAGS_update_over_cellular == "yes";
    if (!allowed && FLAGS_update_over_cellular != "no") {
      LOG(ERROR) << "Unknown option: \"" << FLAGS_update_over_cellular
                 << "\". Please specify \"yes\" or \"no\".";
    } else {
      SetUpdateOverCellularPermission(allowed);
    }
  }

  // Show the current update over cellular network setting.
  if (FLAGS_show_update_over_cellular) {
    bool allowed = GetUpdateOverCellularPermission();
    LOG(INFO) << "Current update over cellular network setting: "
              << (allowed ? "ENABLED" : "DISABLED");
  }

  if (!FLAGS_powerwash && !FLAGS_rollback && FLAGS_channel.empty()) {
    LOG(ERROR) << "powerwash flag only makes sense rollback or channel change";
    return 1;
  }

  // Change the P2P enabled setting.
  if (!FLAGS_p2p_update.empty()) {
    bool enabled = FLAGS_p2p_update == "yes";
    if (!enabled && FLAGS_p2p_update != "no") {
      LOG(ERROR) << "Unknown option: \"" << FLAGS_p2p_update
                 << "\". Please specify \"yes\" or \"no\".";
    } else {
      SetP2PUpdatePermission(enabled);
    }
  }

  // Show the rollback availability.
  if (FLAGS_can_rollback) {
    string rollback_partition = GetRollbackPartition();
    bool can_rollback = true;
    if (rollback_partition.empty()) {
      rollback_partition = "UNAVAILABLE";
      can_rollback = false;
    } else {
      rollback_partition = "AVAILABLE: " + rollback_partition;
    }

    LOG(INFO) << "Rollback partition: " << rollback_partition;
    if (!can_rollback) {
      return 1;
    }
  }

  // Show the current P2P enabled setting.
  if (FLAGS_show_p2p_update) {
    bool enabled = GetP2PUpdatePermission();
    LOG(INFO) << "Current update using P2P setting: "
              << (enabled ? "ENABLED" : "DISABLED");
  }

  // First, update the target channel if requested.
  if (!FLAGS_channel.empty())
    SetTargetChannel(FLAGS_channel, FLAGS_powerwash);

  // Show the current and target channels if requested.
  if (FLAGS_show_channel) {
    string current_channel = GetChannel(true);
    LOG(INFO) << "Current Channel: " << current_channel;

    string target_channel = GetChannel(false);
    if (!target_channel.empty())
      LOG(INFO) << "Target Channel (pending update): " << target_channel;
  }

  bool do_update_request = FLAGS_check_for_update | FLAGS_update |
      !FLAGS_app_version.empty() | !FLAGS_omaha_url.empty();
  if (FLAGS_update)
    FLAGS_follow = true;

  if (do_update_request && FLAGS_rollback) {
    LOG(ERROR) << "Incompatible flags specified with rollback."
               << "Rollback should not include update-related flags.";
    return 1;
  }

  if (FLAGS_rollback) {
    LOG(INFO) << "Requesting rollback.";
    Rollback(FLAGS_powerwash);
  }

  // Initiate an update check, if necessary.
  if (do_update_request) {
    LOG_IF(WARNING, FLAGS_reboot) << "-reboot flag ignored.";
    string app_version = FLAGS_app_version;
    if (FLAGS_update && app_version.empty()) {
      app_version = "ForcedUpdate";
      LOG(INFO) << "Forcing an update by setting app_version to ForcedUpdate.";
    }
    LOG(INFO) << "Initiating update check and install.";
    CheckForUpdates(app_version, FLAGS_omaha_url, FLAGS_interactive);
  }

  // These final options are all mutually exclusive with one another.
  if (FLAGS_follow + FLAGS_watch_for_updates + FLAGS_reboot +
      FLAGS_status + FLAGS_is_reboot_needed +
      FLAGS_block_until_reboot_is_needed > 1) {
    LOG(ERROR) << "Multiple exclusive options selected. "
               << "Select only one of --follow, --watch_for_updates, --reboot, "
               << "--is_reboot_needed, --block_until_reboot_is_needed, "
               << "or --status.";
    return 1;
  }

  if (FLAGS_status) {
    LOG(INFO) << "Querying Update Engine status...";
    ShowStatus();
    return 0;
  }

  if (FLAGS_follow) {
    LOG(INFO) << "Waiting for update to complete.";
    WaitForUpdateComplete();
    return kContinueRunning;
  }

  if (FLAGS_watch_for_updates) {
    LOG(INFO) << "Watching for status updates.";
    WatchForUpdates();
    return kContinueRunning;
  }

  if (FLAGS_reboot) {
    LOG(INFO) << "Requesting a reboot...";
    RebootIfNeeded();
    return 0;
  }

  if (FLAGS_prev_version) {
    ShowPrevVersion();
  }

  if (FLAGS_show_kernels) {
    LOG(INFO) << "Kernel partitions:\n"
              << GetKernelDevices();
  }

  if (FLAGS_is_reboot_needed) {
    // In case of error GetIsRebootNeeded() will exit with 1.
    if (GetIsRebootNeeded()) {
      return 0;
    } else {
      return 2;
    }
  }

  if (FLAGS_block_until_reboot_is_needed) {
    WaitForRebootNeeded();
    return kContinueRunning;
  }

  return 0;
}

}  // namespace

int main(int argc, char** argv) {
  UpdateEngineClient client(argc, argv);
  return client.Run();
}
