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) { 96f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(INFO) << "Parsing file " << path << "..."; 97da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes Timer t; 98f682b4786a4093efb23bf80d69bf80eb274b145bElliott Hughes std::string data; 99ef52ae14abaf091b1bece89656d80850b497e084Tom Cherry if (!read_file(path, &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 109331cf2fb7c16b5b25064f8d2f00284105a9b413fElliott Hughes LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)"; 110e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes return true; 1116310a8261c922533a692fb3e74ece2da98d4bafaColin Cross} 1126310a8261c922533a692fb3e74ece2da98d4bafaColin Cross 113b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Parser::ParseConfigDir(const std::string& path) { 114f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes LOG(INFO) << "Parsing directory " << path << "..."; 115b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry std::unique_ptr<DIR, int(*)(DIR*)> config_dir(opendir(path.c_str()), closedir); 116f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell if (!config_dir) { 117f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes PLOG(ERROR) << "Could not import directory '" << path << "'"; 118f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell return false; 119f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 120f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell dirent* current_file; 1212de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten std::vector<std::string> files; 122f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell while ((current_file = readdir(config_dir.get()))) { 123f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell // Ignore directories and only process regular files. 124f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell if (current_file->d_type == DT_REG) { 1252de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten std::string current_path = 1262de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name); 1272de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten files.emplace_back(current_path); 1282de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten } 1292de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten } 1302de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten // Sort first so we load files in a consistent order (bug 31996208) 1312de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten std::sort(files.begin(), files.end()); 1322de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten for (const auto& file : files) { 1332de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten if (!ParseConfigFile(file)) { 1342de796491aed1c5c40af94d9c9b08a385a309e1fGlenn Kasten LOG(ERROR) << "could not import file '" << file << "'"; 135f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 136f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 137f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell return true; 138f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell} 139f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell 140b7349902a945903f9e36a569051f5131beb0bc24Tom Cherrybool Parser::ParseConfig(const std::string& path) { 141b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry if (is_dir(path.c_str())) { 142b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return ParseConfigDir(path); 143f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell } 144b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry return ParseConfigFile(path); 145f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell} 146f13b1b31399aa501514eb9beeef303d1ae2e0e14Lee Campbell 147b7349902a945903f9e36a569051f5131beb0bc24Tom Cherryvoid Parser::DumpState() const { 148b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ServiceManager::GetInstance().DumpState(); 149b7349902a945903f9e36a569051f5131beb0bc24Tom Cherry ActionManager::GetInstance().DumpState(); 1506310a8261c922533a692fb3e74ece2da98d4bafaColin Cross} 151