| 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 |