16310a8261c922533a692fb3e74ece2da98d4bafaColin Cross/* 26310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * Copyright (C) 2010 The Android Open Source Project 36310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * 46310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * Licensed under the Apache License, Version 2.0 (the "License"); 56310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * you may not use this file except in compliance with the License. 66310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * You may obtain a copy of the License at 76310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * 86310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * http://www.apache.org/licenses/LICENSE-2.0 96310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * 106310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * Unless required by applicable law or agreed to in writing, software 116310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * distributed under the License is distributed on an "AS IS" BASIS, 126310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * See the License for the specific language governing permissions and 146310a8261c922533a692fb3e74ece2da98d4bafaColin Cross * limitations under the License. 156310a8261c922533a692fb3e74ece2da98d4bafaColin Cross */ 166310a8261c922533a692fb3e74ece2da98d4bafaColin Cross 17f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell#include <dirent.h> 188d82ea05cb0945ba6cb8bf321b9ffbd0b6932745Elliott Hughes#include <errno.h> 196310a8261c922533a692fb3e74ece2da98d4bafaColin Cross#include <fcntl.h> 206310a8261c922533a692fb3e74ece2da98d4bafaColin Cross 21fa0c21c94ccb98bfa5cf3cc7a6b220be4a5fa378Tom Cherry#include "action.h" 226310a8261c922533a692fb3e74ece2da98d4bafaColin Cross#include "init_parser.h" 236310a8261c922533a692fb3e74ece2da98d4bafaColin Cross#include "log.h" 24bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "parser.h" 25bac3299720623f4226bca103b26260052732ad30Tom Cherry#include "service.h" 266310a8261c922533a692fb3e74ece2da98d4bafaColin Cross#include "util.h" 276310a8261c922533a692fb3e74ece2da98d4bafaColin Cross 284f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h> 296310a8261c922533a692fb3e74ece2da98d4bafaColin Cross 30b7349902a945903f9e36a569051f5131beb0bc24Tom CherryParser::Parser() { 31c0e919c92062360a69b771722677d041c9998403Elliott Hughes} 32c0e919c92062360a69b771722677d041c9998403Elliott Hughes 33b7349902a945903f9e36a569051f5131beb0bc24Tom CherryParser& Parser::GetInstance() { 34b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry static Parser instance; 35b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return instance; 36a6235eacf4b06b14b19125618d7aca570dbc02b0Dima Zavin} 37a6235eacf4b06b14b19125618d7aca570dbc02b0Dima Zavin 38b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid Parser::AddSectionParser(const std::string& name, 39b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::unique_ptr<SectionParser> parser) { 40b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry section_parsers_[name] = std::move(parser); 4178a1b1fe1ab76964e35b4a4788238b197bfd613dDima Zavin} 4278a1b1fe1ab76964e35b4a4788238b197bfd613dDima Zavin 43b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid Parser::ParseData(const std::string& filename, const std::string& data) { 444ad60fbae51ef4a0b4a4beaa5128d823063c158cTom Cherry //TODO: Use a parser with const input and remove this copy 454ad60fbae51ef4a0b4a4beaa5128d823063c158cTom Cherry std::vector<char> data_copy(data.begin(), data.end()); 464ad60fbae51ef4a0b4a4beaa5128d823063c158cTom Cherry data_copy.push_back('\0'); 474ad60fbae51ef4a0b4a4beaa5128d823063c158cTom Cherry 48eaa3b4ec6f79fe06163b8dd6fe8ba2581d3b9c0bTom Cherry parse_state state; 49b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry state.filename = filename.c_str(); 501be6968d9d51f43fdb00535708a6fed0be6bfbcaBruce Beare state.line = 0; 514ad60fbae51ef4a0b4a4beaa5128d823063c158cTom Cherry state.ptr = &data_copy[0]; 526310a8261c922533a692fb3e74ece2da98d4bafaColin Cross state.nexttoken = 0; 5378a1b1fe1ab76964e35b4a4788238b197bfd613dDima Zavin 54b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry SectionParser* section_parser = nullptr; 55b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::vector<std::string> args; 5678a1b1fe1ab76964e35b4a4788238b197bfd613dDima Zavin 576310a8261c922533a692fb3e74ece2da98d4bafaColin Cross for (;;) { 586310a8261c922533a692fb3e74ece2da98d4bafaColin Cross switch (next_token(&state)) { 596310a8261c922533a692fb3e74ece2da98d4bafaColin Cross case T_EOF: 60b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (section_parser) { 61b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry section_parser->EndSection(); 62b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 63b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return; 646310a8261c922533a692fb3e74ece2da98d4bafaColin Cross case T_NEWLINE: 651be6968d9d51f43fdb00535708a6fed0be6bfbcaBruce Beare state.line++; 66b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (args.empty()) { 67b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry break; 68b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 69b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (section_parsers_.count(args[0])) { 70b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (section_parser) { 71b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry section_parser->EndSection(); 72b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 73b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry section_parser = section_parsers_[args[0]].get(); 74b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string ret_err; 75b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!section_parser->ParseSection(args, &ret_err)) { 76b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry parse_error(&state, "%s\n", ret_err.c_str()); 77b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry section_parser = nullptr; 78b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 79b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } else if (section_parser) { 80b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::string ret_err; 81b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!section_parser->ParseLineSection(args, state.filename, 82b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry state.line, &ret_err)) { 83b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry parse_error(&state, "%s\n", ret_err.c_str()); 846310a8261c922533a692fb3e74ece2da98d4bafaColin Cross } 856310a8261c922533a692fb3e74ece2da98d4bafaColin Cross } 86b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry args.clear(); 876310a8261c922533a692fb3e74ece2da98d4bafaColin Cross break; 886310a8261c922533a692fb3e74ece2da98d4bafaColin Cross case T_TEXT: 89b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry args.emplace_back(state.text); 906310a8261c922533a692fb3e74ece2da98d4bafaColin Cross break; 916310a8261c922533a692fb3e74ece2da98d4bafaColin Cross } 926310a8261c922533a692fb3e74ece2da98d4bafaColin Cross } 936310a8261c922533a692fb3e74ece2da98d4bafaColin Cross} 946310a8261c922533a692fb3e74ece2da98d4bafaColin Cross 95b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Parser::ParseConfigFile(const std::string& path) { 96b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry INFO("Parsing file %s...\n", path.c_str()); 97da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes Timer t; 98f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes std::string data; 99b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!read_file(path.c_str(), &data)) { 100e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes return false; 101f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes } 1026310a8261c922533a692fb3e74ece2da98d4bafaColin Cross 103eaa3b4ec6f79fe06163b8dd6fe8ba2581d3b9c0bTom Cherry data.push_back('\n'); // TODO: fix parse_config. 104b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ParseData(path, data); 105b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry for (const auto& sp : section_parsers_) { 106b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry sp.second->EndFile(path); 107b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry } 1081946d3bca8a3b05d2a527606c06948882940287cElliott Hughes 1091946d3bca8a3b05d2a527606c06948882940287cElliott Hughes // Turning this on and letting the INFO logging be discarded adds 0.2s to 1101946d3bca8a3b05d2a527606c06948882940287cElliott Hughes // Nexus 9 boot time, so it's disabled by default. 1111946d3bca8a3b05d2a527606c06948882940287cElliott Hughes if (false) DumpState(); 112da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes 113b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry NOTICE("(Parsing %s took %.2fs.)\n", path.c_str(), t.duration()); 114e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes return true; 1156310a8261c922533a692fb3e74ece2da98d4bafaColin Cross} 1166310a8261c922533a692fb3e74ece2da98d4bafaColin Cross 117b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Parser::ParseConfigDir(const std::string& path) { 118b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry INFO("Parsing directory %s...\n", path.c_str()); 119b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::unique_ptr<DIR, int(*)(DIR*)> config_dir(opendir(path.c_str()), closedir); 120f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell if (!config_dir) { 121b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ERROR("Could not import directory '%s'\n", path.c_str()); 122f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell return false; 123f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 124f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell dirent* current_file; 125f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell while ((current_file = readdir(config_dir.get()))) { 126f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell std::string current_path = 127b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name); 128f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell // Ignore directories and only process regular files. 129f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell if (current_file->d_type == DT_REG) { 130b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (!ParseConfigFile(current_path)) { 131f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell ERROR("could not import file '%s'\n", current_path.c_str()); 132f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 133f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 134f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 135f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell return true; 136f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell} 137f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell 138b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Parser::ParseConfig(const std::string& path) { 139b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (is_dir(path.c_str())) { 140b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return ParseConfigDir(path); 141f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 142b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return ParseConfigFile(path); 143f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell} 144f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell 145b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid Parser::DumpState() const { 146b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ServiceManager::GetInstance().DumpState(); 147b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ActionManager::GetInstance().DumpState(); 1486310a8261c922533a692fb3e74ece2da98d4bafaColin Cross} 149