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