/*
 * Copyright (C) 2017 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "linker_config.h"

#include "linker_globals.h"
#include "linker_debug.h"
#include "linker_utils.h"

#include <android-base/file.h>
#include <android-base/strings.h>

#include <private/ScopeGuard.h>

#include <stdlib.h>

#include <string>
#include <unordered_map>

class ConfigParser {
 public:
  enum {
    kProperty,
    kSection,
    kEndOfFile,
    kError,
  };

  explicit ConfigParser(std::string&& content)
      : content_(content), p_(0), lineno_(0), was_end_of_file_(false) {}

  /*
   * Possible return values
   * kProperty: name is set to property name and value is set to property value
   * kSection: name is set to section name.
   * kEndOfFile: reached end of file.
   * kError: error_msg is set.
   */
  int next_token(std::string* name, std::string* value, std::string* error_msg) {
    std::string line;
    while(NextLine(&line)) {
      size_t found = line.find('#');
      line = android::base::Trim(line.substr(0, found));

      if (line.empty()) {
        continue;
      }

      if (line[0] == '[' && line[line.size() - 1] == ']') {
        *name = line.substr(1, line.size() - 2);
        return kSection;
      }

      found = line.find('=');
      if (found == std::string::npos) {
        *error_msg = std::string("invalid format: ") +
                    line +
                    ", expected \"name = property\" or \"[section]\"";
        return kError;
      }

      *name = android::base::Trim(line.substr(0, found));
      *value = android::base::Trim(line.substr(found + 1));
      return kProperty;
    }

    // to avoid infinite cycles when programmer makes a mistake
    CHECK(!was_end_of_file_);
    was_end_of_file_ = true;
    return kEndOfFile;
  }

  size_t lineno() const {
    return lineno_;
  }

 private:
  bool NextLine(std::string* line) {
    if (p_ == std::string::npos) {
      return false;
    }

    size_t found = content_.find('\n', p_);
    if (found != std::string::npos) {
      *line = content_.substr(p_, found - p_);
      p_ = found + 1;
    } else {
      *line = content_.substr(p_);
      p_ = std::string::npos;
    }

    lineno_++;
    return true;
  }

  std::string content_;
  size_t p_;
  size_t lineno_;
  bool was_end_of_file_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ConfigParser);
};

class PropertyValue {
 public:
  PropertyValue() = default;

  PropertyValue(std::string&& value, size_t lineno)
    : value_(value), lineno_(lineno) {}

  const std::string& value() const {
    return value_;
  }

  size_t lineno() const {
    return lineno_;
  }

 private:
  std::string value_;
  size_t lineno_;
};

static std::string create_error_msg(const char* file,
                                    size_t lineno,
                                    const std::string& msg) {
  char buf[1024];
  __libc_format_buffer(buf, sizeof(buf), "%s:%zu: error: %s", file, lineno, msg.c_str());

  return std::string(buf);
}

static bool parse_config_file(const char* ld_config_file_path,
                              const char* binary_realpath,
                              std::unordered_map<std::string, PropertyValue>* properties,
                              std::string* error_msg) {
  std::string content;
  if (!android::base::ReadFileToString(ld_config_file_path, &content)) {
    if (errno != ENOENT) {
      *error_msg = std::string("error reading file \"") +
                   ld_config_file_path + "\": " + strerror(errno);
    }
    return false;
  }

  ConfigParser cp(std::move(content));

  std::string section_name;

  while(true) {
    std::string name;
    std::string value;
    std::string error;

    int result = cp.next_token(&name, &value, &error);
    if (result == ConfigParser::kError) {
      DL_WARN("error parsing %s:%zd: %s (ignoring this line)",
              ld_config_file_path,
              cp.lineno(),
              error.c_str());
      continue;
    }

    if (result == ConfigParser::kSection || result == ConfigParser::kEndOfFile) {
      return false;
    }

    if (result == ConfigParser::kProperty) {
      if (!android::base::StartsWith(name, "dir.")) {
        DL_WARN("error parsing %s:%zd: unexpected property name \"%s\", "
                "expected format dir.<section_name> (ignoring this line)",
                ld_config_file_path,
                cp.lineno(),
                name.c_str());
        continue;
      }

      // remove trailing '/'
      while (value[value.size() - 1] == '/') {
        value = value.substr(0, value.size() - 1);
      }

      if (value.empty()) {
        DL_WARN("error parsing %s:%zd: property value is empty (ignoring this line)",
                ld_config_file_path,
                cp.lineno());
        continue;
      }

      if (file_is_under_dir(binary_realpath, value)) {
        section_name = name.substr(4);
        break;
      }
    }
  }

  // skip everything until we meet a correct section
  while (true) {
    std::string name;
    std::string value;
    std::string error;

    int result = cp.next_token(&name, &value, &error);

    if (result == ConfigParser::kSection && name == section_name) {
      break;
    }

    if (result == ConfigParser::kEndOfFile) {
      *error_msg = create_error_msg(ld_config_file_path,
                                    cp.lineno(),
                                    std::string("section \"") + section_name + "\" not found");
      return false;
    }
  }

  // found the section - parse it
  while (true) {
    std::string name;
    std::string value;
    std::string error;

    int result = cp.next_token(&name, &value, &error);

    if (result == ConfigParser::kEndOfFile || result == ConfigParser::kSection) {
      break;
    }

    if (result == ConfigParser::kProperty) {
      if (properties->find(name) != properties->end()) {
        DL_WARN("%s:%zd: warning: property \"%s\" redefinition",
                ld_config_file_path,
                cp.lineno(),
                name.c_str());
      }

      (*properties)[name] = PropertyValue(std::move(value), cp.lineno());
    }

    if (result == ConfigParser::kError) {
      DL_WARN("error parsing %s:%zd: %s (ignoring this line)",
              ld_config_file_path,
              cp.lineno(),
              error.c_str());
      continue;
    }
  }

  return true;
}

static Config g_config;

static constexpr const char* kDefaultConfigName = "default";
static constexpr const char* kPropertyAdditionalNamespaces = "additional.namespaces";
#if defined(__LP64__)
static constexpr const char* kLibParamValue = "lib64";
#else
static constexpr const char* kLibParamValue = "lib";
#endif

class Properties {
 public:
  explicit Properties(std::unordered_map<std::string, PropertyValue>&& properties)
      : properties_(properties), target_sdk_version_(__ANDROID_API__) {}

  std::vector<std::string> get_strings(const std::string& name, size_t* lineno = nullptr) const {
    auto it = find_property(name, lineno);
    if (it == properties_.end()) {
      // return empty vector
      return std::vector<std::string>();
    }

    std::vector<std::string> strings = android::base::Split(it->second.value(), ",");

    for (size_t i = 0; i < strings.size(); ++i) {
      strings[i] = android::base::Trim(strings[i]);
    }

    return strings;
  }

  bool get_bool(const std::string& name, size_t* lineno = nullptr) const {
    auto it = find_property(name, lineno);
    if (it == properties_.end()) {
      return false;
    }

    return it->second.value() == "true";
  }

  std::string get_string(const std::string& name, size_t* lineno = nullptr) const {
    auto it = find_property(name, lineno);
    return (it == properties_.end()) ? "" : it->second.value();
  }

  std::vector<std::string> get_paths(const std::string& name, size_t* lineno = nullptr) {
    std::string paths_str = get_string(name, lineno);

    std::vector<std::string> paths;
    split_path(paths_str.c_str(), ":", &paths);

    std::vector<std::pair<std::string, std::string>> params;
    params.push_back({ "LIB", kLibParamValue });
    if (target_sdk_version_ != 0) {
      char buf[16];
      __libc_format_buffer(buf, sizeof(buf), "%d", target_sdk_version_);
      params.push_back({ "SDK_VER", buf });
    }

    for (auto&& path : paths) {
      format_string(&path, params);
    }

    std::vector<std::string> resolved_paths;

    // do not remove paths that do not exist
    resolve_paths(paths, &resolved_paths);

    return resolved_paths;
  }

  void set_target_sdk_version(int target_sdk_version) {
    target_sdk_version_ = target_sdk_version;
  }

 private:
  std::unordered_map<std::string, PropertyValue>::const_iterator
  find_property(const std::string& name, size_t* lineno) const {
    auto it = properties_.find(name);
    if (it != properties_.end() && lineno != nullptr) {
      *lineno = it->second.lineno();
    }

    return it;
  }
  std::unordered_map<std::string, PropertyValue> properties_;
  int target_sdk_version_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(Properties);
};

bool Config::read_binary_config(const char* ld_config_file_path,
                                      const char* binary_realpath,
                                      bool is_asan,
                                      const Config** config,
                                      std::string* error_msg) {
  g_config.clear();

  std::unordered_map<std::string, PropertyValue> property_map;
  if (!parse_config_file(ld_config_file_path, binary_realpath, &property_map, error_msg)) {
    return false;
  }

  Properties properties(std::move(property_map));

  auto failure_guard = make_scope_guard([] {
    g_config.clear();
  });

  std::unordered_map<std::string, NamespaceConfig*> namespace_configs;

  namespace_configs[kDefaultConfigName] = g_config.create_namespace_config(kDefaultConfigName);

  std::vector<std::string> additional_namespaces = properties.get_strings(kPropertyAdditionalNamespaces);
  for (const auto& name : additional_namespaces) {
    namespace_configs[name] = g_config.create_namespace_config(name);
  }

  bool versioning_enabled = properties.get_bool("enable.target.sdk.version");
  int target_sdk_version = __ANDROID_API__;
  if (versioning_enabled) {
    std::string version_file = dirname(binary_realpath) + "/.version";
    std::string content;
    if (!android::base::ReadFileToString(version_file, &content)) {
      if (errno != ENOENT) {
        *error_msg = std::string("error reading version file \"") +
                     version_file + "\": " + strerror(errno);
        return false;
      }
    } else {
      content = android::base::Trim(content);
      errno = 0;
      char* end = nullptr;
      const char* content_str = content.c_str();
      int result = strtol(content_str, &end, 10);
      if (errno == 0 && *end == '\0' && result > 0) {
        target_sdk_version = result;
        properties.set_target_sdk_version(target_sdk_version);
      } else {
        *error_msg = std::string("invalid version \"") + version_file + "\": \"" + content +"\"";
        return false;
      }
    }
  }

  g_config.set_target_sdk_version(target_sdk_version);

  for (auto ns_config_it : namespace_configs) {
    auto& name = ns_config_it.first;
    NamespaceConfig* ns_config = ns_config_it.second;

    std::string property_name_prefix = std::string("namespace.") + name;

    size_t lineno = 0;
    std::vector<std::string> linked_namespaces =
        properties.get_strings(property_name_prefix + ".links", &lineno);

    for (const auto& linked_ns_name : linked_namespaces) {
      if (namespace_configs.find(linked_ns_name) == namespace_configs.end()) {
        *error_msg = create_error_msg(ld_config_file_path,
                                      lineno,
                                      std::string("undefined namespace: ") + linked_ns_name);
        return false;
      }

      std::string shared_libs = properties.get_string(property_name_prefix +
                                                      ".link." +
                                                      linked_ns_name +
                                                      ".shared_libs", &lineno);

      if (shared_libs.empty()) {
        *error_msg = create_error_msg(ld_config_file_path,
                                      lineno,
                                      std::string("list of shared_libs for ") +
                                      name +
                                      "->" +
                                      linked_ns_name +
                                      " link is not specified or is empty.");
        return false;
      }

      ns_config->add_namespace_link(linked_ns_name, shared_libs);
    }

    ns_config->set_isolated(properties.get_bool(property_name_prefix + ".isolated"));

    // these are affected by is_asan flag
    if (is_asan) {
      property_name_prefix += ".asan";
    }

    ns_config->set_search_paths(properties.get_paths(property_name_prefix + ".search.paths"));
    ns_config->set_permitted_paths(properties.get_paths(property_name_prefix + ".permitted.paths"));
  }

  failure_guard.disable();
  *config = &g_config;
  return true;
}

NamespaceConfig* Config::create_namespace_config(const std::string& name) {
  namespace_configs_.push_back(std::unique_ptr<NamespaceConfig>(new NamespaceConfig(name)));
  NamespaceConfig* ns_config_ptr = namespace_configs_.back().get();
  namespace_configs_map_[name] = ns_config_ptr;
  return ns_config_ptr;
}

void Config::clear() {
  namespace_configs_.clear();
  namespace_configs_map_.clear();
}
