1 /*
2 * Copyright (c) 2021-2022 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 "sqlite_helper.h"
17
18 #include "accesstoken_common_log.h"
19 #include "sqlite3ext.h"
20 #include <sys/types.h>
21
22 namespace OHOS {
23 namespace Security {
24 namespace AccessToken {
25
SqliteHelper(const std::string & dbName,const std::string & dbPath,int32_t version)26 SqliteHelper::SqliteHelper(const std::string& dbName, const std::string& dbPath, int32_t version)
27 : dbName_(dbName), dbPath_(dbPath), currentVersion_(version), db_(nullptr)
28 {}
29
~SqliteHelper()30 SqliteHelper::~SqliteHelper()
31 {}
32
Open()33 void SqliteHelper::Open() __attribute__((no_sanitize("cfi")))
34 {
35 if (db_ != nullptr) {
36 LOGW(ATM_DOMAIN, ATM_TAG, "Db s already open");
37 return;
38 }
39 if (dbName_.empty() || dbPath_.empty() || currentVersion_ < 0) {
40 LOGE(ATM_DOMAIN, ATM_TAG, "Param invalid, dbName: %{public}s, dbPath: %{public}s, currentVersion: %{public}d",
41 dbName_.c_str(), dbPath_.c_str(), currentVersion_);
42 return;
43 }
44 // set soft heap limit as 10KB
45 const int32_t heapLimit = 10 * 1024;
46 sqlite3_soft_heap_limit64(heapLimit);
47 std::string fileName = dbPath_ + dbName_;
48 int32_t res = sqlite3_open(fileName.c_str(), &db_);
49 if (res != SQLITE_OK) {
50 LOGE(ATM_DOMAIN, ATM_TAG, "Failed to open db: %{public}s", sqlite3_errmsg(db_));
51 return;
52 }
53
54 SetWal();
55
56 int32_t version = GetVersion();
57 if (version == currentVersion_) {
58 return;
59 }
60
61 BeginTransaction();
62 if (version == DataBaseVersion::VERISION_0) {
63 OnCreate();
64 } else {
65 if (version < currentVersion_) {
66 OnUpdate(version);
67 }
68 }
69 SetVersion();
70 CommitTransaction();
71 }
72
Close()73 void SqliteHelper::Close()
74 {
75 if (db_ == nullptr) {
76 LOGW(ATM_DOMAIN, ATM_TAG, "Do open data base first!");
77 return;
78 }
79 int32_t ret = sqlite3_close(db_);
80 if (ret != SQLITE_OK) {
81 LOGW(ATM_DOMAIN, ATM_TAG, "Sqlite3_close error, ret=%{public}d", ret);
82 return;
83 }
84 db_ = nullptr;
85 }
86
BeginTransaction() const87 int32_t SqliteHelper::BeginTransaction() const
88 {
89 if (db_ == nullptr) {
90 LOGW(ATM_DOMAIN, ATM_TAG, "Do open data base first!");
91 return GENERAL_ERROR;
92 }
93 char* errorMessage = nullptr;
94 int32_t result = 0;
95 int32_t ret = sqlite3_exec(db_, "BEGIN;", nullptr, nullptr, &errorMessage);
96 if (ret != SQLITE_OK) {
97 LOGE(ATM_DOMAIN, ATM_TAG, "Failed, errorMsg: %{public}s", errorMessage);
98 result = GENERAL_ERROR;
99 }
100 sqlite3_free(errorMessage);
101 return result;
102 }
103
CommitTransaction() const104 int32_t SqliteHelper::CommitTransaction() const
105 {
106 if (db_ == nullptr) {
107 LOGW(ATM_DOMAIN, ATM_TAG, "Do open data base first!");
108 return GENERAL_ERROR;
109 }
110 char* errorMessage = nullptr;
111 int32_t result = 0;
112 int32_t ret = sqlite3_exec(db_, "COMMIT;", nullptr, nullptr, &errorMessage);
113 if (ret != SQLITE_OK) {
114 LOGE(ATM_DOMAIN, ATM_TAG, "Failed, errorMsg: %{public}s", errorMessage);
115 result = GENERAL_ERROR;
116 }
117 sqlite3_free(errorMessage);
118 sqlite3_db_cacheflush(db_);
119 return result;
120 }
121
RollbackTransaction() const122 int32_t SqliteHelper::RollbackTransaction() const
123 {
124 if (db_ == nullptr) {
125 LOGW(ATM_DOMAIN, ATM_TAG, "Do open data base first!");
126 return GENERAL_ERROR;
127 }
128 int32_t result = 0;
129 char* errorMessage = nullptr;
130 int32_t ret = sqlite3_exec(db_, "ROLLBACK;", nullptr, nullptr, &errorMessage);
131 if (ret != SQLITE_OK) {
132 LOGE(ATM_DOMAIN, ATM_TAG, "Failed, errorMsg: %{public}s", errorMessage);
133 result = GENERAL_ERROR;
134 }
135 sqlite3_free(errorMessage);
136 return result;
137 }
138
Prepare(const std::string & sql) const139 Statement SqliteHelper::Prepare(const std::string& sql) const
140 {
141 return Statement(db_, sql);
142 }
143
ExecuteSql(const std::string & sql) const144 int32_t SqliteHelper::ExecuteSql(const std::string& sql) const
145 {
146 if (db_ == nullptr) {
147 LOGW(ATM_DOMAIN, ATM_TAG, "Do open data base first!");
148 return GENERAL_ERROR;
149 }
150 char* errorMessage = nullptr;
151 int32_t result = 0;
152 int32_t res = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &errorMessage);
153 if (res != SQLITE_OK) {
154 LOGE(ATM_DOMAIN, ATM_TAG, "Failed, errorMsg: %{public}s", errorMessage);
155 result = GENERAL_ERROR;
156 }
157 sqlite3_free(errorMessage);
158 return result;
159 }
160
SetWal() const161 void SqliteHelper::SetWal() const
162 {
163 if (db_ == nullptr) {
164 LOGW(ATM_DOMAIN, ATM_TAG, "Do open data base first!");
165 return;
166 }
167 auto statement = Prepare(PRAGMA_WAL_COMMAND);
168 if (statement.Step() != Statement::State::DONE) {
169 LOGE(ATM_DOMAIN, ATM_TAG, "Set wal mode failed, errorMsg: %{public}s", SpitError().c_str());
170 } else {
171 LOGI(ATM_DOMAIN, ATM_TAG, "Set wal mode success!");
172 }
173 }
174
GetVersion() const175 int32_t SqliteHelper::GetVersion() const __attribute__((no_sanitize("cfi")))
176 {
177 if (db_ == nullptr) {
178 LOGW(ATM_DOMAIN, ATM_TAG, "Do open data base first!");
179 return GENERAL_ERROR;
180 }
181 auto statement = Prepare(PRAGMA_VERSION_COMMAND);
182 int32_t version = 0;
183 while (statement.Step() == Statement::State::ROW) {
184 version = statement.GetColumnInt(0);
185 }
186 LOGI(ATM_DOMAIN, ATM_TAG, "Version: %{public}d", version);
187 return version;
188 }
189
SetVersion() const190 void SqliteHelper::SetVersion() const
191 {
192 if (db_ == nullptr) {
193 LOGW(ATM_DOMAIN, ATM_TAG, "Do open data base first!");
194 return;
195 }
196 auto statement = Prepare(PRAGMA_VERSION_COMMAND + " = " + std::to_string(currentVersion_));
197 statement.Step();
198 }
199
SpitError() const200 std::string SqliteHelper::SpitError() const
201 {
202 if (db_ == nullptr) {
203 LOGW(ATM_DOMAIN, ATM_TAG, "Do open data base first!");
204 return "";
205 }
206 return sqlite3_errmsg(db_);
207 }
208 } // namespace AccessToken
209 } // namespace Security
210 } // namespace OHOS
211