/* * Copyright (C) 2017 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 #include #include #include #include #include #include #include #include "utils.h" namespace android { namespace vintf { namespace details { // fake sysprops using Properties = std::map; enum Option : int { DUMP_FILE_LIST = 1, ROOTDIR, HELP, PROPERTY, CHECK_COMPAT, }; // command line arguments using Args = std::multimap; class HostFileSystem : public FileSystemUnderPath { public: HostFileSystem(const std::string& rootdir) : FileSystemUnderPath(rootdir) {} status_t fetch(const std::string& path, std::string* fetched, std::string* error) const override { status_t status = FileSystemUnderPath::fetch(path, fetched, error); std::cerr << "Debug: Fetch '" << getRootDir() << path << "': " << toString(status) << std::endl; return status; } status_t listFiles(const std::string& path, std::vector* out, std::string* error) const override { status_t status = FileSystemUnderPath::listFiles(path, out, error); std::cerr << "Debug: List '" << getRootDir() << path << "': " << toString(status) << std::endl; return status; } private: static std::string toString(status_t status) { return status == OK ? "SUCCESS" : strerror(-status); } }; class PresetPropertyFetcher : public PropertyFetcher { public: std::string getProperty(const std::string& key, const std::string& defaultValue) const override { auto it = mProps.find(key); if (it == mProps.end()) { std::cerr << "Debug: Sysprop " << key << " is missing, default to '" << defaultValue << "'" << std::endl; return defaultValue; } std::cerr << "Debug: Sysprop " << key << "=" << it->second << std::endl; return it->second; } uint64_t getUintProperty(const std::string& key, uint64_t defaultValue, uint64_t max) const override { uint64_t result; std::string value = getProperty(key, ""); if (!value.empty() && android::base::ParseUint(value, &result, max)) return result; return defaultValue; } bool getBoolProperty(const std::string& key, bool defaultValue) const override { std::string value = getProperty(key, ""); if (value == "1" || value == "true") { return true; } else if (value == "0" || value == "false") { return false; } return defaultValue; } void setProperties(const Properties& props) { mProps.insert(props.begin(), props.end()); } private: std::map mProps; }; // helper functions template std::unique_ptr readObject(FileSystem* fileSystem, const std::string& path, const XmlConverter& converter) { std::string xml; std::string error; status_t err = fileSystem->fetch(path, &xml, &error); if (err != OK) { std::cerr << "Error: Cannot read '" << path << "' (" << strerror(-err) << "): " << error << std::endl; return nullptr; } auto ret = std::make_unique(); if (!converter(ret.get(), xml, &error)) { std::cerr << "Error: Cannot parse '" << path << "': " << error << std::endl; return nullptr; } return ret; } int checkCompatibilityForFiles(const std::string& manifestPath, const std::string& matrixPath) { auto fileSystem = std::make_unique(); auto manifest = readObject(fileSystem.get(), manifestPath, gHalManifestConverter); auto matrix = readObject(fileSystem.get(), matrixPath, gCompatibilityMatrixConverter); if (manifest == nullptr || matrix == nullptr) { return -1; } std::string error; if (!manifest->checkCompatibility(*matrix, &error)) { std::cerr << "Error: Incompatible: " << error << std::endl; std::cout << "false" << std::endl; return 1; } std::cout << "true" << std::endl; return 0; } Args parseArgs(int argc, char** argv) { int longOptFlag; int optionIndex; Args ret; std::vector longopts{ {"dump-file-list", no_argument, &longOptFlag, DUMP_FILE_LIST}, {"rootdir", required_argument, &longOptFlag, ROOTDIR}, {"help", no_argument, &longOptFlag, HELP}, {"property", required_argument, &longOptFlag, PROPERTY}, {"check-compat", no_argument, &longOptFlag, CHECK_COMPAT}, {0, 0, 0, 0}}; std::map shortopts{ {'h', HELP}, {'D', PROPERTY}, {'c', CHECK_COMPAT}, }; for (;;) { int c = getopt_long(argc, argv, "hcD:", longopts.data(), &optionIndex); if (c == -1) { break; } std::string argValue = optarg ? optarg : std::string{}; if (c == 0) { ret.emplace(static_cast