// Copyright (c) 2010 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 "chromeos_system.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/string_tokenizer.h"
#include "base/string_util.h"
#include "chromeos/string.h"

namespace chromeos {  // NOLINT

namespace { // NOLINT

// The filepath to the timezone file that symlinks to the actual timezone file.
static const char kTimezoneSymlink[] = "/var/lib/timezone/localtime";
static const char kTimezoneSymlink2[] = "/var/lib/timezone/localtime2";

// The directory that contains all the timezone files. So for timezone
// "US/Pacific", the actual timezone file is: "/usr/share/zoneinfo/US/Pacific"
static const char kTimezoneFilesDir[] = "/usr/share/zoneinfo/";

// The system command that returns the hardware class.
static const char kHardwareClassKey[] = "hardware_class";
static const char kHardwareClassTool[] = "/usr/bin/hardware_class";
static const char kUnknownHardwareClass[] = "unknown";

// Command to get machine hardware info and key/value delimiters.
// /tmp/machine-info is generated by platform/init/chromeos_startup.
static const char kMachineHardwareInfoTool[] = "cat /tmp/machine-info";
static const char kMachineHardwareInfoEq[] = "=";
static const char kMachineHardwareInfoDelim[] = " \n";

// Command to get machine OS info and key/value delimiters.
static const char kMachineOSInfoTool[] = "cat /etc/lsb-release";
static const char kMachineOSInfoEq[] = "=";
static const char kMachineOSInfoDelim[] = "\n";

}  // namespace

extern "C"
std::string ChromeOSGetTimezoneID() {
  // Look at kTimezoneSymlink, see which timezone we are symlinked to.
  char buf[256];
  const ssize_t len = readlink(kTimezoneSymlink, buf,
                               sizeof(buf)-1);
  if (len == -1) {
    LOG(ERROR) << "GetTimezoneID: Cannot read timezone symlink "
               << kTimezoneSymlink;
    return std::string();
  }

  std::string timezone(buf, len);
  // Remove kTimezoneFilesDir from the beginning.
  if (timezone.find(kTimezoneFilesDir) != 0) {
    LOG(ERROR) << "GetTimezoneID: Timezone symlink is wrong "
               << timezone;
    return std::string();
  }

  return timezone.substr(strlen(kTimezoneFilesDir));
}

extern "C"
void ChromeOSSetTimezoneID(const std::string& id) {
  // Change the kTimezoneSymlink symlink to the path for this timezone.
  // We want to do this in an atomic way. So we are going to create the symlink
  // at kTimezoneSymlink2 and then move it to kTimezoneSymlink

  FilePath timezone_symlink(kTimezoneSymlink);
  FilePath timezone_symlink2(kTimezoneSymlink2);
  FilePath timezone_file(kTimezoneFilesDir + id);

  // Make sure timezone_file exists.
  if (!file_util::PathExists(timezone_file)) {
    LOG(ERROR) << "SetTimezoneID: Cannot find timezone file "
               << timezone_file.value();
    return;
  }

  // Delete old symlink2 if it exists.
  file_util::Delete(timezone_symlink2, false);

  // Create new symlink2.
  if (symlink(timezone_file.value().c_str(),
              timezone_symlink2.value().c_str()) == -1) {
    LOG(ERROR) << "SetTimezoneID: Unable to create symlink "
               << timezone_symlink2.value() << " to " << timezone_file.value();
    return;
  }

  // Move symlink2 to symlink.
  if (!file_util::ReplaceFile(timezone_symlink2, timezone_symlink)) {
    LOG(ERROR) << "SetTimezoneID: Unable to move symlink "
               << timezone_symlink2.value() << " to "
               << timezone_symlink.value();
  }
}

void ChromeOSSystem::AddNVPair(const std::string& key,
                               const std::string& value) {
  nv_pairs_.push_back(std::make_pair(key,value));
}

bool ChromeOSSystem::ParseNVPairs(const std::string& in_string,
                                  const std::string& eq,
                                  const std::string& delim) {
  // Set up the pair tokenizer.
  StringTokenizer pair_toks(in_string, delim);
  pair_toks.set_quote_chars("\"");
  // Process token pairs.
  NameValuePairs new_pairs;
  while (pair_toks.GetNext()) {
    std::string pair(pair_toks.token());
    if (pair.find(eq) == 0) {
      LOG(WARNING) << "Empty key: '" << pair << "'. Aborting.";
      return false;
    }
    StringTokenizer keyvalue(pair, eq);
    std::string key,value;
    if (keyvalue.GetNext()) {
      key = keyvalue.token();
      if (keyvalue.GetNext()) {
        value = keyvalue.token();
        if (keyvalue.GetNext()) {
          LOG(WARNING) << "Multiple key tokens: '" << pair << "'. Aborting.";
          return false;
        }
      }
    }
    if (key.empty()) {
      LOG(WARNING) << "Invalid token pair: '" << pair << "'. Aborting.";
      return false;
    }
    new_pairs.push_back(std::make_pair(key, value));
  }
  nv_pairs_.insert(nv_pairs_.end(), new_pairs.begin(), new_pairs.end());
  return true;
}

bool ChromeOSSystem::ExecCmdToString(const std::string& command,
                                     std::string* contents) {
  FILE* fp = popen(command.c_str(), "r");
  if (!fp) {
    return false;
  }
  char buf[1 << 16];
  size_t len;
  while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
    contents->append(buf, len);
  }
  pclose(fp);
  return true;
}

bool ChromeOSSystem::GetSingleValueFromTool(const std::string& tool,
                                            const std::string& key) {
  std::string output_string;
  if (tool.empty() || !ExecCmdToString(tool, &output_string)) {
    LOG(WARNING) << "Error excuting: " << tool;
    return false;
  }
  TrimWhitespaceASCII(output_string, TRIM_ALL, &output_string);
  nv_pairs_.push_back(std::make_pair(key, output_string));
  return true;
}

bool ChromeOSSystem::ParseNVPairsFromTool(const std::string& tool,
                                          const std::string& eq,
                                          const std::string& delim) {
  std::string output_string;
  if (tool.empty() || !ExecCmdToString(tool, &output_string)) {
    LOG(WARNING) << "Error excuting: " << tool;
    return false;
  }
  if (!ParseNVPairs(output_string, eq, delim)) {
    LOG(WARNING) << "Error parsing values while excuting: " << tool;
    return false;
  }
  return true;
}

void ChromeOSSystem::SetMachineInfo(MachineInfo* machine_info) {
  // Set the MachineInfo struct.
  machine_info->name_value_size = nv_pairs_.size();
  machine_info->name_values = new MachineInfo::NVPair[nv_pairs_.size()];
  int idx = 0;
  for (NameValuePairs::iterator iter = nv_pairs_.begin();
       iter != nv_pairs_.end(); ++iter) {
    machine_info->name_values[idx].name = NewStringCopy(iter->first.c_str());
    machine_info->name_values[idx].value = NewStringCopy(iter->second.c_str());
    ++idx;
  }
}

extern "C"
MachineInfo* ChromeOSGetMachineInfo() {
  MachineInfo* machine_info = new MachineInfo();
  if (!machine_info)
    return NULL;

  ChromeOSSystem system;
  if (!system.GetSingleValueFromTool(kHardwareClassTool, kHardwareClassKey)) {
    // Use kUnknownHardwareClass if the hardware class command fails.
    system.AddNVPair(kHardwareClassKey, kUnknownHardwareClass);
  }
  system.ParseNVPairsFromTool(kMachineHardwareInfoTool,
                              kMachineHardwareInfoEq,
                              kMachineHardwareInfoDelim);
  system.ParseNVPairsFromTool(kMachineOSInfoTool,
                              kMachineOSInfoEq,
                              kMachineOSInfoDelim);
  system.SetMachineInfo(machine_info);
  return machine_info;
}

extern "C"
void ChromeOSFreeMachineInfo(MachineInfo* info) {
  if (info) {
    for (int i=0; i<info->name_value_size; ++i) {
      delete info->name_values[i].name;
      delete info->name_values[i].value;
    }
    delete info->name_values;
    delete info;
  }
}

}  // namespace chromeos
