Store global uid as static variable
[platform/core/appfw/pkgmgr-info.git] / src / server / 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 "db_handle_provider.hh"
18
19 #include <fcntl.h>
20 #include <sys/types.h>
21
22 #include <tzplatform_config.h>
23
24 #include <algorithm>
25 #include <string>
26 #include <vector>
27
28 #include "utils/logging.hh"
29
30 #include "pkgmgrinfo_debug.h"
31 #include "pkgmgr-info.h"
32
33 #ifdef LOG_TAG
34 #undef LOG_TAG
35 #endif
36 #define LOG_TAG "PKGMGR_INFO"
37
38 namespace {
39
40 constexpr uid_t REGULAR_USER = 5000;
41
42 uid_t globaluser_uid = -1;
43
44 uid_t GetGlobalUID() {
45   if (globaluser_uid == (uid_t)-1)
46     globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
47
48   return globaluser_uid;
49 }
50
51 uid_t ConvertUID(uid_t uid) {
52   if (uid < REGULAR_USER)
53     return GetGlobalUID();
54   else
55     return uid;
56 }
57
58 static const std::string global_parser_memory_db_path =
59     "file:parserdb?mode=memory&cache=shared";
60
61 static const std::string cert_memory_db_path =
62     "file:certdb?mode=memory&cache=shared";
63
64 }  // namespace
65
66 namespace pkgmgr_server {
67 namespace database {
68
69 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
70     DBHandleProvider::provider_;
71 bool DBHandleProvider::is_memory_global_ = false;
72 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
73     DBHandleProvider::global_parser_memory_db_handle_(
74         nullptr, sqlite3_close_v2);
75 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
76     DBHandleProvider::cert_memory_db_handle_(nullptr, sqlite3_close_v2);
77 std::string DBHandleProvider::global_parser_file_db_path_;
78 std::string DBHandleProvider::cert_file_db_path_;
79 std::unordered_set<pid_t> DBHandleProvider::pid_list_;
80 std::recursive_mutex DBHandleProvider::lock_;
81
82 DBHandleProvider::DBHandleProvider(uid_t uid) : uid_(uid),
83     is_memory_(false), parser_memory_db_handle_(nullptr, sqlite3_close_v2) {
84   char* tmp_path;
85
86   if (global_parser_file_db_path_.empty()) {
87     tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
88     global_parser_file_db_path_ = tmp_path;
89     free(tmp_path);
90
91     tmp_path = getUserPkgCertDBPath();
92     cert_file_db_path_ = tmp_path;
93     free(tmp_path);
94   }
95
96   tmp_path = getUserPkgParserDBPathUID(uid_);
97   parser_file_db_path_ = tmp_path;
98   free(tmp_path);
99
100   parser_memory_db_path_ = "file:parserdb" +
101       std::to_string(static_cast<int>(uid_)) + "?mode=memory&cache=shared";
102 }
103
104 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
105   static std::mutex singleton_lock;
106   std::unique_lock<std::mutex> u(singleton_lock);
107
108   uid = ConvertUID(uid);
109   auto& prov = provider_[uid];
110   if (prov == nullptr)
111     prov.reset(new DBHandleProvider(uid));
112
113   return *prov;
114 }
115
116 bool DBHandleProvider::IsCrashedWriteRequest() {
117   std::unique_lock<std::recursive_mutex> u(lock_);
118
119   if (pid_list_.empty())
120     return false;
121
122   bool ret = true;
123   LOG(DEBUG) << "Check process count : " << pid_list_.size();
124   std::vector<pid_t> remove_pids;
125   for (pid_t pid : pid_list_) {
126     std::string status_path = "/proc/" + std::to_string(pid) + "/status";
127
128     int fd = open(status_path.c_str(), O_RDONLY);
129     if (fd < 0) {
130       LOG(ERROR) << "Process is crashed : " << pid;
131       remove_pids.push_back(pid);
132     } else {
133       ret = false;
134       close(fd);
135     }
136   }
137
138   for (pid_t pid : remove_pids)
139     pid_list_.erase(pid);
140
141   return ret;
142 }
143
144 std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
145     pid_t pid, bool write) {
146   std::unique_lock<std::recursive_mutex> u(lock_);
147   std::vector<std::pair<std::string, uid_t>> db_path_list;
148
149   if (is_memory_ != is_memory_global_)
150     is_memory_global_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
151
152   if (IsMemoryDBActive(pid, write)) {
153     if (uid_ > REGULAR_USER)
154       db_path_list.emplace_back(std::make_pair(parser_memory_db_path_, uid_));
155     db_path_list.emplace_back(
156         std::make_pair(global_parser_memory_db_path, GetGlobalUID()));
157   } else {
158     if (uid_ > REGULAR_USER)
159       db_path_list.emplace_back(std::make_pair(parser_file_db_path_, uid_));
160     db_path_list.emplace_back(
161         std::make_pair(global_parser_file_db_path_, GetGlobalUID()));
162   }
163
164   if (db_path_list.size() == 1) {
165     LOG(DEBUG) << "global db path : " << db_path_list[0].first;
166   } else {
167     LOG(DEBUG) << "local db path : " << db_path_list[0].first;
168     LOG(DEBUG) << "global db path : " << db_path_list[1].first;
169   }
170
171   return db_path_list;
172 }
173
174 std::string DBHandleProvider::GetCertDBPath(pid_t pid, bool write) {
175   std::unique_lock<std::recursive_mutex> u(lock_);
176   if (is_memory_ != is_memory_global_)
177     is_memory_global_ ?
178         SetMemoryMode(pid) : UnsetMemoryMode(is_memory_global_);
179
180   if (IsMemoryDBActive(pid, write))
181     return cert_memory_db_path;
182   else
183     return cert_file_db_path_;
184 }
185
186 sqlite3* DBHandleProvider::GetMemoryDBHandle(const std::string& filedb_path,
187     const std::string& memorydb_path) {
188   sqlite3* memorydb = nullptr;
189   sqlite3* filedb = nullptr;
190   int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
191       SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
192   if (ret != SQLITE_OK) {
193     LOG(ERROR) << "Failed to open memory DB " << ret << ": " << memorydb_path;
194     return nullptr;
195   }
196
197   ret = sqlite3_open_v2(filedb_path.c_str(), &filedb,
198       SQLITE_OPEN_READONLY, nullptr);
199   if (ret != SQLITE_OK) {
200     LOG(ERROR) << "Failed to open file DB " << ret << ": " << filedb_path;
201     sqlite3_close_v2(memorydb);
202     return nullptr;
203   }
204
205   sqlite3_backup* backup = sqlite3_backup_init(memorydb, "main",
206       filedb, "main");
207   if (backup == nullptr) {
208     LOG(ERROR) << "Failed to backup for memory DB";
209     sqlite3_close_v2(memorydb);
210     sqlite3_close_v2(filedb);
211     return nullptr;
212   }
213
214   sqlite3_backup_step(backup, -1);
215   sqlite3_backup_finish(backup);
216   sqlite3_close_v2(filedb);
217   return memorydb;
218 }
219
220 void DBHandleProvider::SetMemoryMode(pid_t pid) {
221   std::unique_lock<std::recursive_mutex> u(lock_);
222   if (is_memory_global_ && is_memory_)
223     return;
224
225   sqlite3* parser_db = GetMemoryDBHandle(parser_file_db_path_,
226       parser_memory_db_path_);
227   if (parser_db != nullptr)
228     parser_memory_db_handle_.reset(parser_db);
229
230   if (is_memory_ == is_memory_global_) {  /* first call */
231     sqlite3* global_parser_file_db = GetMemoryDBHandle(
232         global_parser_file_db_path_, global_parser_memory_db_path);
233     if (global_parser_file_db)
234       global_parser_memory_db_handle_.reset(global_parser_file_db);
235     sqlite3* cert_db = GetMemoryDBHandle(cert_file_db_path_,
236         cert_memory_db_path);
237     if (cert_db != nullptr)
238       cert_memory_db_handle_.reset(cert_db);
239
240     if (pid_list_.find(pid) == pid_list_.end())
241       pid_list_.insert(pid);
242   }
243
244   is_memory_ = true;
245   is_memory_global_ = true;
246   LOG(DEBUG) << "Set Memory mode : Memory";
247 }
248
249 void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
250   std::unique_lock<std::recursive_mutex> u(lock_);
251   if (!is_memory_global_ && !is_memory_)
252     return;
253
254   parser_memory_db_handle_.reset(nullptr);
255   cert_memory_db_handle_.reset(nullptr);
256   global_parser_memory_db_handle_.reset(nullptr);
257
258   auto it = pid_list_.find(pid);
259   if (it != pid_list_.end())
260     pid_list_.erase(it);
261   else
262     LOG(ERROR) << "Given pid is not exists in pid list : " << pid;
263
264   is_memory_ = false;
265   is_memory_global_ = false;
266   LOG(DEBUG) << "Set Memory mode : File";
267 }
268
269 bool DBHandleProvider::IsMemoryDBActive(pid_t pid, bool write) {
270   return (is_memory_ && pid_list_.find(pid) == pid_list_.end() && !write);
271 }
272
273 }  // namespace database
274 }  // namespace pkgmgr_server