1fc223305Sopenharmony_ci/* 2fc223305Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3fc223305Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fc223305Sopenharmony_ci * you may not use this file except in compliance with the License. 5fc223305Sopenharmony_ci * You may obtain a copy of the License at 6fc223305Sopenharmony_ci * 7fc223305Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fc223305Sopenharmony_ci * 9fc223305Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fc223305Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fc223305Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fc223305Sopenharmony_ci * See the License for the specific language governing permissions and 13fc223305Sopenharmony_ci * limitations under the License. 14fc223305Sopenharmony_ci */ 15fc223305Sopenharmony_ci 16fc223305Sopenharmony_ci#include "preferences_helper.h" 17fc223305Sopenharmony_ci 18fc223305Sopenharmony_ci#include <cerrno> 19fc223305Sopenharmony_ci#include <climits> 20fc223305Sopenharmony_ci#include <cstdlib> 21fc223305Sopenharmony_ci#include <utility> 22fc223305Sopenharmony_ci 23fc223305Sopenharmony_ci#include "log_print.h" 24fc223305Sopenharmony_ci#include "preferences.h" 25fc223305Sopenharmony_ci#include "preferences_db_adapter.h" 26fc223305Sopenharmony_ci#include "preferences_errno.h" 27fc223305Sopenharmony_ci#include "preferences_file_lock.h" 28fc223305Sopenharmony_ci#include "preferences_file_operation.h" 29fc223305Sopenharmony_ci#include "preferences_dfx_adapter.h" 30fc223305Sopenharmony_ci#include "preferences_impl.h" 31fc223305Sopenharmony_ci#include "preferences_enhance_impl.h" 32fc223305Sopenharmony_cinamespace OHOS { 33fc223305Sopenharmony_cinamespace NativePreferences { 34fc223305Sopenharmony_cistd::map<std::string, std::pair<std::shared_ptr<Preferences>, bool>> PreferencesHelper::prefsCache_; 35fc223305Sopenharmony_cistd::mutex PreferencesHelper::prefsCacheMutex_; 36fc223305Sopenharmony_cistatic constexpr const int DB_SUFFIX_NUM = 6; 37fc223305Sopenharmony_cistatic constexpr const char *DB_SUFFIX[DB_SUFFIX_NUM] = { ".ctrl", ".ctrl.dwr", ".redo", ".undo", ".safe", ".map" }; 38fc223305Sopenharmony_ci 39fc223305Sopenharmony_cistatic bool IsFileExist(const std::string &path) 40fc223305Sopenharmony_ci{ 41fc223305Sopenharmony_ci struct stat buffer; 42fc223305Sopenharmony_ci return (stat(path.c_str(), &buffer) == 0); 43fc223305Sopenharmony_ci} 44fc223305Sopenharmony_ci 45fc223305Sopenharmony_cistatic int RemoveEnhanceDb(const std::string &filePath) 46fc223305Sopenharmony_ci{ 47fc223305Sopenharmony_ci if (std::remove(filePath.c_str()) != 0) { 48fc223305Sopenharmony_ci LOG_ERROR("remove %{public}s failed.", ExtractFileName(filePath).c_str()); 49fc223305Sopenharmony_ci return E_DELETE_FILE_FAIL; 50fc223305Sopenharmony_ci } 51fc223305Sopenharmony_ci return E_OK; 52fc223305Sopenharmony_ci} 53fc223305Sopenharmony_ci 54fc223305Sopenharmony_cistatic int RemoveEnhanceDbFileIfNeed(const std::string &filePath) 55fc223305Sopenharmony_ci{ 56fc223305Sopenharmony_ci std::string dbFilePath = filePath + ".db"; 57fc223305Sopenharmony_ci if (IsFileExist(dbFilePath) && RemoveEnhanceDb(dbFilePath) != E_OK) { 58fc223305Sopenharmony_ci LOG_ERROR("remove dbFilePath failed."); 59fc223305Sopenharmony_ci return E_DELETE_FILE_FAIL; 60fc223305Sopenharmony_ci } 61fc223305Sopenharmony_ci for (int index = 0; index < DB_SUFFIX_NUM; index++) { 62fc223305Sopenharmony_ci std::string tmpFilePath = dbFilePath + DB_SUFFIX[index]; 63fc223305Sopenharmony_ci if (IsFileExist(tmpFilePath) && RemoveEnhanceDb(tmpFilePath) != E_OK) { 64fc223305Sopenharmony_ci return E_DELETE_FILE_FAIL; 65fc223305Sopenharmony_ci } 66fc223305Sopenharmony_ci } 67fc223305Sopenharmony_ci LOG_DEBUG("db files has been removed."); 68fc223305Sopenharmony_ci return E_OK; 69fc223305Sopenharmony_ci} 70fc223305Sopenharmony_ci 71fc223305Sopenharmony_cistd::string PreferencesHelper::GetRealPath(const std::string &path, int &errorCode) 72fc223305Sopenharmony_ci{ 73fc223305Sopenharmony_ci if (path.empty()) { 74fc223305Sopenharmony_ci LOG_ERROR("The path can not be empty."); 75fc223305Sopenharmony_ci errorCode = E_EMPTY_FILE_PATH; 76fc223305Sopenharmony_ci return ""; 77fc223305Sopenharmony_ci } 78fc223305Sopenharmony_ci if (path.length() > PATH_MAX) { 79fc223305Sopenharmony_ci LOG_ERROR("The path exceeds max length."); 80fc223305Sopenharmony_ci errorCode = E_PATH_EXCEED_MAX_LENGTH; 81fc223305Sopenharmony_ci return ""; 82fc223305Sopenharmony_ci } 83fc223305Sopenharmony_ci std::string::size_type pos = path.find_last_of('/'); 84fc223305Sopenharmony_ci if (pos == std::string::npos) { 85fc223305Sopenharmony_ci LOG_ERROR("path can not be relative path."); 86fc223305Sopenharmony_ci errorCode = E_RELATIVE_PATH; 87fc223305Sopenharmony_ci return ""; 88fc223305Sopenharmony_ci } 89fc223305Sopenharmony_ci#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) 90fc223305Sopenharmony_ci if (path.at(1) != ':') { 91fc223305Sopenharmony_ci LOG_ERROR("The path can not be relative path."); 92fc223305Sopenharmony_ci errorCode = E_RELATIVE_PATH; 93fc223305Sopenharmony_ci return ""; 94fc223305Sopenharmony_ci } 95fc223305Sopenharmony_ci std::string filePath = path.substr(0, pos); 96fc223305Sopenharmony_ci if (Access(filePath) != 0 && !Mkdir(filePath)) { 97fc223305Sopenharmony_ci LOG_ERROR("Failed to create path"); 98fc223305Sopenharmony_ci errorCode = E_INVALID_FILE_PATH; 99fc223305Sopenharmony_ci return ""; 100fc223305Sopenharmony_ci } 101fc223305Sopenharmony_ci#else 102fc223305Sopenharmony_ci if (path.front() != '/') { 103fc223305Sopenharmony_ci LOG_ERROR("The path can not be relative path."); 104fc223305Sopenharmony_ci errorCode = E_RELATIVE_PATH; 105fc223305Sopenharmony_ci return ""; 106fc223305Sopenharmony_ci } 107fc223305Sopenharmony_ci#endif 108fc223305Sopenharmony_ci std::string fileName = path.substr(pos + 1, path.length()); 109fc223305Sopenharmony_ci if (fileName.empty()) { 110fc223305Sopenharmony_ci LOG_ERROR("file name can not be empty."); 111fc223305Sopenharmony_ci errorCode = E_EMPTY_FILE_NAME; 112fc223305Sopenharmony_ci return ""; 113fc223305Sopenharmony_ci } 114fc223305Sopenharmony_ci errorCode = E_OK; 115fc223305Sopenharmony_ci return path; 116fc223305Sopenharmony_ci} 117fc223305Sopenharmony_ci 118fc223305Sopenharmony_ci#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) 119fc223305Sopenharmony_cistatic bool IsUseEnhanceDb(const Options &options) 120fc223305Sopenharmony_ci{ 121fc223305Sopenharmony_ci if (IsFileExist(options.filePath)) { 122fc223305Sopenharmony_ci return false; 123fc223305Sopenharmony_ci } 124fc223305Sopenharmony_ci bool bundleCheck = (options.bundleName.find("uttest") != std::string::npos || 125fc223305Sopenharmony_ci options.bundleName.find("alipay") != std::string::npos || 126fc223305Sopenharmony_ci options.bundleName.find("com.jd.") != std::string::npos || 127fc223305Sopenharmony_ci options.bundleName.find("cmblife") != std::string::npos || 128fc223305Sopenharmony_ci options.bundleName.find("os.mms") != std::string::npos || 129fc223305Sopenharmony_ci options.bundleName.find("os.ouc") != std::string::npos || 130fc223305Sopenharmony_ci options.bundleName.find("meetimeservice") != std::string::npos); 131fc223305Sopenharmony_ci if (!options.isEnhance && !bundleCheck) { 132fc223305Sopenharmony_ci return false; 133fc223305Sopenharmony_ci } 134fc223305Sopenharmony_ci PreferenceDbAdapter::ApiInit(); 135fc223305Sopenharmony_ci return PreferenceDbAdapter::IsEnhandceDbEnable(); 136fc223305Sopenharmony_ci} 137fc223305Sopenharmony_ci#endif 138fc223305Sopenharmony_ci 139fc223305Sopenharmony_cistd::shared_ptr<Preferences> PreferencesHelper::GetPreferences(const Options &options, int &errCode) 140fc223305Sopenharmony_ci{ 141fc223305Sopenharmony_ci std::string realPath = GetRealPath(options.filePath, errCode); 142fc223305Sopenharmony_ci if (realPath == "" || errCode != E_OK) { 143fc223305Sopenharmony_ci return nullptr; 144fc223305Sopenharmony_ci } 145fc223305Sopenharmony_ci 146fc223305Sopenharmony_ci std::lock_guard<std::mutex> lock(prefsCacheMutex_); 147fc223305Sopenharmony_ci auto it = prefsCache_.find(realPath); 148fc223305Sopenharmony_ci if (it != prefsCache_.end()) { 149fc223305Sopenharmony_ci auto pre = it->second.first; 150fc223305Sopenharmony_ci if (pre != nullptr) { 151fc223305Sopenharmony_ci LOG_DEBUG("GetPreferences: found preferences in cache"); 152fc223305Sopenharmony_ci return pre; 153fc223305Sopenharmony_ci } 154fc223305Sopenharmony_ci LOG_DEBUG("GetPreferences: found preferences in cache but it's null, erase it."); 155fc223305Sopenharmony_ci prefsCache_.erase(it); 156fc223305Sopenharmony_ci } 157fc223305Sopenharmony_ci 158fc223305Sopenharmony_ci const_cast<Options &>(options).filePath = realPath; 159fc223305Sopenharmony_ci std::string::size_type pos = realPath.find_last_of('/'); 160fc223305Sopenharmony_ci std::string filePath = realPath.substr(0, pos); 161fc223305Sopenharmony_ci if (access(filePath.c_str(), F_OK) != 0) { 162fc223305Sopenharmony_ci LOG_ERROR("The path is invalid, prefName is %{public}s.", ExtractFileName(realPath).c_str()); 163fc223305Sopenharmony_ci errCode = E_INVALID_FILE_PATH; 164fc223305Sopenharmony_ci return nullptr; 165fc223305Sopenharmony_ci } 166fc223305Sopenharmony_ci std::shared_ptr<Preferences> pref = nullptr; 167fc223305Sopenharmony_ci bool isEnhancePreferences = false; 168fc223305Sopenharmony_ci#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) &&!defined(IOS_PLATFORM) 169fc223305Sopenharmony_ci if (IsUseEnhanceDb(options)) { 170fc223305Sopenharmony_ci LOG_DEBUG("PreferencesHelper::GetPreferences using enhance db."); 171fc223305Sopenharmony_ci pref = PreferencesEnhanceImpl::GetPreferences(options); 172fc223305Sopenharmony_ci errCode = std::static_pointer_cast<PreferencesEnhanceImpl>(pref)->Init(); 173fc223305Sopenharmony_ci isEnhancePreferences = true; 174fc223305Sopenharmony_ci } else { 175fc223305Sopenharmony_ci pref = PreferencesImpl::GetPreferences(options); 176fc223305Sopenharmony_ci errCode = std::static_pointer_cast<PreferencesImpl>(pref)->Init(); 177fc223305Sopenharmony_ci } 178fc223305Sopenharmony_ci#else 179fc223305Sopenharmony_ci pref = PreferencesImpl::GetPreferences(options); 180fc223305Sopenharmony_ci errCode = std::static_pointer_cast<PreferencesImpl>(pref)->Init(); 181fc223305Sopenharmony_ci#endif 182fc223305Sopenharmony_ci if (errCode != E_OK) { 183fc223305Sopenharmony_ci return nullptr; 184fc223305Sopenharmony_ci } 185fc223305Sopenharmony_ci prefsCache_.insert({realPath, {pref, isEnhancePreferences}}); 186fc223305Sopenharmony_ci return pref; 187fc223305Sopenharmony_ci} 188fc223305Sopenharmony_ci 189fc223305Sopenharmony_ciint PreferencesHelper::DeletePreferences(const std::string &path) 190fc223305Sopenharmony_ci{ 191fc223305Sopenharmony_ci int errCode = E_OK; 192fc223305Sopenharmony_ci std::string realPath = GetRealPath(path, errCode); 193fc223305Sopenharmony_ci if (realPath == "" || errCode != E_OK) { 194fc223305Sopenharmony_ci return errCode; 195fc223305Sopenharmony_ci } 196fc223305Sopenharmony_ci 197fc223305Sopenharmony_ci std::string dataGroupId = ""; 198fc223305Sopenharmony_ci { 199fc223305Sopenharmony_ci std::lock_guard<std::mutex> lock(prefsCacheMutex_); 200fc223305Sopenharmony_ci std::map<std::string, std::pair<std::shared_ptr<Preferences>, bool>>::iterator it = prefsCache_.find(realPath); 201fc223305Sopenharmony_ci if (it != prefsCache_.end()) { 202fc223305Sopenharmony_ci auto pref = it->second.first; 203fc223305Sopenharmony_ci if (pref != nullptr) { 204fc223305Sopenharmony_ci LOG_INFO("Begin to Delete Preferences: %{public}s", ExtractFileName(path).c_str()); 205fc223305Sopenharmony_ci dataGroupId = pref->GetGroupId(); 206fc223305Sopenharmony_ci errCode = pref->CloseDb(); 207fc223305Sopenharmony_ci if (errCode != E_OK) { 208fc223305Sopenharmony_ci LOG_ERROR("failed to close db when delete preferences."); 209fc223305Sopenharmony_ci return errCode; 210fc223305Sopenharmony_ci } 211fc223305Sopenharmony_ci } 212fc223305Sopenharmony_ci pref = nullptr; 213fc223305Sopenharmony_ci prefsCache_.erase(it); 214fc223305Sopenharmony_ci LOG_DEBUG("DeletePreferences: found preferences in cache, erase it."); 215fc223305Sopenharmony_ci } else { 216fc223305Sopenharmony_ci LOG_DEBUG("DeletePreferences: cache not found, just delete files."); 217fc223305Sopenharmony_ci } 218fc223305Sopenharmony_ci } 219fc223305Sopenharmony_ci 220fc223305Sopenharmony_ci std::string filePath = realPath.c_str(); 221fc223305Sopenharmony_ci std::string backupPath = MakeFilePath(filePath, STR_BACKUP); 222fc223305Sopenharmony_ci std::string brokenPath = MakeFilePath(filePath, STR_BROKEN); 223fc223305Sopenharmony_ci std::string lockFilePath = MakeFilePath(filePath, STR_LOCK); 224fc223305Sopenharmony_ci 225fc223305Sopenharmony_ci PreferencesFileLock fileLock(lockFilePath, dataGroupId); 226fc223305Sopenharmony_ci std::remove(filePath.c_str()); 227fc223305Sopenharmony_ci std::remove(backupPath.c_str()); 228fc223305Sopenharmony_ci std::remove(brokenPath.c_str()); 229fc223305Sopenharmony_ci if (RemoveEnhanceDbFileIfNeed(path) != E_OK) { 230fc223305Sopenharmony_ci return E_DELETE_FILE_FAIL; 231fc223305Sopenharmony_ci } 232fc223305Sopenharmony_ci 233fc223305Sopenharmony_ci if (!dataGroupId.empty()) { 234fc223305Sopenharmony_ci std::remove(lockFilePath.c_str()); 235fc223305Sopenharmony_ci } 236fc223305Sopenharmony_ci 237fc223305Sopenharmony_ci if (IsFileExist(filePath) || IsFileExist(backupPath) || IsFileExist(brokenPath)) { 238fc223305Sopenharmony_ci return E_DELETE_FILE_FAIL; 239fc223305Sopenharmony_ci } 240fc223305Sopenharmony_ci return E_OK; 241fc223305Sopenharmony_ci} 242fc223305Sopenharmony_ci 243fc223305Sopenharmony_ciint PreferencesHelper::RemovePreferencesFromCache(const std::string &path) 244fc223305Sopenharmony_ci{ 245fc223305Sopenharmony_ci int errCode = E_OK; 246fc223305Sopenharmony_ci std::string realPath = GetRealPath(path, errCode); 247fc223305Sopenharmony_ci if (realPath == "" || errCode != E_OK) { 248fc223305Sopenharmony_ci return errCode; 249fc223305Sopenharmony_ci } 250fc223305Sopenharmony_ci 251fc223305Sopenharmony_ci std::lock_guard<std::mutex> lock(prefsCacheMutex_); 252fc223305Sopenharmony_ci std::map<std::string, std::pair<std::shared_ptr<Preferences>, bool>>::iterator it = prefsCache_.find(realPath); 253fc223305Sopenharmony_ci if (it == prefsCache_.end()) { 254fc223305Sopenharmony_ci LOG_DEBUG("RemovePreferencesFromCache: preferences not in cache, just return"); 255fc223305Sopenharmony_ci return E_OK; 256fc223305Sopenharmony_ci } 257fc223305Sopenharmony_ci 258fc223305Sopenharmony_ci if (it->second.second) { 259fc223305Sopenharmony_ci auto pref = it->second.first; 260fc223305Sopenharmony_ci errCode = std::static_pointer_cast<PreferencesEnhanceImpl>(pref)->CloseDb(); 261fc223305Sopenharmony_ci if (errCode != E_OK) { 262fc223305Sopenharmony_ci LOG_ERROR("RemovePreferencesFromCache: failed to close db."); 263fc223305Sopenharmony_ci return E_ERROR; 264fc223305Sopenharmony_ci } 265fc223305Sopenharmony_ci } 266fc223305Sopenharmony_ci 267fc223305Sopenharmony_ci prefsCache_.erase(it); 268fc223305Sopenharmony_ci return E_OK; 269fc223305Sopenharmony_ci} 270fc223305Sopenharmony_ci} // End of namespace NativePreferences 271fc223305Sopenharmony_ci} // End of namespace OHOS