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 #ifndef OMIT_MULTI_VER
17 #include "local_database_oper.h"
18 
19 #include "log_print.h"
20 #include "platform_specific.h"
21 #include "db_errno.h"
22 #include "db_constant.h"
23 #include "db_common.h"
24 
25 namespace DistributedDB {
LocalDatabaseOper(SQLiteLocalKvDB * localKvDb,SQLiteStorageEngine * storageEngine)26 LocalDatabaseOper::LocalDatabaseOper(SQLiteLocalKvDB *localKvDb, SQLiteStorageEngine *storageEngine)
27     : localKvDb_(localKvDb),
28       storageEngine_(storageEngine)
29 {}
30 
Rekey(const CipherPassword & passwd)31 int LocalDatabaseOper::Rekey(const CipherPassword &passwd)
32 {
33     if (localKvDb_ == nullptr || storageEngine_ == nullptr) {
34         return -E_INVALID_DB;
35     }
36 
37     return ExecuteRekey(passwd, localKvDb_->GetDbProperties());
38 }
39 
Import(const std::string & filePath,const CipherPassword & passwd)40 int LocalDatabaseOper::Import(const std::string &filePath, const CipherPassword &passwd)
41 {
42     if (localKvDb_ == nullptr || storageEngine_ == nullptr) {
43         return -E_INVALID_DB;
44     }
45 
46     return ExecuteImport(filePath, passwd, localKvDb_->GetDbProperties());
47 }
48 
Export(const std::string & filePath,const CipherPassword & passwd) const49 int LocalDatabaseOper::Export(const std::string &filePath, const CipherPassword &passwd) const
50 {
51     return ExecuteExport(filePath, passwd, localKvDb_->GetDbProperties());
52 }
53 
RekeyPreHandle(const CipherPassword & passwd,int & errCode)54 bool LocalDatabaseOper::RekeyPreHandle(const CipherPassword &passwd, int &errCode)
55 {
56     CipherType cipherType;
57     CipherPassword cachePasswd;
58     localKvDb_->GetDbProperties().GetPassword(cipherType, cachePasswd);
59 
60     if (cachePasswd.GetSize() == 0 && passwd.GetSize() == 0) {
61         errCode = E_OK;
62         return false;
63     }
64 
65     // need invoke sqlite3 rekey
66     if (cachePasswd.GetSize() > 0 && passwd.GetSize() > 0) {
67         errCode = localKvDb_->RunRekeyLogic(cipherType, passwd);
68         return false;
69     }
70 
71     return true;
72 }
73 
BackupDb(const CipherPassword & passwd) const74 int LocalDatabaseOper::BackupDb(const CipherPassword &passwd) const
75 {
76     std::string filePrefix;
77     int errCode = GetCtrlFilePrefix(localKvDb_->GetDbProperties(), filePrefix);
78     if (errCode != E_OK) {
79         return errCode;
80     }
81 
82     // create backup dir
83     std::string backupDir = filePrefix + DBConstant::PATH_BACKUP_POSTFIX;
84     errCode = DBCommon::CreateDirectory(backupDir);
85     if (errCode != E_OK) {
86         LOGE("create backup dir failed:%d.", errCode);
87         return errCode;
88     }
89 
90     // export db to backup
91     CipherType cipherType;
92     CipherPassword oldPasswd;
93     localKvDb_->GetDbProperties().GetPassword(cipherType, oldPasswd);
94     std::string backupDbName = backupDir + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION;
95     return localKvDb_->RunExportLogic(cipherType, passwd, backupDbName);
96 }
97 
CloseStorages()98 int LocalDatabaseOper::CloseStorages()
99 {
100     // close old db
101     storageEngine_->Release();
102     int errCode = RekeyRecover(localKvDb_->GetDbProperties());
103     if (errCode != E_OK) {
104         LOGE("Recover failed after rekey ok:%d.", errCode);
105         int innerCode = localKvDb_->InitDatabaseContext(localKvDb_->GetDbProperties());
106         if (innerCode != E_OK) {
107             LOGE("ReInit the handlePool failed:%d", innerCode);
108         }
109     }
110     return errCode;
111 }
112 
RekeyPostHandle(const CipherPassword & passwd)113 int LocalDatabaseOper::RekeyPostHandle(const CipherPassword &passwd)
114 {
115     CipherType cipherType;
116     CipherPassword oldPasswd;
117     localKvDb_->GetDbPropertyForUpdate().GetPassword(cipherType, oldPasswd);
118     localKvDb_->GetDbPropertyForUpdate().SetPassword(cipherType, passwd);
119     return localKvDb_->InitDatabaseContext(localKvDb_->GetDbProperties());
120 }
121 
ExportAllDatabases(const std::string & currentDir,const CipherPassword & passwd,const std::string & dbDir) const122 int LocalDatabaseOper::ExportAllDatabases(const std::string &currentDir, const CipherPassword &passwd,
123     const std::string &dbDir) const
124 {
125     std::string backupDbName = dbDir + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION;
126     std::string currentDb = currentDir + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION;
127 
128     CipherType cipherType;
129     CipherPassword currPasswd;
130     localKvDb_->GetDbProperties().GetPassword(cipherType, currPasswd);
131     int errCode = SQLiteUtils::ExportDatabase(currentDb, cipherType, currPasswd, backupDbName, passwd);
132     if (errCode != E_OK) {
133         LOGE("Export the database failed:%d", errCode);
134     }
135     return errCode;
136 }
137 
BackupCurrentDatabase(const ImportFileInfo & info) const138 int LocalDatabaseOper::BackupCurrentDatabase(const ImportFileInfo &info) const
139 {
140     storageEngine_->Release();
141     // create the pre flag file.
142     int errCode = OS::CreateFileByFileName(info.curValidFile);
143     if (errCode != E_OK) {
144         LOGE("create ctrl file failed:%d.", errCode);
145         return errCode;
146     }
147 
148     // create backup dir
149     errCode = DBCommon::CreateDirectory(info.backupDir);
150     if (errCode != E_OK) {
151         LOGE("Create backup dir failed:%d.", errCode);
152         (void)RemoveFile(info.curValidFile);
153         return errCode;
154     }
155 
156     std::string currentFile = info.currentDir + DBConstant::LOCAL_DATABASE_NAME +
157         DBConstant::DB_EXTENSION;
158     std::string backupFile = info.backupDir + DBConstant::LOCAL_DATABASE_NAME +
159         DBConstant::DB_EXTENSION;
160     errCode = DBCommon::CopyFile(currentFile, backupFile);
161     if (errCode != E_OK) {
162         LOGE("Backup the current database error:%d", errCode);
163         return errCode;
164     }
165     int innerCode = rename(info.curValidFile.c_str(), info.backValidFile.c_str());
166     if (innerCode != 0) {
167         LOGE("Failed to rename the file after the backup:%d", errno);
168         errCode = -E_SYSTEM_API_FAIL;
169     }
170     return errCode;
171 }
172 
ImportUnpackedDatabase(const ImportFileInfo & info,const CipherPassword & srcPasswd) const173 int LocalDatabaseOper::ImportUnpackedDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd) const
174 {
175     // create backup dir
176     int errCode = DBCommon::RemoveAllFilesOfDirectory(info.currentDir, false);
177     if (errCode != E_OK) {
178         return errCode;
179     }
180 
181     std::string unpackedFile = info.unpackedDir + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION;
182     std::string currentFile = info.currentDir + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION;
183     CipherType cipherType;
184     CipherPassword passwd;
185     localKvDb_->GetDbProperties().GetPassword(cipherType, passwd);
186     errCode = SQLiteUtils::ExportDatabase(unpackedFile, cipherType, srcPasswd, currentFile, passwd);
187     DBCommon::RemoveAllFilesOfDirectory(info.unpackedDir);
188     if (errCode != E_OK) {
189         LOGE("export the unpacked database to current error:%d", errCode);
190         errCode = -E_INVALID_FILE;
191         return errCode;
192     }
193 
194     // reinitialize the database, and delete the backup database.
195     errCode = localKvDb_->InitDatabaseContext(localKvDb_->GetDbProperties());
196     if (errCode != E_OK) {
197         LOGE("InitDatabaseContext error:%d", errCode);
198         return errCode;
199     }
200 
201     // rename the flag file.
202     int innerCode = rename(info.backValidFile.c_str(), info.curValidFile.c_str());
203     if (innerCode != E_OK) {
204         LOGE("Failed to rename after the import operation:%d", errno);
205         errCode = -E_SYSTEM_API_FAIL;
206     }
207 
208     return errCode;
209 }
210 
ImportPostHandle() const211 int LocalDatabaseOper::ImportPostHandle() const
212 {
213     return localKvDb_->InitDatabaseContext(localKvDb_->GetDbProperties());
214 }
215 } // namespace DistributedDB
216 #endif // OMIT_MULTI_VER
217