Loading init/Android.bp +7 −1 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ cc_library_static { "log.cpp", "log.cpp", "parser.cpp", "parser.cpp", "persistent_properties.cpp", "persistent_properties.cpp", "persistent_properties.proto", "property_service.cpp", "property_service.cpp", "security.cpp", "security.cpp", "selinux.cpp", "selinux.cpp", Loading @@ -90,11 +91,15 @@ cc_library_static { "liblog", "liblog", "libprocessgroup", "libprocessgroup", "libfs_mgr", "libfs_mgr", "libprotobuf-cpp-lite", ], ], include_dirs: [ include_dirs: [ "system/core/mkbootimg", "system/core/mkbootimg", ], ], proto: { type: "lite", export_proto_headers: true, }, } } /* /* Loading Loading @@ -179,6 +184,7 @@ cc_test { "libinit", "libinit", "libselinux", "libselinux", "libcrypto", "libcrypto", "libprotobuf-cpp-lite", ], ], } } Loading init/Android.mk +1 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,7 @@ LOCAL_STATIC_LIBRARIES := \ libprocessgroup \ libprocessgroup \ libavb \ libavb \ libkeyutils \ libkeyutils \ libprotobuf-cpp-lite \ LOCAL_REQUIRED_MODULES := \ LOCAL_REQUIRED_MODULES := \ e2fsdroid \ e2fsdroid \ Loading init/persistent_properties.cpp +67 −70 Original line number Original line Diff line number Diff line Loading @@ -46,14 +46,21 @@ namespace { constexpr const uint32_t kMagic = 0x8495E0B4; constexpr const uint32_t kMagic = 0x8495E0B4; constexpr const char kLegacyPersistentPropertyDir[] = "/data/property"; constexpr const char kLegacyPersistentPropertyDir[] = "/data/property"; Result<std::vector<std::pair<std::string, std::string>>> LoadLegacyPersistentProperties() { void AddPersistentProperty(const std::string& name, const std::string& value, PersistentProperties* persistent_properties) { auto persistent_property_record = persistent_properties->add_properties(); persistent_property_record->set_name(name); persistent_property_record->set_value(value); } Result<PersistentProperties> LoadLegacyPersistentProperties() { std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kLegacyPersistentPropertyDir), closedir); std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kLegacyPersistentPropertyDir), closedir); if (!dir) { if (!dir) { return ErrnoError() << "Unable to open persistent property directory \"" return ErrnoError() << "Unable to open persistent property directory \"" << kLegacyPersistentPropertyDir << "\""; << kLegacyPersistentPropertyDir << "\""; } } std::vector<std::pair<std::string, std::string>> persistent_properties; PersistentProperties persistent_properties; dirent* entry; dirent* entry; while ((entry = readdir(dir.get())) != nullptr) { while ((entry = readdir(dir.get())) != nullptr) { if (!StartsWith(entry->d_name, "persist.")) { if (!StartsWith(entry->d_name, "persist.")) { Loading Loading @@ -87,7 +94,7 @@ Result<std::vector<std::pair<std::string, std::string>>> LoadLegacyPersistentPro std::string value; std::string value; if (ReadFdToString(fd, &value)) { if (ReadFdToString(fd, &value)) { persistent_properties.emplace_back(entry->d_name, value); AddPersistentProperty(entry->d_name, value, &persistent_properties); } else { } else { PLOG(ERROR) << "Unable to read persistent property file " << entry->d_name; PLOG(ERROR) << "Unable to read persistent property file " << entry->d_name; } } Loading Loading @@ -115,30 +122,28 @@ void RemoveLegacyPersistentPropertyFiles() { } } } } std::vector<std::pair<std::string, std::string>> LoadPersistentPropertiesFromMemory() { PersistentProperties LoadPersistentPropertiesFromMemory() { std::vector<std::pair<std::string, std::string>> properties; PersistentProperties persistent_properties; __system_property_foreach( __system_property_foreach( [](const prop_info* pi, void* cookie) { [](const prop_info* pi, void* cookie) { __system_property_read_callback( __system_property_read_callback( pi, pi, [](void* cookie, const char* name, const char* value, unsigned serial) { [](void* cookie, const char* name, const char* value, unsigned serial) { if (StartsWith(name, "persist.")) { if (StartsWith(name, "persist.")) { auto properties = auto properties = reinterpret_cast<PersistentProperties*>(cookie); reinterpret_cast<std::vector<std::pair<std::string, std::string>>*>( AddPersistentProperty(name, value, properties); cookie); properties->emplace_back(name, value); } } }, }, cookie); cookie); }, }, &properties); &persistent_properties); return properties; return persistent_properties; } } class PersistentPropertyFileParser { class PersistentPropertyFileParser { public: public: PersistentPropertyFileParser(const std::string& contents) : contents_(contents), position_(0) {} PersistentPropertyFileParser(const std::string& contents) : contents_(contents), position_(0) {} Result<std::vector<std::pair<std::string, std::string>>> Parse(); Result<PersistentProperties> Parse(); private: private: Result<std::string> ReadString(); Result<std::string> ReadString(); Loading @@ -148,9 +153,7 @@ class PersistentPropertyFileParser { size_t position_; size_t position_; }; }; Result<std::vector<std::pair<std::string, std::string>>> PersistentPropertyFileParser::Parse() { Result<PersistentProperties> PersistentPropertyFileParser::Parse() { std::vector<std::pair<std::string, std::string>> result; if (auto magic = ReadUint32(); magic) { if (auto magic = ReadUint32(); magic) { if (*magic != kMagic) { if (*magic != kMagic) { return Error() << "Magic value '0x" << std::hex << *magic return Error() << "Magic value '0x" << std::hex << *magic Loading @@ -174,24 +177,20 @@ Result<std::vector<std::pair<std::string, std::string>>> PersistentPropertyFileP return Error() << "Could not read num_properties: " << num_properties.error(); return Error() << "Could not read num_properties: " << num_properties.error(); } } PersistentProperties result; while (position_ < contents_.size()) { while (position_ < contents_.size()) { auto key = ReadString(); auto name = ReadString(); if (!key) { if (!name) { return Error() << "Could not read key: " << key.error(); return Error() << "Could not read name: " << name.error(); } } if (!StartsWith(*key, "persist.")) { if (!StartsWith(*name, "persist.")) { return Error() << "Property '" << *key << "' does not starts with 'persist.'"; return Error() << "Property '" << *name << "' does not starts with 'persist.'"; } } auto value = ReadString(); auto value = ReadString(); if (!value) { if (!value) { return Error() << "Could not read value: " << value.error(); return Error() << "Could not read value: " << value.error(); } } result.emplace_back(*key, *value); AddPersistentProperty(*name, *value, &result); } if (result.size() != *num_properties) { return Error() << "Mismatch of number of persistent properties read, " << result.size() << " and number of persistent properties expected, " << *num_properties; } } return result; return result; Loading Loading @@ -220,9 +219,7 @@ Result<uint32_t> PersistentPropertyFileParser::ReadUint32() { return result; return result; } } } // namespace Result<std::string> ReadPersistentPropertyFile() { Result<std::vector<std::pair<std::string, std::string>>> LoadPersistentPropertyFile() { const std::string temp_filename = persistent_property_filename + ".tmp"; const std::string temp_filename = persistent_property_filename + ".tmp"; if (access(temp_filename.c_str(), F_OK) == 0) { if (access(temp_filename.c_str(), F_OK) == 0) { LOG(INFO) LOG(INFO) Loading @@ -234,51 +231,47 @@ Result<std::vector<std::pair<std::string, std::string>>> LoadPersistentPropertyF if (!file_contents) { if (!file_contents) { return Error() << "Unable to read persistent property file: " << file_contents.error(); return Error() << "Unable to read persistent property file: " << file_contents.error(); } } auto parsed_contents = PersistentPropertyFileParser(*file_contents).Parse(); return *file_contents; if (!parsed_contents) { // If the file cannot be parsed, then we don't have any recovery mechanisms, so we delete // it to allow for future writes to take place successfully. unlink(persistent_property_filename.c_str()); return Error() << "Unable to parse persistent property file: " << parsed_contents.error(); } } return parsed_contents; } std::string GenerateFileContents( const std::vector<std::pair<std::string, std::string>>& persistent_properties) { std::string result; uint32_t magic = kMagic; } // namespace result.append(reinterpret_cast<char*>(&magic), sizeof(uint32_t)); uint32_t version = 1; Result<PersistentProperties> LoadPersistentPropertyFile() { result.append(reinterpret_cast<char*>(&version), sizeof(uint32_t)); auto file_contents = ReadPersistentPropertyFile(); if (!file_contents) return file_contents.error(); uint32_t num_properties = persistent_properties.size(); // Check the intermediate "I should have used protobufs from the start" format. result.append(reinterpret_cast<char*>(&num_properties), sizeof(uint32_t)); // TODO: Remove this. auto parsed_contents = PersistentPropertyFileParser(*file_contents).Parse(); if (parsed_contents) { LOG(INFO) << "Intermediate format persistent property file found, converting to protobuf"; for (const auto& [key, value] : persistent_properties) { // Update to the protobuf format uint32_t key_length = key.length(); WritePersistentPropertyFile(*parsed_contents); result.append(reinterpret_cast<char*>(&key_length), sizeof(uint32_t)); return parsed_contents; result.append(key); uint32_t value_length = value.length(); result.append(reinterpret_cast<char*>(&value_length), sizeof(uint32_t)); result.append(value); } return result; } } Result<Success> WritePersistentPropertyFile( PersistentProperties persistent_properties; const std::vector<std::pair<std::string, std::string>>& persistent_properties) { if (persistent_properties.ParseFromString(*file_contents)) return persistent_properties; auto file_contents = GenerateFileContents(persistent_properties); // If the file cannot be parsed in either format, then we don't have any recovery // mechanisms, so we delete it to allow for future writes to take place successfully. unlink(persistent_property_filename.c_str()); return Error() << "Unable to parse persistent property file: " << parsed_contents.error(); } Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties) { const std::string temp_filename = persistent_property_filename + ".tmp"; const std::string temp_filename = persistent_property_filename + ".tmp"; unique_fd fd(TEMP_FAILURE_RETRY( unique_fd fd(TEMP_FAILURE_RETRY( open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600))); open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600))); if (fd == -1) { if (fd == -1) { return ErrnoError() << "Could not open temporary properties file"; return ErrnoError() << "Could not open temporary properties file"; } } if (!WriteStringToFd(file_contents, fd)) { std::string serialized_string; if (!persistent_properties.SerializeToString(&serialized_string)) { return Error() << "Unable to serialize properties"; } if (!WriteStringToFd(serialized_string, fd)) { return ErrnoError() << "Unable to write file contents"; return ErrnoError() << "Unable to write file contents"; } } fsync(fd); fsync(fd); Loading @@ -295,26 +288,30 @@ Result<Success> WritePersistentPropertyFile( // Persistent properties are not written often, so we rather not keep any data in memory and read // Persistent properties are not written often, so we rather not keep any data in memory and read // then rewrite the persistent property file for each update. // then rewrite the persistent property file for each update. void WritePersistentProperty(const std::string& name, const std::string& value) { void WritePersistentProperty(const std::string& name, const std::string& value) { auto persistent_properties = LoadPersistentPropertyFile(); auto file_contents = ReadPersistentPropertyFile(); if (!persistent_properties) { PersistentProperties persistent_properties; if (!file_contents || !persistent_properties.ParseFromString(*file_contents)) { LOG(ERROR) << "Recovering persistent properties from memory: " LOG(ERROR) << "Recovering persistent properties from memory: " << persistent_properties.error(); << (!file_contents ? file_contents.error_string() : "Could not parse protobuf"); persistent_properties = LoadPersistentPropertiesFromMemory(); persistent_properties = LoadPersistentPropertiesFromMemory(); } } auto it = std::find_if(persistent_properties->begin(), persistent_properties->end(), auto it = std::find_if(persistent_properties.mutable_properties()->begin(), [&name](const auto& entry) { return entry.first == name; }); persistent_properties.mutable_properties()->end(), if (it != persistent_properties->end()) { [&name](const auto& record) { return record.name() == name; }); *it = {name, value}; if (it != persistent_properties.mutable_properties()->end()) { it->set_name(name); it->set_value(value); } else { } else { persistent_properties->emplace_back(name, value); AddPersistentProperty(name, value, &persistent_properties); } } if (auto result = WritePersistentPropertyFile(*persistent_properties); !result) { if (auto result = WritePersistentPropertyFile(persistent_properties); !result) { LOG(ERROR) << "Could not store persistent property: " << result.error(); LOG(ERROR) << "Could not store persistent property: " << result.error(); } } } } std::vector<std::pair<std::string, std::string>> LoadPersistentProperties() { PersistentProperties LoadPersistentProperties() { auto persistent_properties = LoadPersistentPropertyFile(); auto persistent_properties = LoadPersistentPropertyFile(); if (!persistent_properties) { if (!persistent_properties) { Loading init/persistent_properties.h +4 −7 Original line number Original line Diff line number Diff line Loading @@ -18,22 +18,19 @@ #define _INIT_PERSISTENT_PROPERTIES_H #define _INIT_PERSISTENT_PROPERTIES_H #include <string> #include <string> #include <vector> #include "result.h" #include "result.h" #include "system/core/init/persistent_properties.pb.h" namespace android { namespace android { namespace init { namespace init { std::vector<std::pair<std::string, std::string>> LoadPersistentProperties(); PersistentProperties LoadPersistentProperties(); void WritePersistentProperty(const std::string& name, const std::string& value); void WritePersistentProperty(const std::string& name, const std::string& value); // Exposed only for testing // Exposed only for testing Result<std::vector<std::pair<std::string, std::string>>> LoadPersistentPropertyFile(); Result<PersistentProperties> LoadPersistentPropertyFile(); std::string GenerateFileContents( Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties); const std::vector<std::pair<std::string, std::string>>& persistent_properties); Result<Success> WritePersistentPropertyFile( const std::vector<std::pair<std::string, std::string>>& persistent_properties); extern std::string persistent_property_filename; extern std::string persistent_property_filename; } // namespace init } // namespace init Loading init/persistent_properties.proto 0 → 100644 +27 −0 Original line number Original line Diff line number Diff line /* * 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. */ syntax = "proto2"; option optimize_for = LITE_RUNTIME; message PersistentProperties { message PersistentPropertyRecord { optional string name = 1; optional string value = 2; } repeated PersistentPropertyRecord properties = 1; } Loading
init/Android.bp +7 −1 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ cc_library_static { "log.cpp", "log.cpp", "parser.cpp", "parser.cpp", "persistent_properties.cpp", "persistent_properties.cpp", "persistent_properties.proto", "property_service.cpp", "property_service.cpp", "security.cpp", "security.cpp", "selinux.cpp", "selinux.cpp", Loading @@ -90,11 +91,15 @@ cc_library_static { "liblog", "liblog", "libprocessgroup", "libprocessgroup", "libfs_mgr", "libfs_mgr", "libprotobuf-cpp-lite", ], ], include_dirs: [ include_dirs: [ "system/core/mkbootimg", "system/core/mkbootimg", ], ], proto: { type: "lite", export_proto_headers: true, }, } } /* /* Loading Loading @@ -179,6 +184,7 @@ cc_test { "libinit", "libinit", "libselinux", "libselinux", "libcrypto", "libcrypto", "libprotobuf-cpp-lite", ], ], } } Loading
init/Android.mk +1 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,7 @@ LOCAL_STATIC_LIBRARIES := \ libprocessgroup \ libprocessgroup \ libavb \ libavb \ libkeyutils \ libkeyutils \ libprotobuf-cpp-lite \ LOCAL_REQUIRED_MODULES := \ LOCAL_REQUIRED_MODULES := \ e2fsdroid \ e2fsdroid \ Loading
init/persistent_properties.cpp +67 −70 Original line number Original line Diff line number Diff line Loading @@ -46,14 +46,21 @@ namespace { constexpr const uint32_t kMagic = 0x8495E0B4; constexpr const uint32_t kMagic = 0x8495E0B4; constexpr const char kLegacyPersistentPropertyDir[] = "/data/property"; constexpr const char kLegacyPersistentPropertyDir[] = "/data/property"; Result<std::vector<std::pair<std::string, std::string>>> LoadLegacyPersistentProperties() { void AddPersistentProperty(const std::string& name, const std::string& value, PersistentProperties* persistent_properties) { auto persistent_property_record = persistent_properties->add_properties(); persistent_property_record->set_name(name); persistent_property_record->set_value(value); } Result<PersistentProperties> LoadLegacyPersistentProperties() { std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kLegacyPersistentPropertyDir), closedir); std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kLegacyPersistentPropertyDir), closedir); if (!dir) { if (!dir) { return ErrnoError() << "Unable to open persistent property directory \"" return ErrnoError() << "Unable to open persistent property directory \"" << kLegacyPersistentPropertyDir << "\""; << kLegacyPersistentPropertyDir << "\""; } } std::vector<std::pair<std::string, std::string>> persistent_properties; PersistentProperties persistent_properties; dirent* entry; dirent* entry; while ((entry = readdir(dir.get())) != nullptr) { while ((entry = readdir(dir.get())) != nullptr) { if (!StartsWith(entry->d_name, "persist.")) { if (!StartsWith(entry->d_name, "persist.")) { Loading Loading @@ -87,7 +94,7 @@ Result<std::vector<std::pair<std::string, std::string>>> LoadLegacyPersistentPro std::string value; std::string value; if (ReadFdToString(fd, &value)) { if (ReadFdToString(fd, &value)) { persistent_properties.emplace_back(entry->d_name, value); AddPersistentProperty(entry->d_name, value, &persistent_properties); } else { } else { PLOG(ERROR) << "Unable to read persistent property file " << entry->d_name; PLOG(ERROR) << "Unable to read persistent property file " << entry->d_name; } } Loading Loading @@ -115,30 +122,28 @@ void RemoveLegacyPersistentPropertyFiles() { } } } } std::vector<std::pair<std::string, std::string>> LoadPersistentPropertiesFromMemory() { PersistentProperties LoadPersistentPropertiesFromMemory() { std::vector<std::pair<std::string, std::string>> properties; PersistentProperties persistent_properties; __system_property_foreach( __system_property_foreach( [](const prop_info* pi, void* cookie) { [](const prop_info* pi, void* cookie) { __system_property_read_callback( __system_property_read_callback( pi, pi, [](void* cookie, const char* name, const char* value, unsigned serial) { [](void* cookie, const char* name, const char* value, unsigned serial) { if (StartsWith(name, "persist.")) { if (StartsWith(name, "persist.")) { auto properties = auto properties = reinterpret_cast<PersistentProperties*>(cookie); reinterpret_cast<std::vector<std::pair<std::string, std::string>>*>( AddPersistentProperty(name, value, properties); cookie); properties->emplace_back(name, value); } } }, }, cookie); cookie); }, }, &properties); &persistent_properties); return properties; return persistent_properties; } } class PersistentPropertyFileParser { class PersistentPropertyFileParser { public: public: PersistentPropertyFileParser(const std::string& contents) : contents_(contents), position_(0) {} PersistentPropertyFileParser(const std::string& contents) : contents_(contents), position_(0) {} Result<std::vector<std::pair<std::string, std::string>>> Parse(); Result<PersistentProperties> Parse(); private: private: Result<std::string> ReadString(); Result<std::string> ReadString(); Loading @@ -148,9 +153,7 @@ class PersistentPropertyFileParser { size_t position_; size_t position_; }; }; Result<std::vector<std::pair<std::string, std::string>>> PersistentPropertyFileParser::Parse() { Result<PersistentProperties> PersistentPropertyFileParser::Parse() { std::vector<std::pair<std::string, std::string>> result; if (auto magic = ReadUint32(); magic) { if (auto magic = ReadUint32(); magic) { if (*magic != kMagic) { if (*magic != kMagic) { return Error() << "Magic value '0x" << std::hex << *magic return Error() << "Magic value '0x" << std::hex << *magic Loading @@ -174,24 +177,20 @@ Result<std::vector<std::pair<std::string, std::string>>> PersistentPropertyFileP return Error() << "Could not read num_properties: " << num_properties.error(); return Error() << "Could not read num_properties: " << num_properties.error(); } } PersistentProperties result; while (position_ < contents_.size()) { while (position_ < contents_.size()) { auto key = ReadString(); auto name = ReadString(); if (!key) { if (!name) { return Error() << "Could not read key: " << key.error(); return Error() << "Could not read name: " << name.error(); } } if (!StartsWith(*key, "persist.")) { if (!StartsWith(*name, "persist.")) { return Error() << "Property '" << *key << "' does not starts with 'persist.'"; return Error() << "Property '" << *name << "' does not starts with 'persist.'"; } } auto value = ReadString(); auto value = ReadString(); if (!value) { if (!value) { return Error() << "Could not read value: " << value.error(); return Error() << "Could not read value: " << value.error(); } } result.emplace_back(*key, *value); AddPersistentProperty(*name, *value, &result); } if (result.size() != *num_properties) { return Error() << "Mismatch of number of persistent properties read, " << result.size() << " and number of persistent properties expected, " << *num_properties; } } return result; return result; Loading Loading @@ -220,9 +219,7 @@ Result<uint32_t> PersistentPropertyFileParser::ReadUint32() { return result; return result; } } } // namespace Result<std::string> ReadPersistentPropertyFile() { Result<std::vector<std::pair<std::string, std::string>>> LoadPersistentPropertyFile() { const std::string temp_filename = persistent_property_filename + ".tmp"; const std::string temp_filename = persistent_property_filename + ".tmp"; if (access(temp_filename.c_str(), F_OK) == 0) { if (access(temp_filename.c_str(), F_OK) == 0) { LOG(INFO) LOG(INFO) Loading @@ -234,51 +231,47 @@ Result<std::vector<std::pair<std::string, std::string>>> LoadPersistentPropertyF if (!file_contents) { if (!file_contents) { return Error() << "Unable to read persistent property file: " << file_contents.error(); return Error() << "Unable to read persistent property file: " << file_contents.error(); } } auto parsed_contents = PersistentPropertyFileParser(*file_contents).Parse(); return *file_contents; if (!parsed_contents) { // If the file cannot be parsed, then we don't have any recovery mechanisms, so we delete // it to allow for future writes to take place successfully. unlink(persistent_property_filename.c_str()); return Error() << "Unable to parse persistent property file: " << parsed_contents.error(); } } return parsed_contents; } std::string GenerateFileContents( const std::vector<std::pair<std::string, std::string>>& persistent_properties) { std::string result; uint32_t magic = kMagic; } // namespace result.append(reinterpret_cast<char*>(&magic), sizeof(uint32_t)); uint32_t version = 1; Result<PersistentProperties> LoadPersistentPropertyFile() { result.append(reinterpret_cast<char*>(&version), sizeof(uint32_t)); auto file_contents = ReadPersistentPropertyFile(); if (!file_contents) return file_contents.error(); uint32_t num_properties = persistent_properties.size(); // Check the intermediate "I should have used protobufs from the start" format. result.append(reinterpret_cast<char*>(&num_properties), sizeof(uint32_t)); // TODO: Remove this. auto parsed_contents = PersistentPropertyFileParser(*file_contents).Parse(); if (parsed_contents) { LOG(INFO) << "Intermediate format persistent property file found, converting to protobuf"; for (const auto& [key, value] : persistent_properties) { // Update to the protobuf format uint32_t key_length = key.length(); WritePersistentPropertyFile(*parsed_contents); result.append(reinterpret_cast<char*>(&key_length), sizeof(uint32_t)); return parsed_contents; result.append(key); uint32_t value_length = value.length(); result.append(reinterpret_cast<char*>(&value_length), sizeof(uint32_t)); result.append(value); } return result; } } Result<Success> WritePersistentPropertyFile( PersistentProperties persistent_properties; const std::vector<std::pair<std::string, std::string>>& persistent_properties) { if (persistent_properties.ParseFromString(*file_contents)) return persistent_properties; auto file_contents = GenerateFileContents(persistent_properties); // If the file cannot be parsed in either format, then we don't have any recovery // mechanisms, so we delete it to allow for future writes to take place successfully. unlink(persistent_property_filename.c_str()); return Error() << "Unable to parse persistent property file: " << parsed_contents.error(); } Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties) { const std::string temp_filename = persistent_property_filename + ".tmp"; const std::string temp_filename = persistent_property_filename + ".tmp"; unique_fd fd(TEMP_FAILURE_RETRY( unique_fd fd(TEMP_FAILURE_RETRY( open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600))); open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600))); if (fd == -1) { if (fd == -1) { return ErrnoError() << "Could not open temporary properties file"; return ErrnoError() << "Could not open temporary properties file"; } } if (!WriteStringToFd(file_contents, fd)) { std::string serialized_string; if (!persistent_properties.SerializeToString(&serialized_string)) { return Error() << "Unable to serialize properties"; } if (!WriteStringToFd(serialized_string, fd)) { return ErrnoError() << "Unable to write file contents"; return ErrnoError() << "Unable to write file contents"; } } fsync(fd); fsync(fd); Loading @@ -295,26 +288,30 @@ Result<Success> WritePersistentPropertyFile( // Persistent properties are not written often, so we rather not keep any data in memory and read // Persistent properties are not written often, so we rather not keep any data in memory and read // then rewrite the persistent property file for each update. // then rewrite the persistent property file for each update. void WritePersistentProperty(const std::string& name, const std::string& value) { void WritePersistentProperty(const std::string& name, const std::string& value) { auto persistent_properties = LoadPersistentPropertyFile(); auto file_contents = ReadPersistentPropertyFile(); if (!persistent_properties) { PersistentProperties persistent_properties; if (!file_contents || !persistent_properties.ParseFromString(*file_contents)) { LOG(ERROR) << "Recovering persistent properties from memory: " LOG(ERROR) << "Recovering persistent properties from memory: " << persistent_properties.error(); << (!file_contents ? file_contents.error_string() : "Could not parse protobuf"); persistent_properties = LoadPersistentPropertiesFromMemory(); persistent_properties = LoadPersistentPropertiesFromMemory(); } } auto it = std::find_if(persistent_properties->begin(), persistent_properties->end(), auto it = std::find_if(persistent_properties.mutable_properties()->begin(), [&name](const auto& entry) { return entry.first == name; }); persistent_properties.mutable_properties()->end(), if (it != persistent_properties->end()) { [&name](const auto& record) { return record.name() == name; }); *it = {name, value}; if (it != persistent_properties.mutable_properties()->end()) { it->set_name(name); it->set_value(value); } else { } else { persistent_properties->emplace_back(name, value); AddPersistentProperty(name, value, &persistent_properties); } } if (auto result = WritePersistentPropertyFile(*persistent_properties); !result) { if (auto result = WritePersistentPropertyFile(persistent_properties); !result) { LOG(ERROR) << "Could not store persistent property: " << result.error(); LOG(ERROR) << "Could not store persistent property: " << result.error(); } } } } std::vector<std::pair<std::string, std::string>> LoadPersistentProperties() { PersistentProperties LoadPersistentProperties() { auto persistent_properties = LoadPersistentPropertyFile(); auto persistent_properties = LoadPersistentPropertyFile(); if (!persistent_properties) { if (!persistent_properties) { Loading
init/persistent_properties.h +4 −7 Original line number Original line Diff line number Diff line Loading @@ -18,22 +18,19 @@ #define _INIT_PERSISTENT_PROPERTIES_H #define _INIT_PERSISTENT_PROPERTIES_H #include <string> #include <string> #include <vector> #include "result.h" #include "result.h" #include "system/core/init/persistent_properties.pb.h" namespace android { namespace android { namespace init { namespace init { std::vector<std::pair<std::string, std::string>> LoadPersistentProperties(); PersistentProperties LoadPersistentProperties(); void WritePersistentProperty(const std::string& name, const std::string& value); void WritePersistentProperty(const std::string& name, const std::string& value); // Exposed only for testing // Exposed only for testing Result<std::vector<std::pair<std::string, std::string>>> LoadPersistentPropertyFile(); Result<PersistentProperties> LoadPersistentPropertyFile(); std::string GenerateFileContents( Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties); const std::vector<std::pair<std::string, std::string>>& persistent_properties); Result<Success> WritePersistentPropertyFile( const std::vector<std::pair<std::string, std::string>>& persistent_properties); extern std::string persistent_property_filename; extern std::string persistent_property_filename; } // namespace init } // namespace init Loading
init/persistent_properties.proto 0 → 100644 +27 −0 Original line number Original line Diff line number Diff line /* * 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. */ syntax = "proto2"; option optimize_for = LITE_RUNTIME; message PersistentProperties { message PersistentPropertyRecord { optional string name = 1; optional string value = 2; } repeated PersistentPropertyRecord properties = 1; }