// Copyright 2011 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Implementation of bootstat_log(), part of the Chromium OS 'bootstat'
// facility.

#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <linux/rtc.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>

#include <optional>
#include <string>
#include <vector>

#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <rootdev/rootdev.h>

#include "bootstat/bootstat.h"

namespace bootstat {

namespace {
// Default root-relative path to directory where output statistics will be
// stored.
static const char kDefaultOutputDirectoryName[] = "run/bootstat";

static constexpr char kProcUptime[] = "proc/uptime";

static constexpr int64_t kNsecsPerSec = 1e9;

// Length of the longest valid string naming an event, including the
// terminating NUL character.
//
// This value is arbitrarily chosen.
static constexpr int kBootstatMaxEventLength = 64;

// Parse a line of text containing one or more space-separated columns of
// decimal numbers. For example (without the quotes):
//   "12.76543 0.89"
//   "10.3333"
static std::optional<std::vector<base::TimeDelta>> ParseDecimalColumns(
    std::string_view line) {
  auto numbers = base::SplitStringPiece(line, " ", base::TRIM_WHITESPACE,
                                        base::SPLIT_WANT_NONEMPTY);
  if (numbers.empty()) {
    LOG(ERROR) << "Malformed line: " << line;
    return std::nullopt;
  }

  std::vector<base::TimeDelta> results;
  for (auto& number : numbers) {
    auto pieces = base::SplitStringPiece(number, ".", base::TRIM_WHITESPACE,
                                         base::SPLIT_WANT_NONEMPTY);
    if (pieces.size() != 2) {
      LOG(ERROR) << "Malformed number: " << line;
      return std::nullopt;
    }

    uint64_t secs;
    if (!base::StringToUint64(pieces[0], &secs)) {
      LOG(ERROR) << "Malformed seconds: " << line;
      return std::nullopt;
    }

    // We're looking for nanoseconds.
    if (pieces[1].size() > 9) {
      LOG(ERROR) << "Malformed decimal places: " << line;
      return std::nullopt;
    }
    // Pad to 9, with trailing zeroes.
    unsigned int nsecs;
    if (!base::StringToUint(pieces[1], &nsecs)) {
      LOG(ERROR) << "Malformed decimal: " << line;
      return std::nullopt;
    }
    for (int i = 0; i < 9 - pieces[1].size(); i++)
      nsecs *= 10;

    results.push_back(base::Seconds(secs) + base::Nanoseconds(nsecs));
  }

  return results;
}

}  // namespace

BootStatSystem::BootStatSystem() : BootStatSystem(base::FilePath("/")) {}

BootStatSystem::BootStatSystem(const base::FilePath& root_path)
    : root_path_(root_path) {}

// TODO(drinkcat): Cache function output (we only need to evaluate it once)
base::FilePath BootStatSystem::GetDiskStatisticsFilePath() const {
  char boot_path[PATH_MAX];
  int ret = rootdev(boot_path, sizeof(boot_path),
                    true,    // Do full resolution.
                    false);  // Do not remove partition number.
  if (ret != 0) {
    LOG(ERROR) << "Cannot get rootdev.";
    return base::FilePath();
  }

  // The general idea is to use the the root device's sysfs entry to
  // get the path to the root disk's sysfs entry.
  // Example:
  // - rootdev() returns "/dev/sda3"
  // - Use /sys/class/block/sda3/../ to get to root disk (sda) sysfs entry.
  //   This is because /sys/class/block/sda3 is a symlink that maps to:
  //     /sys/devices/pci.../.../ata./host./target.../.../block/sda/sda3
  base::FilePath root_device_name = base::FilePath(boot_path).BaseName();

  base::FilePath stat_path = base::FilePath("/sys/class/block")
                                 .Append(root_device_name)
                                 .Append("../stat");

  // Normalize the path as some functions refuse to follow symlink/`..`.
  base::FilePath norm;
  if (!base::NormalizeFilePath(stat_path, &norm)) {
    LOG(ERROR) << "Cannot normalize disk statistics file path.";
    return base::FilePath();
  }
  return norm;
}

std::optional<struct timespec> BootStatSystem::GetUpTime() const {
  struct timespec uptime;
  int ret = clock_gettime(CLOCK_BOOTTIME, &uptime);
  if (ret != 0) {
    PLOG(ERROR) << "Cannot get uptime (CLOCK_BOOTTIME).";
    return std::nullopt;
  }
  return uptime;
}

std::optional<base::TimeDelta> BootStatSystem::GetIdleTime() const {
  base::FilePath path = root_path_.Append(kProcUptime);
  std::string data;
  if (!base::ReadFileToString(path, &data)) {
    PLOG(ERROR) << "Cannot read uptime from: " << path;
    return std::nullopt;
  }

  auto numbers = ParseDecimalColumns(data);
  if (!numbers) {
    LOG(ERROR) << "Couldn't parse uptime: " << data;
    return std::nullopt;
  }
  if (numbers->size() != 2) {
    LOG(ERROR) << "Unexpected uptime contents: " << data;
    return std::nullopt;
  }
  // Second column is idle time.
  return (*numbers)[1];
}

base::ScopedFD BootStatSystem::OpenRtc() const {
  int rtc_fd = HANDLE_EINTR(open("/dev/rtc", O_RDONLY | O_CLOEXEC));
  if (rtc_fd < 0)
    PLOG(ERROR) << "Cannot open RTC";

  return base::ScopedFD(rtc_fd);
}

std::optional<struct rtc_time> BootStatSystem::GetRtcTime(
    base::ScopedFD* rtc_fd) const {
  struct rtc_time rtc_time;
  if (ioctl(rtc_fd->get(), RTC_RD_TIME, &rtc_time) < 0) {
    PLOG(ERROR) << "RTC ioctl error";
    return std::nullopt;
  }

  return rtc_time;
}

BootStat::BootStat() : BootStat(base::FilePath("/")) {}

BootStat::BootStat(const base::FilePath& root_path)
    : BootStat(root_path.Append(base::FilePath(kDefaultOutputDirectoryName)),
               std::make_unique<BootStatSystem>()) {}

BootStat::BootStat(const base::FilePath& output_directory_path,
                   std::unique_ptr<BootStatSystem> boot_stat_system)
    : output_directory_path_(output_directory_path),
      boot_stat_system_(std::move(boot_stat_system)) {}

BootStat::~BootStat() = default;

base::FilePath BootStat::GetEventPath(const std::string& prefix,
                                      const std::string& event_name) const {
  //
  // For those not up on the more esoteric features of printf
  // formats:  the "%.*s" format is used to truncate the event name
  // to the proper number of characters..
  //
  std::string output_file =
      base::StringPrintf("%s-%.*s", prefix.c_str(), kBootstatMaxEventLength - 1,
                         event_name.c_str());

  return output_directory_path_.Append(output_file);
}

std::optional<struct BootStat::RtcTick> BootStat::GetRtcTick() const {
  base::ScopedFD rtc_fd = boot_stat_system_->OpenRtc();
  if (!rtc_fd.is_valid())
    return std::nullopt;

  // Record start time so that we can timeout if needed.
  std::optional<struct timespec> tps_start = boot_stat_system_->GetUpTime();
  if (!tps_start)
    return std::nullopt;

  std::optional<struct rtc_time> rtc_time[2];

  for (int i = 0;; i++) {
    int old = (i + 1) % 2;
    int cur = i % 2;

    std::optional<struct timespec> tps_cur = boot_stat_system_->GetUpTime();
    if (!tps_cur)
      return std::nullopt;

    rtc_time[cur] = boot_stat_system_->GetRtcTime(&rtc_fd);
    if (!rtc_time[cur])
      return std::nullopt;

    if (i > 0 && rtc_time[cur]->tm_sec != rtc_time[old]->tm_sec) {
      // RTC ticked, record "after" time.
      std::optional<struct timespec> tps_after = boot_stat_system_->GetUpTime();
      if (!tps_after)
        return std::nullopt;
      return {{*rtc_time[cur], *tps_cur, *tps_after}};
    }

    // Timeout after 1.5 seconds.
    if (difftime(tps_cur->tv_sec, tps_start->tv_sec) +
            (tps_cur->tv_nsec - tps_start->tv_nsec) * 1e-9 >
        1.5) {
      LOG(ERROR) << "Timeout waiting for RTC tick.";
      return std::nullopt;
    }

    // Don't hog the CPU too much, we don't care about sub-ms resolution
    // anyway.
    usleep(1000);
  }
}

base::ScopedFD BootStat::OpenEventFile(const std::string& output_name_prefix,
                                       const std::string& event_name) const {
  const mode_t kFileCreationMode =
      S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

  base::FilePath output_path = GetEventPath(output_name_prefix, event_name);

  int output_fd =
      HANDLE_EINTR(open(output_path.value().c_str(),
                        O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW | O_CLOEXEC,
                        kFileCreationMode));
  if (output_fd < 0) {
    PLOG(ERROR) << "Cannot open event file " << output_path.value() << ".";
    return base::ScopedFD();
  }

  base::stat_wrapper_t stat;
  if (base::File::Fstat(output_fd, &stat) < 0) {
    PLOG(ERROR) << "Failed to stat file " << output_path.value();
    return base::ScopedFD();
  }

  // Double check the read permissions, because umask may override us during
  // creation, and we need those. (We allow write permissions to be masked.)
  mode_t new_mode = stat.st_mode | S_IRGRP | S_IROTH;
  if (stat.st_mode == new_mode)
    return base::ScopedFD(output_fd);

  // We need to force the permissions again. There's a small race here, as the
  // file may exist with a umask()'ed (incorrect) mode briefly, so consumers
  // should still be prepared to handle EPERM errors.
  if (HANDLE_EINTR(fchmod(output_fd, new_mode)) == -1) {
    PLOG(ERROR) << "Failed to set permissions for event file "
                << output_path.value();
    return base::ScopedFD();
  }
  return base::ScopedFD(output_fd);
}

bool BootStat::LogDiskEvent(const std::string& event_name) const {
  base::FilePath disk_statistics_file_path =
      boot_stat_system_->GetDiskStatisticsFilePath();

  if (disk_statistics_file_path.empty())
    return false;

  std::string data;
  if (!base::ReadFileToString(disk_statistics_file_path, &data)) {
    LOG(ERROR) << "Cannot read disk statistics "
               << disk_statistics_file_path.value() << ".";
    return false;
  }

  base::ScopedFD output_fd = OpenEventFile("disk", event_name);
  if (!output_fd.is_valid())
    return false;

  bool ret = base::WriteFileDescriptor(output_fd.get(), data);
  LOG_IF(ERROR, !ret) << "Cannot write disk event.";
  return ret;
}

bool BootStat::LogUptimeEvent(const std::string& event_name) const {
  std::optional<struct timespec> uptime = boot_stat_system_->GetUpTime();
  if (!uptime)
    return false;

  std::optional<base::TimeDelta> idle = boot_stat_system_->GetIdleTime();
  if (!idle)
    return false;

  std::string data = base::StringPrintf(
      "%" PRId64 ".%09ld %" PRId64 ".%09" PRId64 "\n",
      static_cast<int64_t>(uptime->tv_sec), uptime->tv_nsec, idle->InSeconds(),
      idle->InNanoseconds() % kNsecsPerSec);

  base::ScopedFD output_fd = OpenEventFile("uptime", event_name);
  if (!output_fd.is_valid())
    return false;

  bool ret = base::WriteFileDescriptor(output_fd.get(), data);
  LOG_IF(ERROR, !ret) << "Cannot write uptime event.";
  return ret;
}

std::optional<std::vector<BootStat::BootstatTiming>> BootStat::ParseUptimeEvent(
    const std::string& contents) const {
  auto lines = base::SplitStringPiece(contents, "\n", base::TRIM_WHITESPACE,
                                      base::SPLIT_WANT_NONEMPTY);

  std::vector<BootStat::BootstatTiming> events;
  for (auto& line : lines) {
    auto result = ParseDecimalColumns(line);
    if (!result)
      return std::nullopt;
    if (result->size() != 2) {
      LOG(ERROR) << "Unexpected uptime line: " << line;
      return std::nullopt;
    }

    BootStat::BootstatTiming event = {
        .uptime = (*result)[0],
        .idle_time = (*result)[1],
    };
    events.push_back(std::move(event));
  }

  return events;
}

// API functions.
bool BootStat::LogEvent(const std::string& event_name) const {
  bool ret = true;

  ret &= LogDiskEvent(event_name);
  ret &= LogUptimeEvent(event_name);

  return ret;
}

bool BootStat::LogRtcSync(const char* event_name) {
  std::optional<struct RtcTick> tick = GetRtcTick();
  if (!tick)
    return false;

  base::ScopedFD output_fd = OpenEventFile("sync-rtc", event_name);
  if (!output_fd.is_valid())
    return false;

  std::string data = base::StringPrintf(
      "%" PRId64 ".%09ld %" PRId64 ".%09ld %04d-%02d-%02d %02d:%02d:%02d\n",
      static_cast<int64_t>(tick->boottime_before.tv_sec),
      tick->boottime_before.tv_nsec,
      static_cast<int64_t>(tick->boottime_after.tv_sec),
      tick->boottime_after.tv_nsec, tick->rtc_time.tm_year + 1900,
      tick->rtc_time.tm_mon + 1, tick->rtc_time.tm_mday, tick->rtc_time.tm_hour,
      tick->rtc_time.tm_min, tick->rtc_time.tm_sec);

  bool ret = base::WriteFileDescriptor(output_fd.get(), data);
  LOG_IF(ERROR, !ret) << "Cannot write rtc sync.";
  return ret;
}

std::optional<std::vector<BootStat::BootstatTiming>> BootStat::GetEventTimings(
    const std::string& event_name) const {
  base::FilePath event_path = GetEventPath("uptime", event_name);

  std::string data;
  if (!base::ReadFileToString(event_path, &data)) {
    PLOG(ERROR) << "Could not read event file: " << event_path;
    return std::nullopt;
  }

  auto result = ParseUptimeEvent(data);
  if (!result)
    LOG(ERROR) << "Failed to parse bootstat file for event: " << event_name;

  return result;
}

};  // namespace bootstat
