summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--init/persistent_properties.cpp110
1 files changed, 9 insertions, 101 deletions
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
index 71f235532..21adce914 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -43,7 +43,6 @@ std::string persistent_property_filename = "/data/property/persistent_properties
43 43
44namespace { 44namespace {
45 45
46constexpr const uint32_t kMagic = 0x8495E0B4;
47constexpr const char kLegacyPersistentPropertyDir[] = "/data/property"; 46constexpr const char kLegacyPersistentPropertyDir[] = "/data/property";
48 47
49void AddPersistentProperty(const std::string& name, const std::string& value, 48void AddPersistentProperty(const std::string& name, const std::string& value,
@@ -140,85 +139,6 @@ PersistentProperties LoadPersistentPropertiesFromMemory() {
140 return persistent_properties; 139 return persistent_properties;
141} 140}
142 141
143class PersistentPropertyFileParser {
144 public:
145 PersistentPropertyFileParser(const std::string& contents) : contents_(contents), position_(0) {}
146 Result<PersistentProperties> Parse();
147
148 private:
149 Result<std::string> ReadString();
150 Result<uint32_t> ReadUint32();
151
152 const std::string& contents_;
153 size_t position_;
154};
155
156Result<PersistentProperties> PersistentPropertyFileParser::Parse() {
157 if (auto magic = ReadUint32(); magic) {
158 if (*magic != kMagic) {
159 return Error() << "Magic value '0x" << std::hex << *magic
160 << "' does not match expected value '0x" << kMagic << "'";
161 }
162 } else {
163 return Error() << "Could not read magic value: " << magic.error();
164 }
165
166 if (auto version = ReadUint32(); version) {
167 if (*version != 1) {
168 return Error() << "Version '" << *version
169 << "' does not match any compatible version: (1)";
170 }
171 } else {
172 return Error() << "Could not read version: " << version.error();
173 }
174
175 auto num_properties = ReadUint32();
176 if (!num_properties) {
177 return Error() << "Could not read num_properties: " << num_properties.error();
178 }
179
180 PersistentProperties result;
181 while (position_ < contents_.size()) {
182 auto name = ReadString();
183 if (!name) {
184 return Error() << "Could not read name: " << name.error();
185 }
186 if (!StartsWith(*name, "persist.")) {
187 return Error() << "Property '" << *name << "' does not starts with 'persist.'";
188 }
189 auto value = ReadString();
190 if (!value) {
191 return Error() << "Could not read value: " << value.error();
192 }
193 AddPersistentProperty(*name, *value, &result);
194 }
195
196 return result;
197}
198
199Result<std::string> PersistentPropertyFileParser::ReadString() {
200 auto string_length = ReadUint32();
201 if (!string_length) {
202 return Error() << "Could not read size for string";
203 }
204
205 if (position_ + *string_length > contents_.size()) {
206 return Error() << "String size would cause it to overflow the input buffer";
207 }
208 auto result = std::string(contents_, position_, *string_length);
209 position_ += *string_length;
210 return result;
211}
212
213Result<uint32_t> PersistentPropertyFileParser::ReadUint32() {
214 if (position_ + 3 > contents_.size()) {
215 return Error() << "Input buffer not large enough to read uint32_t";
216 }
217 uint32_t result = *reinterpret_cast<const uint32_t*>(&contents_[position_]);
218 position_ += sizeof(uint32_t);
219 return result;
220}
221
222Result<std::string> ReadPersistentPropertyFile() { 142Result<std::string> ReadPersistentPropertyFile() {
223 const std::string temp_filename = persistent_property_filename + ".tmp"; 143 const std::string temp_filename = persistent_property_filename + ".tmp";
224 if (access(temp_filename.c_str(), F_OK) == 0) { 144 if (access(temp_filename.c_str(), F_OK) == 0) {
@@ -240,24 +160,13 @@ Result<PersistentProperties> LoadPersistentPropertyFile() {
240 auto file_contents = ReadPersistentPropertyFile(); 160 auto file_contents = ReadPersistentPropertyFile();
241 if (!file_contents) return file_contents.error(); 161 if (!file_contents) return file_contents.error();
242 162
243 // Check the intermediate "I should have used protobufs from the start" format.
244 // TODO: Remove this.
245 auto parsed_contents = PersistentPropertyFileParser(*file_contents).Parse();
246 if (parsed_contents) {
247 LOG(INFO) << "Intermediate format persistent property file found, converting to protobuf";
248
249 // Update to the protobuf format
250 WritePersistentPropertyFile(*parsed_contents);
251 return parsed_contents;
252 }
253
254 PersistentProperties persistent_properties; 163 PersistentProperties persistent_properties;
255 if (persistent_properties.ParseFromString(*file_contents)) return persistent_properties; 164 if (persistent_properties.ParseFromString(*file_contents)) return persistent_properties;
256 165
257 // If the file cannot be parsed in either format, then we don't have any recovery 166 // If the file cannot be parsed in either format, then we don't have any recovery
258 // mechanisms, so we delete it to allow for future writes to take place successfully. 167 // mechanisms, so we delete it to allow for future writes to take place successfully.
259 unlink(persistent_property_filename.c_str()); 168 unlink(persistent_property_filename.c_str());
260 return Error() << "Unable to parse persistent property file: " << parsed_contents.error(); 169 return Error() << "Unable to parse persistent property file: Could not parse protobuf";
261} 170}
262 171
263Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties) { 172Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties) {
@@ -288,25 +197,24 @@ Result<Success> WritePersistentPropertyFile(const PersistentProperties& persiste
288// Persistent properties are not written often, so we rather not keep any data in memory and read 197// Persistent properties are not written often, so we rather not keep any data in memory and read
289// then rewrite the persistent property file for each update. 198// then rewrite the persistent property file for each update.
290void WritePersistentProperty(const std::string& name, const std::string& value) { 199void WritePersistentProperty(const std::string& name, const std::string& value) {
291 auto file_contents = ReadPersistentPropertyFile(); 200 auto persistent_properties = LoadPersistentPropertyFile();
292 PersistentProperties persistent_properties;
293 201
294 if (!file_contents || !persistent_properties.ParseFromString(*file_contents)) { 202 if (!persistent_properties) {
295 LOG(ERROR) << "Recovering persistent properties from memory: " 203 LOG(ERROR) << "Recovering persistent properties from memory: "
296 << (!file_contents ? file_contents.error_string() : "Could not parse protobuf"); 204 << persistent_properties.error();
297 persistent_properties = LoadPersistentPropertiesFromMemory(); 205 persistent_properties = LoadPersistentPropertiesFromMemory();
298 } 206 }
299 auto it = std::find_if(persistent_properties.mutable_properties()->begin(), 207 auto it = std::find_if(persistent_properties->mutable_properties()->begin(),
300 persistent_properties.mutable_properties()->end(), 208 persistent_properties->mutable_properties()->end(),
301 [&name](const auto& record) { return record.name() == name; }); 209 [&name](const auto& record) { return record.name() == name; });
302 if (it != persistent_properties.mutable_properties()->end()) { 210 if (it != persistent_properties->mutable_properties()->end()) {
303 it->set_name(name); 211 it->set_name(name);
304 it->set_value(value); 212 it->set_value(value);
305 } else { 213 } else {
306 AddPersistentProperty(name, value, &persistent_properties); 214 AddPersistentProperty(name, value, &persistent_properties.value());
307 } 215 }
308 216
309 if (auto result = WritePersistentPropertyFile(persistent_properties); !result) { 217 if (auto result = WritePersistentPropertyFile(*persistent_properties); !result) {
310 LOG(ERROR) << "Could not store persistent property: " << result.error(); 218 LOG(ERROR) << "Could not store persistent property: " << result.error();
311 } 219 }
312} 220}