diff options
| -rw-r--r-- | cmds/installd/file_parsing.h | 60 | ||||
| -rw-r--r-- | cmds/installd/otapreopt.cpp | 76 | ||||
| -rw-r--r-- | cmds/installd/system_properties.h | 30 |
3 files changed, 112 insertions, 54 deletions
diff --git a/cmds/installd/file_parsing.h b/cmds/installd/file_parsing.h new file mode 100644 index 0000000000..3e2f815f32 --- /dev/null +++ b/cmds/installd/file_parsing.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef OTAPREOPT_FILE_PARSING_H_ +#define OTAPREOPT_FILE_PARSING_H_ + +#include <fstream> +#include <functional> +#include <string> + +namespace android { +namespace installd { + +bool ParseFile(const std::string& strFile, std::function<bool (const std::string&)> parse) { + std::ifstream input_stream(strFile); + + if (!input_stream.is_open()) { + return false; + } + + while (!input_stream.eof()) { + // Read the next line. + std::string line; + getline(input_stream, line); + + // Is the line empty? Simplifies the next check. + if (line.empty()) { + continue; + } + + // Is this a comment (starts with pound)? + if (line[0] == '#') { + continue; + } + + if (!parse(line)) { + return false; + } + } + + return true; +} + +} // namespace installd +} // namespace android + +#endif // OTAPREOPT_FILE_PARSING_H_ diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp index da454a7d31..89a4225ed2 100644 --- a/cmds/installd/otapreopt.cpp +++ b/cmds/installd/otapreopt.cpp @@ -17,6 +17,7 @@ #include <algorithm> #include <inttypes.h> #include <random> +#include <regex> #include <selinux/android.h> #include <selinux/avc.h> #include <stdlib.h> @@ -35,6 +36,7 @@ #include <private/android_filesystem_config.h> #include <commands.h> +#include <file_parsing.h> #include <globals.h> #include <installd_deps.h> // Need to fill in requirements of commands. #include <string_helpers.h> @@ -54,8 +56,8 @@ using android::base::StringPrintf; namespace android { namespace installd { -static constexpr const char* kBootClassPathPropertyName = "env.BOOTCLASSPATH"; -static constexpr const char* kAndroidRootPathPropertyName = "env.ANDROID_ROOT"; +static constexpr const char* kBootClassPathPropertyName = "BOOTCLASSPATH"; +static constexpr const char* kAndroidRootPathPropertyName = "ANDROID_ROOT"; static constexpr const char* kOTARootDirectory = "/system-b"; static constexpr size_t kISAIndex = 3; @@ -131,41 +133,55 @@ class OTAPreoptService { private: bool ReadSystemProperties() { - // TODO(agampe): What to do about the things in default.prop? It's only heap sizes, so it's easy - // to emulate for now, but has issues (e.g., vendors modifying the boot classpath - // may require larger values here - revisit). That's why this goes first, so that - // if those dummy values are overridden in build.prop, that's what we'll get. - // - // Note: It seems we'll get access to the B root partition, so we should read the default.prop - // file. - // if (!system_properties_.Load("/default.prop")) { - // return false; - // } - system_properties_.SetProperty("dalvik.vm.image-dex2oat-Xms", "64m"); - system_properties_.SetProperty("dalvik.vm.image-dex2oat-Xmx", "64m"); - system_properties_.SetProperty("dalvik.vm.dex2oat-Xms", "64m"); - system_properties_.SetProperty("dalvik.vm.dex2oat-Xmx", "512m"); - - // TODO(agampe): Do this properly/test. - return system_properties_.Load("/system/build.prop"); + static constexpr const char* kPropertyFiles[] = { + "/default.prop", "/system/build.prop" + }; + + for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) { + if (!system_properties_.Load(kPropertyFiles[i])) { + return false; + } + } + + return true; } bool ReadEnvironment() { - // Read important environment variables. For simplicity, store them as - // system properties. - // TODO(agampe): We'll have to parse init.environ.rc for BOOTCLASSPATH. - // For now, just the A version. - const char* boot_classpath = getenv("BOOTCLASSPATH"); - if (boot_classpath == nullptr) { + // Parse the environment variables from init.environ.rc, which have the form + // export NAME VALUE + // For simplicity, don't respect string quotation. The values we are interested in can be + // encoded without them. + std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)"); + bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) { + std::smatch export_match; + if (!std::regex_match(line, export_match, export_regex)) { + return true; + } + + if (export_match.size() != 3) { + return true; + } + + std::string name = export_match[1].str(); + std::string value = export_match[2].str(); + + system_properties_.SetProperty(name, value); + + return true; + }); + if (!parse_result) { return false; } - system_properties_.SetProperty(kBootClassPathPropertyName, boot_classpath); - const char* root_path = getenv("ANDROID_ROOT"); - if (root_path == nullptr) { - return false; + // Check that we found important properties. + constexpr const char* kRequiredProperties[] = { + kBootClassPathPropertyName, kAndroidRootPathPropertyName + }; + for (size_t i = 0; i < arraysize(kRequiredProperties); ++i) { + if (system_properties_.GetProperty(kRequiredProperties[i]) == nullptr) { + return false; + } } - system_properties_.SetProperty(kAndroidRootPathPropertyName, root_path); return true; } diff --git a/cmds/installd/system_properties.h b/cmds/installd/system_properties.h index 1b5fb3aac2..2d940a325f 100644 --- a/cmds/installd/system_properties.h +++ b/cmds/installd/system_properties.h @@ -21,6 +21,8 @@ #include <string> #include <unordered_map> +#include <file_parsing.h> + namespace android { namespace installd { @@ -28,31 +30,11 @@ namespace installd { class SystemProperties { public: bool Load(const std::string& strFile) { - std::ifstream input_stream(strFile); - - if (!input_stream.is_open()) { - return false; - } - - while (!input_stream.eof()) { - // Read the next line. - std::string line; - getline(input_stream, line); - - // Is the line empty? Simplifies the next check. - if (line.empty()) { - continue; - } - - // Is this a comment (starts with pound)? - if (line[0] == '#') { - continue; - } - + return ParseFile(strFile, [&](const std::string& line) { size_t equals_pos = line.find('='); if (equals_pos == std::string::npos || equals_pos == 0) { // Did not find equals sign, or it's the first character - isn't a valid line. - continue; + return true; } std::string key = line.substr(0, equals_pos); @@ -60,9 +42,9 @@ class SystemProperties { line.length() - equals_pos + 1); properties_.insert(std::make_pair(key, value)); - } - return true; + return true; + }); } // Look up the key in the map. Returns null if the key isn't mapped. |