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 "sqlite_database_utils.h"
17
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21
22 #include <algorithm>
23 #include <cstdio>
24 #include <fstream>
25
26 #include "logger.h"
27 #include "rdb_errno.h"
28
29 namespace OHOS {
30 namespace NativeRdb {
31 std::map<std::string, int> SqliteDatabaseUtils::g_statementType = SqliteDatabaseUtils::MapInit();
32 std::mutex SqliteDatabaseUtils::g_locker;
33 // Set the file access permissions is 777
34 int SqliteDatabaseUtils::g_mkdirMode = 0771;
MapInit()35 std::map<std::string, int> SqliteDatabaseUtils::MapInit()
36 {
37 std::map<std::string, int> temp;
38 temp["SEL"] = STATEMENT_SELECT;
39 temp["INS"] = STATEMENT_UPDATE;
40 temp["UPD"] = STATEMENT_UPDATE;
41 temp["REP"] = STATEMENT_UPDATE;
42 temp["DEL"] = STATEMENT_UPDATE;
43 temp["ATT"] = STATEMENT_ATTACH;
44 temp["DET"] = STATEMENT_DETACH;
45 temp["COM"] = STATEMENT_COMMIT;
46 temp["END"] = STATEMENT_COMMIT;
47 temp["ROL"] = STATEMENT_ROLLBACK;
48 temp["BEG"] = STATEMENT_BEGIN;
49 temp["PRA"] = STATEMENT_PRAGMA;
50 temp["CRE"] = STATEMENT_DDL;
51 temp["DRO"] = STATEMENT_DDL;
52 temp["ALT"] = STATEMENT_DDL;
53
54 return temp;
55 }
56
57 /**
58 * Obtains the type of SQL statement.
59 */
GetSqlStatementType(std::string sql)60 int SqliteDatabaseUtils::GetSqlStatementType(std::string sql)
61 {
62 if (sql.empty()) {
63 return STATEMENT_OTHER;
64 }
65 sql.erase(0, sql.find_first_not_of(" "));
66 sql.erase(sql.find_last_not_of(" ") + 1);
67
68 if (sql.length() < SQL_FIRST_CHARACTER) {
69 return STATEMENT_OTHER;
70 }
71 sql = sql.substr(0, SQL_FIRST_CHARACTER);
72 std::string prefixSql;
73 transform(sql.begin(), sql.end(), prefixSql.begin(), ::toupper);
74 prefixSql = prefixSql.c_str();
75 auto iter = g_statementType.find(prefixSql);
76 if (iter != g_statementType.end()) {
77 return iter->second;
78 }
79 return STATEMENT_OTHER;
80 }
81
82 /**
83 * Delete the specified file.
84 */
DeleteFile(std::string & fileName)85 void SqliteDatabaseUtils::DeleteFile(std::string &fileName)
86 {
87 if (access(fileName.c_str(), F_OK) != 0) {
88 LOG_ERROR("File %{private}s does not exist", fileName.c_str());
89 return;
90 }
91 if (!remove(fileName.c_str())) {
92 LOG_ERROR("FileName= %{private}s has been deleted", fileName.c_str());
93 return;
94 }
95 LOG_INFO("Failed to delete File %{private}s", fileName.c_str());
96 }
97
98 /**
99 * Rename file.
100 */
RenameFile(std::string & oldFileName,std::string & newFileName)101 bool SqliteDatabaseUtils::RenameFile(std::string &oldFileName, std::string &newFileName)
102 {
103 if (access(oldFileName.c_str(), F_OK) != 0) {
104 LOG_ERROR("File %{private}s does not exist", oldFileName.c_str());
105 return false;
106 }
107 if (rename(oldFileName.c_str(), newFileName.c_str())) {
108 LOG_ERROR("Rename oldFileName = %{private}s to newFileName %{private}s", oldFileName.c_str(),
109 newFileName.c_str());
110 return true;
111 }
112 return false;
113 }
114
115 /**
116 * Get and Check default path.
117 */
GetDefaultDatabasePath(std::string & context,std::string & name,int & errorCode)118 std::string SqliteDatabaseUtils::GetDefaultDatabasePath(std::string &context, std::string &name, int &errorCode)
119 {
120 std::unique_lock<std::mutex> lock(g_locker);
121 if (access(context.c_str(), F_OK) != 0) {
122 if (mkdir(context.c_str(), g_mkdirMode)) {
123 errorCode = E_CREATE_FOLDER_FAIL;
124 }
125 }
126 std::string databasePath = context + "/db";
127 if (access(databasePath.c_str(), F_OK) != 0) {
128 if (mkdir(databasePath.c_str(), g_mkdirMode)) {
129 errorCode = E_CREATE_FOLDER_FAIL;
130 }
131 }
132 char canonicalPath[PATH_MAX + 1] = { 0 };
133 if (realpath(databasePath.c_str(), canonicalPath) == nullptr) {
134 LOG_ERROR("Failed to obtain real path, errno:%{public}d", errno);
135 errorCode = E_INVALID_FILE_PATH;
136 return "";
137 }
138 std::string realFilePath(canonicalPath);
139 realFilePath = realFilePath.append("/").append(name);
140 return realFilePath;
141 }
142
143 /**
144 * Get corrupt path from database path.
145 */
GetCorruptPath(std::string & path,int & errorCode)146 std::string SqliteDatabaseUtils::GetCorruptPath(std::string &path, int &errorCode)
147 {
148 std::string databaseFile = path;
149 std::string name = databaseFile.substr(databaseFile.find_last_of("/") + 1);
150 std::string parentFile = databaseFile.substr(0, databaseFile.find_last_of("/"));
151 std::string databaseTypeDir = parentFile.substr(parentFile.find_last_of("/") + 1);
152 size_t posDatabaseType = databaseTypeDir.find("_encrypt");
153
154 bool isEncrypt = false;
155 if (posDatabaseType != databaseTypeDir.npos) {
156 std::string databaseTypeDirStr = databaseTypeDir.substr(posDatabaseType);
157 std::string end = "_encrypt";
158 if (databaseTypeDirStr.compare(end) == 0) {
159 isEncrypt = true;
160 }
161 }
162
163 std::string databaseDir = parentFile.substr(0, parentFile.find_last_of("/"));
164 std::string encrypt = isEncrypt ? "_encrypt" : "";
165 std::string corruptTypeDir = "corrupt" + encrypt;
166 std::string corruptPath = databaseDir + "/" + corruptTypeDir;
167
168 if (access(corruptPath.c_str(), F_OK) != 0) {
169 if (mkdir(corruptPath.c_str(), g_mkdirMode)) {
170 errorCode = E_CREATE_FOLDER_FAIL;
171 }
172 }
173 corruptPath = corruptPath + "/" + name;
174 return corruptPath;
175 }
176
177 /**
178 * Get and Check no dbname path.
179 */
GetDatabasePathNoName(std::string & context,RdbStoreConfig & fileConfig,int & errorCode)180 std::string SqliteDatabaseUtils::GetDatabasePathNoName(std::string &context, RdbStoreConfig &fileConfig, int &errorCode)
181 {
182 std::string securityLevel = fileConfig.GetDatabaseFileSecurityLevel();
183 std::string databaseDir = GetDatabaseDir(fileConfig, securityLevel);
184 std::string databasePath = context + "/" + databaseDir;
185 std::unique_lock<std::mutex> lock(g_locker);
186 if (access(databasePath.c_str(), F_OK) != 0) {
187 if (mkdir(databasePath.c_str(), g_mkdirMode)) {
188 errorCode = E_CREATE_FOLDER_FAIL;
189 }
190 }
191 return databasePath;
192 }
193
GetDatabaseDir(RdbStoreConfig & fileConfig,std::string & securityLevel)194 std::string SqliteDatabaseUtils::GetDatabaseDir(RdbStoreConfig &fileConfig, std::string &securityLevel)
195 {
196 std::string databaseTypeDir = fileConfig.GetDatabaseFileType();
197 std::string suffix = fileConfig.GetEncryptKey().empty() ? "" : "_encrypt";
198 std::string prefix;
199 if (!securityLevel.compare("S3") || !securityLevel.compare("S4")) {
200 prefix = "sece_";
201 } else {
202 prefix = "";
203 }
204 return prefix + databaseTypeDir + suffix;
205 }
206 } // namespace NativeRdb
207 } // namespace OHOS