// Copyright 2019 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 "diagnostics/wilco_dtc_supportd/telemetry/system_files_service_impl.h"

#include <utility>

#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_util.h>

namespace diagnostics {

// static
base::FilePath SystemFilesServiceImpl::GetPathForFile(
    SystemFilesService::File location) {
  switch (location) {
    case File::kProcUptime:
      return base::FilePath("proc/uptime");
    case File::kProcMeminfo:
      return base::FilePath("proc/meminfo");
    case File::kProcLoadavg:
      return base::FilePath("proc/loadavg");
    case File::kProcStat:
      return base::FilePath("proc/stat");
    case File::kProcNetNetstat:
      return base::FilePath("proc/net/netstat");
    case File::kProcNetDev:
      return base::FilePath("proc/net/dev");
    case File::kProcDiskstats:
      return base::FilePath("proc/diskstats");
    case File::kProcCpuinfo:
      return base::FilePath("proc/cpuinfo");
    case File::kProcVmstat:
      return base::FilePath("proc/vmstat");
  }

  NOTREACHED();
}

// static
base::FilePath SystemFilesServiceImpl::GetPathForDirectory(
    SystemFilesService::Directory location) {
  switch (location) {
    case Directory::kProcAcpiButton:
      return base::FilePath("proc/acpi/button/");
    case Directory::kSysClassHwmon:
      return base::FilePath("sys/class/hwmon/");
    case Directory::kSysClassThermal:
      return base::FilePath("sys/class/thermal/");
    case Directory::kSysFirmwareDmiTables:
      return base::FilePath("sys/firmware/dmi/tables/");
    case Directory::kSysClassPowerSupply:
      return base::FilePath("sys/class/power_supply/");
    case Directory::kSysClassBacklight:
      return base::FilePath("sys/class/backlight/");
    case Directory::kSysClassNetwork:
      return base::FilePath("sys/class/net/");
    case Directory::kSysDevicesSystemCpu:
      return base::FilePath("sys/devices/system/cpu/");
  }

  NOTREACHED();
}

// static
base::FilePath SystemFilesServiceImpl::GetPathForVpdField(VpdField vpd_field) {
  switch (vpd_field) {
    case VpdField::kActivateDate:
      return base::FilePath("run/wilco_dtc/vpd_fields/ActivateDate");
    case VpdField::kAssetId:
      return base::FilePath("run/wilco_dtc/vpd_fields/asset_id");
    case VpdField::kMfgDate:
      return base::FilePath("run/wilco_dtc/vpd_fields/mfg_date");
    case VpdField::kModelName:
      return base::FilePath("run/wilco_dtc/vpd_fields/model_name");
    case VpdField::kSerialNumber:
      return base::FilePath("run/wilco_dtc/vpd_fields/serial_number");
    case VpdField::kSkuNumber:
      return base::FilePath("run/wilco_dtc/vpd_fields/sku_number");
    case VpdField::kSystemId:
      return base::FilePath("run/wilco_dtc/vpd_fields/system_id");
    case VpdField::kUuid:
      return base::FilePath("run/wilco_dtc/vpd_fields/uuid_id");
  }

  NOTREACHED();
}

SystemFilesServiceImpl::SystemFilesServiceImpl() = default;

SystemFilesServiceImpl::~SystemFilesServiceImpl() = default;

base::Optional<SystemFilesService::FileDump>
SystemFilesServiceImpl::GetFileDump(File location) {
  FileDump dump;
  if (!MakeFileDump(root_dir_.Append(GetPathForFile(location)), &dump)) {
    return base::nullopt;
  }
  return std::move(dump);
}

base::Optional<SystemFilesService::FileDumps>
SystemFilesServiceImpl::GetDirectoryDump(Directory location) {
  base::FilePath path = root_dir_.Append(GetPathForDirectory(location));
  if (!base::DirectoryExists(path))
    return base::nullopt;

  FileDumps dumps;
  std::set<std::string> visited_paths;
  SearchDirectory(path, &visited_paths, &dumps);

  return std::move(dumps);
}

base::Optional<std::string> SystemFilesServiceImpl::GetVpdField(
    VpdField vpd_field) {
  FileDump dump;
  if (!MakeFileDump(root_dir_.Append(GetPathForVpdField(vpd_field)), &dump)) {
    return base::nullopt;
  }

  base::TrimString(dump.contents, base::kWhitespaceASCII, &dump.contents);
  if (dump.contents.empty() || !base::IsStringASCII(dump.contents)) {
    VLOG(2) << "VPD field from " << GetPathForVpdField(vpd_field).BaseName()
            << " is not non-empty ASCII string";
    return base::nullopt;
  }

  return std::move(dump.contents);
}

void SystemFilesServiceImpl::set_root_dir_for_testing(
    const base::FilePath& dir) {
  root_dir_ = dir;
}

bool SystemFilesServiceImpl::MakeFileDump(const base::FilePath& file_path,
                                          FileDump* file_dump) const {
  std::string file_contents;
  if (!base::ReadFileToString(file_path, &file_contents)) {
    VPLOG(2) << "Failed to read from " << file_path.value();
    return false;
  }
  const base::FilePath canonical_file_path =
      base::MakeAbsoluteFilePath(file_path);
  if (canonical_file_path.empty()) {
    PLOG(ERROR) << "Failed to obtain canonical path for " << file_path.value();
    return false;
  }
  VLOG(3) << "Read " << file_contents.size() << " bytes from "
          << file_path.value() << " with canonical path "
          << canonical_file_path.value();

  file_dump->path = file_path;
  file_dump->canonical_path = canonical_file_path;
  file_dump->contents = std::move(file_contents);
  return true;
}

void SystemFilesServiceImpl::SearchDirectory(
    const base::FilePath& root_dir,
    std::set<std::string>* visited_paths,
    FileDumps* file_dumps) const {
  visited_paths->insert(base::MakeAbsoluteFilePath(root_dir).value());
  base::FileEnumerator file_enum(
      base::FilePath(root_dir), false,
      base::FileEnumerator::FileType::FILES |
          base::FileEnumerator::FileType::DIRECTORIES |
          base::FileEnumerator::FileType::SHOW_SYM_LINKS);
  for (base::FilePath path = file_enum.Next(); !path.empty();
       path = file_enum.Next()) {
    // Only certain symlinks are followed - see the comments for
    // ShouldFollowSymlink for a full description of the behavior.
    if (base::IsLink(path) && !ShouldFollowSymlink(path))
      continue;

    base::FilePath canonical_path = base::MakeAbsoluteFilePath(path);
    if (canonical_path.empty()) {
      VPLOG(2) << "Failed to resolve path '" << path.value() << "'.";
      continue;
    }

    // Prevent visiting duplicate paths, which could happen due to following
    // symlinks.
    if (visited_paths->find(canonical_path.value()) != visited_paths->end())
      continue;

    visited_paths->insert(canonical_path.value());

    if (base::DirectoryExists(path)) {
      SearchDirectory(path, visited_paths, file_dumps);
    } else {
      auto file_dump = std::make_unique<FileDump>();
      if (!MakeFileDump(path, file_dump.get())) {
        // When a file is failed to be dumped, it's just omitted from the
        // returned list of entries.
        continue;
      }
      file_dumps->push_back(std::move(file_dump));
    }
  }
}

bool SystemFilesServiceImpl::ShouldFollowSymlink(
    const base::FilePath& link) const {
  // Path relative to the root directory where we will follow symlinks.
  constexpr char kAllowableSymlinkParentDir[] = "sys/class";
  return base::FilePath(root_dir_.Append(kAllowableSymlinkParentDir)) ==
         link.DirName().DirName();
}

}  // namespace diagnostics
