• 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 <cerrno>
19 #include <climits>
20 #include <cstdlib>
21 #include <utility>
22 
23 #include "log_print.h"
24 #include "preferences.h"
25 #include "preferences_errno.h"
26 #include "preferences_file_lock.h"
27 #include "preferences_file_operation.h"
28 #include "preferences_impl.h"
29 #include "securec.h"
30 namespace OHOS {
31 namespace NativePreferences {
32 std::map<std::string, std::shared_ptr<Preferences>> PreferencesHelper::prefsCache_;
33 std::mutex PreferencesHelper::prefsCacheMutex_;
IsFileExist(const std::string & path)34 static bool IsFileExist(const std::string &path)
35 {
36     struct stat buffer;
37     return (stat(path.c_str(), &buffer) == 0);
38 }
39 
GetRealPath(const std::string & path,int & errorCode)40 std::string PreferencesHelper::GetRealPath(const std::string &path, int &errorCode)
41 {
42     if (path.empty()) {
43         LOG_ERROR("The path can not be empty.");
44         errorCode = E_EMPTY_FILE_PATH;
45         return "";
46     }
47     if (path.front() != '/') {
48         LOG_ERROR("The path can not be relative path.");
49         errorCode = E_RELATIVE_PATH;
50         return "";
51     }
52     if (path.length() > PATH_MAX) {
53         LOG_ERROR("The path exceeds max length.");
54         errorCode = E_PATH_EXCEED_MAX_LENGTH;
55         return "";
56     }
57     std::string::size_type pos = path.find_last_of('/');
58     if (pos == std::string::npos) {
59         LOG_ERROR("path can not be relative path.");
60         errorCode = E_RELATIVE_PATH;
61         return "";
62     }
63 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
64     if (path.at(1) != ':') {
65         LOG_ERROR("The path can not be relative path.");
66         errorCode = E_RELATIVE_PATH;
67         return "";
68     }
69     std::string filePath = path.substr(0, pos);
70     if (Access(filePath) != 0 && Mkdir(filePath)) {
71         LOG_ERROR("Failed to create path");
72         errorCode = E_INVALID_FILE_PATH;
73         return "";
74     }
75 #endif
76     std::string fileName = path.substr(pos + 1, path.length());
77     if (fileName.empty()) {
78         LOG_ERROR("file name can not be empty.");
79         errorCode = E_EMPTY_FILE_NAME;
80         return "";
81     }
82     errorCode = E_OK;
83     return path;
84 }
85 
GetPreferences(const Options & options,int & errCode)86 std::shared_ptr<Preferences> PreferencesHelper::GetPreferences(const Options &options, int &errCode)
87 {
88     std::string realPath = GetRealPath(options.filePath, errCode);
89     if (realPath == "" || errCode != E_OK) {
90         return nullptr;
91     }
92 
93     std::lock_guard<std::mutex> lock(prefsCacheMutex_);
94     std::map<std::string, std::shared_ptr<Preferences>>::iterator it = prefsCache_.find(realPath);
95     if (it != prefsCache_.end()) {
96         return it->second;
97     }
98 
99     const_cast<Options &>(options).filePath = realPath;
100     std::shared_ptr<PreferencesImpl> pref = PreferencesImpl::GetPreferences(options);
101     errCode = pref->Init();
102     if (errCode != E_OK) {
103         return nullptr;
104     }
105     prefsCache_.insert(make_pair(realPath, pref));
106     return pref;
107 }
108 
DeletePreferences(const std::string & path)109 int PreferencesHelper::DeletePreferences(const std::string &path)
110 {
111     int errCode = E_OK;
112     std::string realPath = GetRealPath(path, errCode);
113     if (realPath == "" || errCode != E_OK) {
114         return errCode;
115     }
116 
117     std::string dataGroupId = "";
118     {
119         std::lock_guard<std::mutex> lock(prefsCacheMutex_);
120         std::map<std::string, std::shared_ptr<Preferences>>::iterator it = prefsCache_.find(realPath);
121         if (it != prefsCache_.end()) {
122             dataGroupId = it->second->GetGroupId();
123             prefsCache_.erase(it);
124         }
125     }
126 
127     std::string filePath = realPath.c_str();
128     std::string backupPath = PreferencesImpl::MakeFilePath(filePath, STR_BACKUP);
129     std::string brokenPath = PreferencesImpl::MakeFilePath(filePath, STR_BROKEN);
130     std::string lockFilePath = PreferencesImpl::MakeFilePath(filePath, STR_LOCK);
131 
132     PreferencesFileLock fileLock(lockFilePath, dataGroupId);
133     std::remove(filePath.c_str());
134     std::remove(backupPath.c_str());
135     std::remove(brokenPath.c_str());
136 
137     if (!dataGroupId.empty()) {
138         std::remove(lockFilePath.c_str());
139     }
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     int errCode = E_OK;
150     std::string realPath = GetRealPath(path, errCode);
151     if (realPath == "" || errCode != E_OK) {
152         return errCode;
153     }
154 
155     std::lock_guard<std::mutex> lock(prefsCacheMutex_);
156     std::map<std::string, std::shared_ptr<Preferences>>::iterator it = prefsCache_.find(realPath);
157     if (it == prefsCache_.end()) {
158         return E_OK;
159     }
160     prefsCache_.erase(it);
161     return E_OK;
162 }
163 } // End of namespace NativePreferences
164 } // End of namespace OHOS
165