46b8c95acef39008ab616256926f65be80b555f9
[platform/core/appfw/pkgmgr-info.git] / src / common / database / db_handle_provider.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <fcntl.h>
18 #include <sys/types.h>
19
20 #include <tzplatform_config.h>
21
22 #include <algorithm>
23 #include <string>
24 #include <vector>
25
26 #include "db_handle_provider.hh"
27 #include "pkgmgrinfo_debug.h"
28 #include "pkgmgr-info.h"
29
30
31 #ifdef LOG_TAG
32 #undef LOG_TAG
33 #endif
34 #define LOG_TAG "PKGMGR_INFO"
35
36 namespace {
37
38 constexpr uid_t REGULAR_USER = 5000;
39
40 uid_t GetGlobalUID() {
41   return tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
42 }
43
44 uid_t ConvertUID(uid_t uid) {
45   if (uid < REGULAR_USER)
46     return tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
47   else
48     return uid;
49 }
50
51 }  // namespace
52
53 namespace pkgmgr_common {
54
55 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
56     DBHandleProvider::provider_;
57 bool DBHandleProvider::is_memory_global_ = false;
58 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
59     DBHandleProvider::global_parser_memory_db_handle_(
60         nullptr, sqlite3_close_v2);
61 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
62     DBHandleProvider::cert_memory_db_handle_(nullptr, sqlite3_close_v2);
63 std::string DBHandleProvider::global_parser_memory_db_path_ =
64     "file:parserdb?mode=memory&cache=shared";
65 std::string DBHandleProvider::global_parser_file_db_path_;
66 std::string DBHandleProvider::cert_memory_db_path_ =
67     "file:certdb?mode=memory&cache=shared";
68 std::string DBHandleProvider::cert_file_db_path_;
69 std::unordered_set<pid_t> DBHandleProvider::pid_list_;
70 std::recursive_mutex DBHandleProvider::lock_;
71
72 DBHandleProvider::DBHandleProvider(uid_t uid) : uid_(uid),
73     is_memory_(false), parser_memory_db_handle_(nullptr, sqlite3_close_v2) {
74   char* tmp_path = nullptr;
75   if (global_parser_file_db_path_.empty()) {
76     tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
77     global_parser_file_db_path_ = tmp_path;
78     free(tmp_path);
79
80     tmp_path = getUserPkgCertDBPath();
81     cert_file_db_path_ = tmp_path;
82     free(tmp_path);
83   }
84
85   tmp_path = getUserPkgParserDBPathUID(uid_);
86   parser_file_db_path_ = tmp_path;
87   free(tmp_path);
88
89   parser_memory_db_path_ = "file:parserdb" +
90       std::to_string(static_cast<int>(uid_)) + "?mode=memory&cache=shared";
91 }
92
93 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
94   static std::mutex singleton_lock;
95   std::unique_lock<std::mutex> u(singleton_lock);
96   uid = ConvertUID(uid);
97   auto& prov = provider_[uid];
98   if (prov == nullptr)
99     prov.reset(new DBHandleProvider(uid));
100
101   return *prov;
102 }
103
104 bool DBHandleProvider::IsCrashedWriteRequest() {
105   std::unique_lock<std::recursive_mutex> u(lock_);
106   if (pid_list_.empty())
107     return false;
108   bool ret = true;
109   LOGD("Check process count : %d", pid_list_.size());
110   std::vector<pid_t> remove_pids;
111   for (pid_t pid : pid_list_) {
112     std::string status_path = "/proc/" + std::to_string(pid) + "/status";
113
114     int fd = open(status_path.c_str(), O_RDONLY);
115     if (fd < 0) {
116       LOGE("Process is crashed (%d)", pid);
117       remove_pids.push_back(pid);
118     } else {
119       ret = false;
120       close(fd);
121     }
122   }
123
124   for (pid_t pid : remove_pids)
125     pid_list_.erase(pid);
126
127   return ret;
128 }
129
130 std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
131     pid_t pid, bool write) {
132   std::unique_lock<std::recursive_mutex> u(lock_);
133   std::vector<std::pair<std::string, uid_t>> db_path_list;
134   if (is_memory_ != is_memory_global_)
135     SetMemoryMode(pid, is_memory_global_);
136
137   if (is_memory_ && pid_list_.find(pid) == pid_list_.end() && !write) {
138     if (uid_ > REGULAR_USER)
139       db_path_list.emplace_back(std::make_pair(parser_memory_db_path_, uid_));
140     db_path_list.emplace_back(
141         std::make_pair(global_parser_memory_db_path_, GetGlobalUID()));
142   } else {
143     if (uid_ > REGULAR_USER)
144       db_path_list.emplace_back(std::make_pair(parser_file_db_path_, uid_));
145     db_path_list.emplace_back(
146         std::make_pair(global_parser_file_db_path_, GetGlobalUID()));
147   }
148
149   if (db_path_list.size() == 1) {
150     LOGD("global db path : %s", db_path_list[0].first.c_str());
151   } else {
152     LOGD("local db path : %s", db_path_list[0].first.c_str());
153     LOGD("global db path : %s", db_path_list[1].first.c_str());
154   }
155
156   return db_path_list;
157 }
158
159 std::string DBHandleProvider::GetCertDBPath(pid_t pid, bool write) {
160   std::unique_lock<std::recursive_mutex> u(lock_);
161   if (is_memory_ != is_memory_global_)
162     SetMemoryMode(pid, is_memory_global_);
163
164   if ((is_memory_ && pid_list_.find(pid) == pid_list_.end()) && !write)
165     return cert_memory_db_path_;
166   else
167     return cert_file_db_path_;
168 }
169
170 sqlite3* DBHandleProvider::GetMemoryDBHandle(const std::string& filedb_path,
171     const std::string& memorydb_path) {
172   sqlite3* memorydb = nullptr;
173   sqlite3* filedb = nullptr;
174   int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
175       SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
176   if (ret != SQLITE_OK) {
177     LOGE("Failed to open memory DB %d(%s)", ret, memorydb_path.c_str());
178     return nullptr;
179   }
180
181   ret = sqlite3_open_v2(filedb_path.c_str(), &filedb,
182       SQLITE_OPEN_READONLY, nullptr);
183   if (ret != SQLITE_OK) {
184     LOGE("Failed to open file DB %d(%s)", ret, filedb_path.c_str());
185     sqlite3_close_v2(memorydb);
186     return nullptr;
187   }
188   sqlite3_backup* backup = sqlite3_backup_init(memorydb, "main",
189       filedb, "main");
190   if (backup == nullptr) {
191     LOGE("Failed to backup for memory DB");
192     sqlite3_close_v2(memorydb);
193     sqlite3_close_v2(filedb);
194     return nullptr;
195   }
196
197   sqlite3_backup_step(backup, -1);
198   sqlite3_backup_finish(backup);
199   LOGD("Set memory DB(%s)", memorydb_path.c_str());
200   sqlite3_close_v2(filedb);
201   return memorydb;
202 }
203
204 void DBHandleProvider::SetMemoryMode(pid_t pid, bool flag) {
205   std::unique_lock<std::recursive_mutex> u(lock_);
206   if (flag == is_memory_global_ && flag == is_memory_)
207     return;
208
209   if (flag == true) {
210     sqlite3* parser_db = GetMemoryDBHandle(parser_file_db_path_,
211         parser_memory_db_path_);
212     if (parser_db != nullptr)
213       parser_memory_db_handle_.reset(parser_db);
214
215     if (is_memory_ == is_memory_global_) {  /* first call */
216       sqlite3* global_parser_file_db = GetMemoryDBHandle(
217           global_parser_file_db_path_, global_parser_memory_db_path_);
218       if (global_parser_file_db)
219         global_parser_memory_db_handle_.reset(global_parser_file_db);
220       sqlite3* cert_db = GetMemoryDBHandle(cert_file_db_path_,
221           cert_memory_db_path_);
222       if (cert_db != nullptr)
223         cert_memory_db_handle_.reset(cert_db);
224
225       if (pid_list_.find(pid) == pid_list_.end())
226         pid_list_.insert(pid);
227     }
228   } else {
229     parser_memory_db_handle_.reset(nullptr);
230     cert_memory_db_handle_.reset(nullptr);
231     global_parser_memory_db_handle_.reset(nullptr);
232
233     auto it = pid_list_.find(pid);
234     if (it != pid_list_.end())
235       pid_list_.erase(it);
236     else
237       LOGE("Given pid is not exists in pid list : %d", pid);
238   }
239   is_memory_ = flag;
240   is_memory_global_ = flag;
241   LOGD("Set Memory mode : %s", flag ? "Memory" : "File");
242 }
243
244 }  // namespace pkgmgr_common