1 /*
2 * Copyright (c) 2023 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 "single_ver_utils.h"
17
18 #include "db_common.h"
19 #include "platform_specific.h"
20 #include "runtime_context.h"
21 #include "sqlite_utils.h"
22
23 namespace DistributedDB {
24
GetPathSecurityOption(const std::string & filePath,SecurityOption & secOpt)25 int GetPathSecurityOption(const std::string &filePath, SecurityOption &secOpt)
26 {
27 return RuntimeContext::GetInstance()->GetSecurityOption(filePath, secOpt);
28 }
29
GetDbDir(const std::string & subDir,DbType type)30 std::string GetDbDir(const std::string &subDir, DbType type)
31 {
32 switch (type) {
33 case DbType::MAIN:
34 return subDir + "/" + DBConstant::MAINDB_DIR;
35 case DbType::META:
36 return subDir + "/" + DBConstant::METADB_DIR;
37 case DbType::CACHE:
38 return subDir + "/" + DBConstant::CACHEDB_DIR;
39 default:
40 break;
41 }
42 return "";
43 }
44
GetDatabasePath(const KvDBProperties & kvDBProp)45 std::string GetDatabasePath(const KvDBProperties &kvDBProp)
46 {
47 return GetSubDirPath(kvDBProp) + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE +
48 DBConstant::DB_EXTENSION;
49 }
50
GetSubDirPath(const KvDBProperties & kvDBProp)51 std::string GetSubDirPath(const KvDBProperties &kvDBProp)
52 {
53 std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, "");
54 std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, "");
55 return dataDir + "/" + identifierDir + "/" + DBConstant::SINGLE_SUB_DIR;
56 }
57
ClearIncompleteDatabase(const KvDBProperties & kvDBPro)58 int ClearIncompleteDatabase(const KvDBProperties &kvDBPro)
59 {
60 std::string dbSubDir = GetSubDirPath(kvDBPro);
61 if (OS::CheckPathExistence(dbSubDir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE)) {
62 int errCode = DBCommon::RemoveAllFilesOfDirectory(dbSubDir);
63 if (errCode != E_OK) {
64 LOGE("Remove the incomplete database dir failed!");
65 return -E_REMOVE_FILE;
66 }
67 }
68 return E_OK;
69 }
70
CreateNewDirsAndSetSecOption(const OpenDbProperties & option)71 int CreateNewDirsAndSetSecOption(const OpenDbProperties &option)
72 {
73 std::vector<std::string> dbDir { DBConstant::MAINDB_DIR, DBConstant::METADB_DIR, DBConstant::CACHEDB_DIR };
74 for (const auto &item : dbDir) {
75 if (OS::CheckPathExistence(option.subdir + "/" + item)) {
76 continue;
77 }
78
79 // Dir and old db file not existed, it means that the database is newly created
80 // need create flag of database not incomplete
81 if (!OS::CheckPathExistence(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) &&
82 !OS::CheckPathExistence(option.subdir + "/" + DBConstant::SINGLE_VER_DATA_STORE +
83 DBConstant::DB_EXTENSION) &&
84 OS::CreateFileByFileName(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) {
85 LOGE("Fail to create the token of database incompleted! errCode = [E_SYSTEM_API_FAIL]");
86 return -E_SYSTEM_API_FAIL;
87 }
88
89 if (DBCommon::CreateDirectory(option.subdir + "/" + item) != E_OK) {
90 LOGE("Create sub-directory for single ver failed, errno:%d", errno);
91 return -E_SYSTEM_API_FAIL;
92 }
93
94 if (option.securityOpt.securityLabel == NOT_SET) {
95 continue;
96 }
97
98 SecurityOption secOption = option.securityOpt;
99 if (item == DBConstant::METADB_DIR) {
100 secOption.securityLabel = ((option.securityOpt.securityLabel >= SecurityLabel::S2) ?
101 SecurityLabel::S2 : option.securityOpt.securityLabel);
102 secOption.securityFlag = SecurityFlag::ECE;
103 }
104
105 int errCode = RuntimeContext::GetInstance()->SetSecurityOption(option.subdir + "/" + item, secOption);
106 if (errCode != E_OK && errCode != -E_NOT_SUPPORT) {
107 LOGE("Set the security option of sub-directory failed[%d]", errCode);
108 return errCode;
109 }
110 }
111 return E_OK;
112 }
113
GetExistedSecOpt(const OpenDbProperties & opt,SecurityOption & secOption)114 int GetExistedSecOpt(const OpenDbProperties &opt, SecurityOption &secOption)
115 {
116 // Check the existence of the database, include the origin database and the database in the 'main' directory.
117 auto mainDbDir = GetDbDir(opt.subdir, DbType::MAIN);
118 auto mainDbFilePath = mainDbDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION;
119 auto origDbFilePath = opt.subdir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION;
120 if (!OS::CheckPathExistence(origDbFilePath) && !OS::CheckPathExistence(mainDbFilePath)) {
121 secOption = opt.securityOpt;
122 return E_OK;
123 }
124
125 // the main database file has high priority of the security option.
126 int errCode;
127 if (OS::CheckPathExistence(mainDbFilePath)) {
128 errCode = GetPathSecurityOption(mainDbFilePath, secOption);
129 } else {
130 errCode = GetPathSecurityOption(origDbFilePath, secOption);
131 }
132 if (errCode == E_OK) {
133 return E_OK;
134 }
135 secOption = SecurityOption();
136 if (errCode == -E_NOT_SUPPORT) {
137 return E_OK;
138 }
139 LOGE("Get the security option of the existed database failed.");
140 return errCode;
141 }
142
InitCommitNotifyDataKeyStatus(SingleVerNaturalStoreCommitNotifyData * committedData,const Key & hashKey,const DataOperStatus & dataStatus)143 void InitCommitNotifyDataKeyStatus(SingleVerNaturalStoreCommitNotifyData *committedData, const Key &hashKey,
144 const DataOperStatus &dataStatus)
145 {
146 if (committedData == nullptr) {
147 return;
148 }
149
150 ExistStatus existedStatus = ExistStatus::NONE;
151 if (dataStatus.preStatus == DataStatus::DELETED) {
152 existedStatus = ExistStatus::DELETED;
153 } else if (dataStatus.preStatus == DataStatus::EXISTED) {
154 existedStatus = ExistStatus::EXIST;
155 }
156
157 committedData->InitKeyPropRecord(hashKey, existedStatus);
158 }
159
CheckStoreStatus(const OpenDbProperties & opt)160 int CheckStoreStatus(const OpenDbProperties &opt)
161 {
162 // Check the existence of the database, include the origin database and the database in the 'main' directory.
163 auto mainDbDir = GetDbDir(opt.subdir, DbType::MAIN);
164 auto mainDbFilePath = mainDbDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION;
165 auto origDbFilePath = opt.subdir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION;
166 if (!OS::CheckPathExistence(origDbFilePath) && !OS::CheckPathExistence(mainDbFilePath)) {
167 return E_OK;
168 }
169 sqlite3 *db = nullptr;
170 OpenDbProperties checkOpt = opt;
171 if (OS::CheckPathExistence(mainDbFilePath)) {
172 checkOpt.uri = mainDbFilePath;
173 } else {
174 checkOpt.uri = origDbFilePath;
175 }
176 int errCode = SQLiteUtils::OpenDatabase(checkOpt, db);
177 if (db != nullptr) {
178 int ret = sqlite3_close_v2(db);
179 if (ret != E_OK) {
180 LOGW("close db failed %d when check db status", ret);
181 }
182 }
183 if (errCode != E_OK && errCode != -E_EKEYREVOKED) {
184 LOGE("check db status failed %d", errCode);
185 } else {
186 errCode = E_OK;
187 }
188 return errCode;
189 }
190 } // namespace DistributedDB