• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "preferences_helper.h"
17 
18 #include <climits>
19 #include <cstdlib>
20 
21 #include <cerrno>
22 #include <utility>
23 
24 #include "adaptor.h"
25 #include "logger.h"
26 #include "preferences.h"
27 #include "preferences_errno.h"
28 #include "preferences_impl.h"
29 #include "securec.h"
30 
31 namespace OHOS {
32 namespace NativePreferences {
33 std::map<std::string, std::shared_ptr<Preferences>> PreferencesHelper::prefsCache_;
34 std::mutex PreferencesHelper::prefsCacheMutex_;
IsFileExist(const std::string & path)35 static bool IsFileExist(const std::string &path)
36 {
37     FILE *file = std::fopen(path.c_str(), "r");
38     if (file != nullptr) {
39         std::fclose(file);
40         return true;
41     }
42     return false;
43 }
44 
GetRealPath(const std::string & path,int & errorCode)45 std::string PreferencesHelper::GetRealPath(const std::string &path, int &errorCode)
46 {
47     if (path.empty()) {
48         LOG_ERROR("The path can not be empty.");
49         errorCode = E_EMPTY_FILE_PATH;
50         return "";
51     }
52     if (path.front() != '/' && path.at(1) != ':') {
53         LOG_ERROR("The path can not be relative path.");
54         errorCode = E_RELATIVE_PATH;
55         return "";
56     }
57     if (strlen(path.c_str()) > PATH_MAX) {
58         LOG_ERROR("The path exceeds max length.");
59         errorCode = E_PATH_EXCEED_MAX_LENGTH;
60         return "";
61     }
62     std::string::size_type pos = path.find_last_of('/');
63     if (pos == std::string::npos) {
64         LOG_ERROR("path can not be relative path.");
65         errorCode = E_RELATIVE_PATH;
66         return "";
67     }
68     std::string filePath = path.substr(0, pos);
69 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
70     if (ACCESS(filePath.c_str()) != 0 && MKDIR(filePath.c_str())) {
71         LOG_ERROR("Failed to create path");
72         errorCode = E_INVALID_FILE_PATH;
73         return "";
74     }
75 #endif
76     char canonicalPath[PATH_MAX + 1] = { 0 };
77     if (REALPATH(filePath.c_str(), canonicalPath, PATH_MAX) == nullptr) {
78         LOG_ERROR("Failed to obtain real path, errno:%{public}d", errno);
79         errorCode = E_INVALID_FILE_PATH;
80         return "";
81     }
82     std::string fileName = path.substr(pos + 1, path.length());
83     if (fileName.empty()) {
84         LOG_ERROR("file name can not be empty.");
85         errorCode = E_EMPTY_FILE_NAME;
86         return "";
87     }
88     errorCode = E_OK;
89     std::string realFilePath(canonicalPath);
90     return realFilePath.append("/").append(fileName);
91 }
92 
GetPreferences(const std::string & path,int & errCode)93 std::shared_ptr<Preferences> PreferencesHelper::GetPreferences(const std::string &path, int &errCode)
94 {
95     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
96     std::string realPath = GetRealPath(path, errCode);
97     if (realPath == "" || errCode != E_OK) {
98         return nullptr;
99     }
100 
101     std::lock_guard<std::mutex> lock(prefsCacheMutex_);
102     std::map<std::string, std::shared_ptr<Preferences>>::iterator it = prefsCache_.find(realPath);
103     if (it != prefsCache_.end()) {
104         return it->second;
105     }
106 
107     std::string filePath = realPath.c_str();
108     std::shared_ptr<PreferencesImpl> pref = std::make_shared<PreferencesImpl>(filePath);
109     errCode = pref->Init();
110     if (errCode != E_OK) {
111         LOG_ERROR("Preferences Init failed.");
112         return nullptr;
113     }
114     prefsCache_.insert(make_pair(realPath, pref));
115     return pref;
116 }
117 
DeletePreferences(const std::string & path)118 int PreferencesHelper::DeletePreferences(const std::string &path)
119 {
120     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
121     int errCode = E_OK;
122     std::string realPath = GetRealPath(path, errCode);
123     if (realPath == "" || errCode != E_OK) {
124         return errCode;
125     }
126 
127     std::lock_guard<std::mutex> lock(prefsCacheMutex_);
128     std::map<std::string, std::shared_ptr<Preferences>>::iterator it = prefsCache_.find(realPath);
129     if (it != prefsCache_.end()) {
130         prefsCache_.erase(it);
131     }
132 
133     std::string filePath = realPath.c_str();
134     std::string backupPath = PreferencesImpl::MakeBackupPath(filePath);
135     std::string brokenPath = PreferencesImpl::MakeBrokenPath(filePath);
136 
137     std::remove(filePath.c_str());
138     std::remove(backupPath.c_str());
139     std::remove(brokenPath.c_str());
140 
141     if (IsFileExist(filePath) || IsFileExist(backupPath) || IsFileExist(brokenPath)) {
142         return E_DELETE_FILE_FAIL;
143     }
144     return E_OK;
145 }
146 
RemovePreferencesFromCache(const std::string & path)147 int PreferencesHelper::RemovePreferencesFromCache(const std::string &path)
148 {
149     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
150     int errCode = E_OK;
151     std::string realPath = GetRealPath(path, errCode);
152     if (realPath == "" || errCode != E_OK) {
153         return errCode;
154     }
155 
156     std::lock_guard<std::mutex> lock(prefsCacheMutex_);
157     std::map<std::string, std::shared_ptr<Preferences>>::iterator it = prefsCache_.find(realPath);
158     if (it == prefsCache_.end()) {
159         return E_OK;
160     }
161     prefsCache_.erase(it);
162     return E_OK;
163 }
164 } // End of namespace NativePreferences
165 } // End of namespace OHOS
166