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