| Alex Deymo | aea4c1c | 2015-08-19 20:24:43 -0700 | [diff] [blame] | 1 | // | 
|  | 2 | // Copyright (C) 2012 The Android Open Source Project | 
|  | 3 | // | 
|  | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | // you may not use this file except in compliance with the License. | 
|  | 6 | // You may obtain a copy of the License at | 
|  | 7 | // | 
|  | 8 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | // | 
|  | 10 | // Unless required by applicable law or agreed to in writing, software | 
|  | 11 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | // See the License for the specific language governing permissions and | 
|  | 14 | // limitations under the License. | 
|  | 15 | // | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 16 |  | 
| Alex Deymo | 39910dc | 2015-11-09 17:04:30 -0800 | [diff] [blame] | 17 | #include "update_engine/common/prefs.h" | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 18 |  | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 19 | #include <algorithm> | 
| Daniel Zheng | 5eece04 | 2023-05-17 14:44:10 -0700 | [diff] [blame] | 20 | #include <filesystem> | 
|  | 21 | #include <unistd.h> | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 22 |  | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 23 | #include <base/files/file_enumerator.h> | 
| Ben Chan | 06c76a4 | 2014-09-05 08:21:06 -0700 | [diff] [blame] | 24 | #include <base/files/file_util.h> | 
| Darin Petkov | 3627577 | 2010-10-01 11:40:57 -0700 | [diff] [blame] | 25 | #include <base/logging.h> | 
| Alex Vakulenko | 75039d7 | 2014-03-25 12:36:28 -0700 | [diff] [blame] | 26 | #include <base/strings/string_number_conversions.h> | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 27 | #include <base/strings/string_split.h> | 
| Alex Vakulenko | 75039d7 | 2014-03-25 12:36:28 -0700 | [diff] [blame] | 28 | #include <base/strings/string_util.h> | 
| Darin Petkov | 3627577 | 2010-10-01 11:40:57 -0700 | [diff] [blame] | 29 |  | 
| Daniel Zheng | 5eece04 | 2023-05-17 14:44:10 -0700 | [diff] [blame] | 30 | #include "update_engine/common/platform_constants.h" | 
| Alex Deymo | 39910dc | 2015-11-09 17:04:30 -0800 | [diff] [blame] | 31 | #include "update_engine/common/utils.h" | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 32 |  | 
|  | 33 | using std::string; | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 34 | using std::vector; | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 35 |  | 
|  | 36 | namespace chromeos_update_engine { | 
|  | 37 |  | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 38 | namespace { | 
|  | 39 |  | 
|  | 40 | void DeleteEmptyDirectories(const base::FilePath& path) { | 
|  | 41 | base::FileEnumerator path_enum( | 
|  | 42 | path, false /* recursive */, base::FileEnumerator::DIRECTORIES); | 
|  | 43 | for (base::FilePath dir_path = path_enum.Next(); !dir_path.empty(); | 
|  | 44 | dir_path = path_enum.Next()) { | 
|  | 45 | DeleteEmptyDirectories(dir_path); | 
|  | 46 | if (base::IsDirectoryEmpty(dir_path)) | 
| hscham | 043355b | 2020-11-17 16:50:10 +0900 | [diff] [blame] | 47 | #if BASE_VER < 800000 | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 48 | base::DeleteFile(dir_path, false); | 
| hscham | 043355b | 2020-11-17 16:50:10 +0900 | [diff] [blame] | 49 | #else | 
|  | 50 | base::DeleteFile(dir_path); | 
|  | 51 | #endif | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 52 | } | 
|  | 53 | } | 
|  | 54 |  | 
|  | 55 | }  // namespace | 
|  | 56 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 57 | bool PrefsBase::GetString(const std::string_view key, string* value) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 58 | return storage_->GetKey(key, value); | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 59 | } | 
|  | 60 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 61 | bool PrefsBase::SetString(std::string_view key, std::string_view value) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 62 | TEST_AND_RETURN_FALSE(storage_->SetKey(key, value)); | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 63 | const auto observers_for_key = observers_.find(key); | 
|  | 64 | if (observers_for_key != observers_.end()) { | 
|  | 65 | std::vector<ObserverInterface*> copy_observers(observers_for_key->second); | 
|  | 66 | for (ObserverInterface* observer : copy_observers) | 
|  | 67 | observer->OnPrefSet(key); | 
|  | 68 | } | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 69 | return true; | 
|  | 70 | } | 
|  | 71 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 72 | bool PrefsBase::GetInt64(const std::string_view key, int64_t* value) const { | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 73 | string str_value; | 
| Jay Srinivasan | 08fce04 | 2012-06-07 16:31:01 -0700 | [diff] [blame] | 74 | if (!GetString(key, &str_value)) | 
|  | 75 | return false; | 
| Ben Chan | 736fcb5 | 2014-05-21 18:28:22 -0700 | [diff] [blame] | 76 | base::TrimWhitespaceASCII(str_value, base::TRIM_ALL, &str_value); | 
| Chris Masone | 790e62e | 2010-08-12 10:41:18 -0700 | [diff] [blame] | 77 | TEST_AND_RETURN_FALSE(base::StringToInt64(str_value, value)); | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 78 | return true; | 
|  | 79 | } | 
|  | 80 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 81 | bool PrefsBase::SetInt64(std::string_view key, const int64_t value) { | 
| hscham | 00b6aa2 | 2020-02-20 12:32:06 +0900 | [diff] [blame] | 82 | return SetString(key, base::NumberToString(value)); | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 83 | } | 
|  | 84 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 85 | bool PrefsBase::GetBoolean(std::string_view key, bool* value) const { | 
| Alex Deymo | efb7c4c | 2013-07-09 14:34:00 -0700 | [diff] [blame] | 86 | string str_value; | 
|  | 87 | if (!GetString(key, &str_value)) | 
|  | 88 | return false; | 
| Ben Chan | 736fcb5 | 2014-05-21 18:28:22 -0700 | [diff] [blame] | 89 | base::TrimWhitespaceASCII(str_value, base::TRIM_ALL, &str_value); | 
| Alex Deymo | efb7c4c | 2013-07-09 14:34:00 -0700 | [diff] [blame] | 90 | if (str_value == "false") { | 
|  | 91 | *value = false; | 
|  | 92 | return true; | 
|  | 93 | } | 
|  | 94 | if (str_value == "true") { | 
|  | 95 | *value = true; | 
|  | 96 | return true; | 
|  | 97 | } | 
|  | 98 | return false; | 
|  | 99 | } | 
|  | 100 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 101 | bool PrefsBase::SetBoolean(std::string_view key, const bool value) { | 
| Alex Deymo | efb7c4c | 2013-07-09 14:34:00 -0700 | [diff] [blame] | 102 | return SetString(key, value ? "true" : "false"); | 
|  | 103 | } | 
|  | 104 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 105 | bool PrefsBase::Exists(std::string_view key) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 106 | return storage_->KeyExists(key); | 
| Jay Srinivasan | 480ddfa | 2012-06-01 19:15:26 -0700 | [diff] [blame] | 107 | } | 
|  | 108 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 109 | bool PrefsBase::Delete(std::string_view key) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 110 | TEST_AND_RETURN_FALSE(storage_->DeleteKey(key)); | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 111 | const auto observers_for_key = observers_.find(key); | 
|  | 112 | if (observers_for_key != observers_.end()) { | 
|  | 113 | std::vector<ObserverInterface*> copy_observers(observers_for_key->second); | 
|  | 114 | for (ObserverInterface* observer : copy_observers) | 
|  | 115 | observer->OnPrefDeleted(key); | 
|  | 116 | } | 
|  | 117 | return true; | 
|  | 118 | } | 
|  | 119 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 120 | bool PrefsBase::Delete(std::string_view pref_key, const vector<string>& nss) { | 
| Vyshu Khota | 4c5413d | 2020-11-04 16:17:25 -0800 | [diff] [blame] | 121 | // Delete pref key for platform. | 
|  | 122 | bool success = Delete(pref_key); | 
|  | 123 | // Delete pref key in each namespace. | 
|  | 124 | for (const auto& ns : nss) { | 
|  | 125 | vector<string> namespace_keys; | 
|  | 126 | success = GetSubKeys(ns, &namespace_keys) && success; | 
|  | 127 | for (const auto& key : namespace_keys) { | 
|  | 128 | auto last_key_seperator = key.find_last_of(kKeySeparator); | 
|  | 129 | if (last_key_seperator != string::npos && | 
|  | 130 | pref_key == key.substr(last_key_seperator + 1)) { | 
|  | 131 | success = Delete(key) && success; | 
|  | 132 | } | 
|  | 133 | } | 
|  | 134 | } | 
|  | 135 | return success; | 
|  | 136 | } | 
|  | 137 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 138 | bool PrefsBase::GetSubKeys(std::string_view ns, vector<string>* keys) const { | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 139 | return storage_->GetSubKeys(ns, keys); | 
|  | 140 | } | 
|  | 141 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 142 | void PrefsBase::AddObserver(std::string_view key, ObserverInterface* observer) { | 
|  | 143 | observers_[std::string{key}].push_back(observer); | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 144 | } | 
|  | 145 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 146 | void PrefsBase::RemoveObserver(std::string_view key, | 
|  | 147 | ObserverInterface* observer) { | 
|  | 148 | std::vector<ObserverInterface*>& observers_for_key = | 
|  | 149 | observers_[std::string{key}]; | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 150 | auto observer_it = | 
|  | 151 | std::find(observers_for_key.begin(), observers_for_key.end(), observer); | 
|  | 152 | if (observer_it != observers_for_key.end()) | 
|  | 153 | observers_for_key.erase(observer_it); | 
| Jay Srinivasan | 480ddfa | 2012-06-01 19:15:26 -0700 | [diff] [blame] | 154 | } | 
|  | 155 |  | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 156 | string PrefsInterface::CreateSubKey(const vector<string>& ns_and_key) { | 
|  | 157 | return base::JoinString(ns_and_key, string(1, kKeySeparator)); | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 158 | } | 
|  | 159 |  | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 160 | // Prefs | 
|  | 161 |  | 
|  | 162 | bool Prefs::Init(const base::FilePath& prefs_dir) { | 
|  | 163 | return file_storage_.Init(prefs_dir); | 
|  | 164 | } | 
|  | 165 |  | 
| Daniel Zheng | 5eece04 | 2023-05-17 14:44:10 -0700 | [diff] [blame] | 166 | bool PrefsBase::StartTransaction() { | 
|  | 167 | return storage_->CreateTemporaryPrefs(); | 
|  | 168 | } | 
|  | 169 |  | 
|  | 170 | bool PrefsBase::CancelTransaction() { | 
|  | 171 | return storage_->DeleteTemporaryPrefs(); | 
|  | 172 | } | 
|  | 173 |  | 
|  | 174 | bool PrefsBase::SubmitTransaction() { | 
|  | 175 | return storage_->SwapPrefs(); | 
|  | 176 | } | 
|  | 177 |  | 
|  | 178 | std::string Prefs::FileStorage::GetTemporaryDir() const { | 
|  | 179 | return prefs_dir_.value() + "_tmp"; | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | bool Prefs::FileStorage::CreateTemporaryPrefs() { | 
|  | 183 | // Delete any existing prefs_tmp | 
|  | 184 | DeleteTemporaryPrefs(); | 
|  | 185 | // Get the paths to the source and destination directories. | 
|  | 186 | std::filesystem::path source_directory(prefs_dir_.value()); | 
|  | 187 | std::filesystem::path destination_directory(GetTemporaryDir()); | 
|  | 188 |  | 
|  | 189 | if (!std::filesystem::exists(source_directory)) { | 
|  | 190 | LOG(ERROR) << "prefs directory does not exist: " << source_directory; | 
|  | 191 | return false; | 
|  | 192 | } | 
|  | 193 | // Copy the directory. | 
|  | 194 | std::filesystem::copy(source_directory, destination_directory); | 
|  | 195 |  | 
|  | 196 | return true; | 
|  | 197 | } | 
|  | 198 |  | 
|  | 199 | bool Prefs::FileStorage::DeleteTemporaryPrefs() { | 
|  | 200 | std::filesystem::path destination_directory(GetTemporaryDir()); | 
|  | 201 |  | 
|  | 202 | if (std::filesystem::exists(destination_directory)) { | 
|  | 203 | return std::filesystem::remove_all(destination_directory); | 
|  | 204 | } | 
|  | 205 | return true; | 
|  | 206 | } | 
|  | 207 |  | 
|  | 208 | bool Prefs::FileStorage::SwapPrefs() { | 
|  | 209 | if (std::filesystem::exists(prefs_dir_.value())) { | 
|  | 210 | std::filesystem::remove_all(prefs_dir_.value()); | 
|  | 211 | } | 
|  | 212 | if (rename(GetTemporaryDir().c_str(), prefs_dir_.value().c_str()) != 0) { | 
|  | 213 | LOG(ERROR) << "Error replacing prefs with prefs_tmp" << strerror(errno); | 
|  | 214 | return false; | 
|  | 215 | } | 
|  | 216 | return true; | 
|  | 217 | } | 
|  | 218 |  | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 219 | bool Prefs::FileStorage::Init(const base::FilePath& prefs_dir) { | 
|  | 220 | prefs_dir_ = prefs_dir; | 
| Daniel Zheng | 5eece04 | 2023-05-17 14:44:10 -0700 | [diff] [blame] | 221 |  | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 222 | // Delete empty directories. Ignore errors when deleting empty directories. | 
| Jae Hoon Kim | c1f3692 | 2020-05-11 18:20:18 -0700 | [diff] [blame] | 223 | DeleteEmptyDirectories(prefs_dir_); | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 224 | return true; | 
|  | 225 | } | 
|  | 226 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 227 | bool Prefs::FileStorage::GetKey(std::string_view key, string* value) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 228 | base::FilePath filename; | 
|  | 229 | TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); | 
|  | 230 | if (!base::ReadFileToString(filename, value)) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 231 | return false; | 
|  | 232 | } | 
|  | 233 | return true; | 
|  | 234 | } | 
|  | 235 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 236 | bool Prefs::FileStorage::GetSubKeys(std::string_view ns, | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 237 | vector<string>* keys) const { | 
|  | 238 | base::FilePath filename; | 
|  | 239 | TEST_AND_RETURN_FALSE(GetFileNameForKey(ns, &filename)); | 
|  | 240 | base::FileEnumerator namespace_enum( | 
|  | 241 | prefs_dir_, true, base::FileEnumerator::FILES); | 
|  | 242 | for (base::FilePath f = namespace_enum.Next(); !f.empty(); | 
|  | 243 | f = namespace_enum.Next()) { | 
|  | 244 | auto filename_str = filename.value(); | 
|  | 245 | if (f.value().compare(0, filename_str.length(), filename_str) == 0) { | 
|  | 246 | // Only return the key portion excluding the |prefs_dir_| with slash. | 
|  | 247 | keys->push_back(f.value().substr( | 
|  | 248 | prefs_dir_.AsEndingWithSeparator().value().length())); | 
|  | 249 | } | 
|  | 250 | } | 
|  | 251 | return true; | 
|  | 252 | } | 
|  | 253 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 254 | bool Prefs::FileStorage::SetKey(std::string_view key, std::string_view value) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 255 | base::FilePath filename; | 
|  | 256 | TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); | 
|  | 257 | if (!base::DirectoryExists(filename.DirName())) { | 
|  | 258 | // Only attempt to create the directory if it doesn't exist to avoid calls | 
|  | 259 | // to parent directories where we might not have permission to write to. | 
|  | 260 | TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName())); | 
|  | 261 | } | 
| Kelvin Zhang | 49170aa | 2022-11-28 10:55:16 -0800 | [diff] [blame] | 262 | TEST_AND_RETURN_FALSE( | 
|  | 263 | utils::WriteStringToFileAtomic(filename.value(), value)); | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 264 | return true; | 
|  | 265 | } | 
|  | 266 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 267 | bool Prefs::FileStorage::KeyExists(std::string_view key) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 268 | base::FilePath filename; | 
|  | 269 | TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); | 
|  | 270 | return base::PathExists(filename); | 
|  | 271 | } | 
|  | 272 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 273 | bool Prefs::FileStorage::DeleteKey(std::string_view key) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 274 | base::FilePath filename; | 
|  | 275 | TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename)); | 
| hscham | 043355b | 2020-11-17 16:50:10 +0900 | [diff] [blame] | 276 | #if BASE_VER < 800000 | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 277 | TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false)); | 
| hscham | 043355b | 2020-11-17 16:50:10 +0900 | [diff] [blame] | 278 | #else | 
|  | 279 | TEST_AND_RETURN_FALSE(base::DeleteFile(filename)); | 
|  | 280 | #endif | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 281 | return true; | 
|  | 282 | } | 
|  | 283 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 284 | bool Prefs::FileStorage::GetFileNameForKey(std::string_view key, | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 285 | base::FilePath* filename) const { | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 286 | // Allows only non-empty keys containing [A-Za-z0-9_-/]. | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 287 | TEST_AND_RETURN_FALSE(!key.empty()); | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 288 | for (char c : key) | 
| Alex Vakulenko | 0103c36 | 2016-01-20 07:56:15 -0800 | [diff] [blame] | 289 | TEST_AND_RETURN_FALSE(base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || | 
| Andrew | 065d78d | 2020-04-07 15:43:07 -0700 | [diff] [blame] | 290 | c == '_' || c == '-' || c == kKeySeparator); | 
| Daniel Zheng | 5eece04 | 2023-05-17 14:44:10 -0700 | [diff] [blame] | 291 | if (std::filesystem::exists(GetTemporaryDir())) { | 
|  | 292 | *filename = | 
|  | 293 | base::FilePath(GetTemporaryDir()) | 
|  | 294 | .Append(base::FilePath::StringPieceType(key.data(), key.size())); | 
|  | 295 | } else { | 
|  | 296 | *filename = prefs_dir_.Append( | 
|  | 297 | base::FilePath::StringPieceType(key.data(), key.size())); | 
|  | 298 | } | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 299 | return true; | 
|  | 300 | } | 
|  | 301 |  | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 302 | // MemoryPrefs | 
|  | 303 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 304 | bool MemoryPrefs::MemoryStorage::GetKey(std::string_view key, | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 305 | string* value) const { | 
|  | 306 | auto it = values_.find(key); | 
|  | 307 | if (it == values_.end()) | 
|  | 308 | return false; | 
|  | 309 | *value = it->second; | 
|  | 310 | return true; | 
|  | 311 | } | 
|  | 312 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 313 | bool MemoryPrefs::MemoryStorage::GetSubKeys(std::string_view ns, | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 314 | vector<string>* keys) const { | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 315 | auto lower_comp = [](const auto& pr, const auto& ns) { | 
|  | 316 | return std::string_view{pr.first.data(), ns.length()} < ns; | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 317 | }; | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 318 | auto upper_comp = [](const auto& ns, const auto& pr) { | 
|  | 319 | return ns < std::string_view{pr.first.data(), ns.length()}; | 
| Jae Hoon Kim | 29a80e0 | 2020-05-11 20:18:49 -0700 | [diff] [blame] | 320 | }; | 
|  | 321 | auto lower_it = | 
|  | 322 | std::lower_bound(begin(values_), end(values_), ns, lower_comp); | 
|  | 323 | auto upper_it = std::upper_bound(lower_it, end(values_), ns, upper_comp); | 
|  | 324 | while (lower_it != upper_it) | 
|  | 325 | keys->push_back((lower_it++)->first); | 
|  | 326 | return true; | 
|  | 327 | } | 
|  | 328 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 329 | bool MemoryPrefs::MemoryStorage::SetKey(std::string_view key, | 
| Kelvin Zhang | cf4600e | 2020-10-27 15:50:33 -0400 | [diff] [blame] | 330 | std::string_view value) { | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 331 | values_[std::string{key}] = value; | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 332 | return true; | 
|  | 333 | } | 
|  | 334 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 335 | bool MemoryPrefs::MemoryStorage::KeyExists(std::string_view key) const { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 336 | return values_.find(key) != values_.end(); | 
|  | 337 | } | 
|  | 338 |  | 
| Kelvin Zhang | 1c86a92 | 2021-05-13 10:30:48 -0400 | [diff] [blame] | 339 | bool MemoryPrefs::MemoryStorage::DeleteKey(std::string_view key) { | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 340 | auto it = values_.find(key); | 
| Andrew | 914f554 | 2020-04-21 10:56:33 -0700 | [diff] [blame] | 341 | if (it != values_.end()) | 
|  | 342 | values_.erase(it); | 
| Alex Deymo | a0284ac | 2016-07-22 12:51:41 -0700 | [diff] [blame] | 343 | return true; | 
|  | 344 | } | 
|  | 345 |  | 
| Darin Petkov | 3003059 | 2010-07-27 13:53:20 -0700 | [diff] [blame] | 346 | }  // namespace chromeos_update_engine |