Separate source files, clean up repository
[platform/core/appfw/pkgmgr-info.git] / src / pkgmgrinfo_db.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <grp.h>
8 #include <dirent.h>
9 #include <libgen.h>
10
11 #include <sqlite3.h>
12
13 #include <tzplatform_config.h>
14 #include <db-util.h>
15
16 #include "pkgmgr-info.h"
17 #include "pkgmgrinfo_debug.h"
18 #include "pkgmgrinfo_private.h"
19 #include "pkgmgr_parser.h"
20 #include "pkgmgr_parser_internal.h"
21
22 #define QUERY_CREATE_TABLE_PACKAGE_CERT_INDEX_INFO "create table if not exists package_cert_index_info " \
23                                                 "(cert_info text not null, " \
24                                                 "cert_id integer, " \
25                                                 "cert_ref_count integer, " \
26                                                 "PRIMARY KEY(cert_id)) "
27
28 #define QUERY_CREATE_TABLE_PACKAGE_CERT_INFO "create table if not exists package_cert_info " \
29                                                 "(package text not null, " \
30                                                 "author_root_cert integer, " \
31                                                 "author_im_cert integer, " \
32                                                 "author_signer_cert integer, " \
33                                                 "dist_root_cert integer, " \
34                                                 "dist_im_cert integer, " \
35                                                 "dist_signer_cert integer, " \
36                                                 "dist2_root_cert integer, " \
37                                                 "dist2_im_cert integer, " \
38                                                 "dist2_signer_cert integer, " \
39                                                 "PRIMARY KEY(package)) "
40 __thread db_handle manifest_db;
41 __thread db_handle cert_db;
42
43 typedef int (*sqlite_query_callback)(void *data, int ncols, char **coltxt, char **colname);
44
45 static int _mkdir_for_user(const char* dir, uid_t uid, gid_t gid)
46 {
47         int ret;
48         char *fullpath;
49         char *subpath;
50
51         fullpath = strdup(dir);
52         if (fullpath == NULL)
53                 return -1;
54         subpath = dirname(fullpath);
55         if (strlen(subpath) > 1 && strcmp(subpath, fullpath) != 0) {
56                 ret = _mkdir_for_user(fullpath, uid, gid);
57                 if (ret == -1) {
58                         free(fullpath);
59                         return ret;
60                 }
61         }
62
63         ret = mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
64         if (ret && errno != EEXIST) {
65                 free(fullpath);
66                 return ret;
67         } else if (ret && errno == EEXIST) {
68                 free(fullpath);
69                 return 0;
70         }
71
72         if (getuid() == ROOT_UID) {
73                 ret = chown(dir, uid, gid);
74                 if (ret == -1)
75                         _LOGE("FAIL : chown %s %d.%d, because %s", dir, uid,
76                                         gid, strerror(errno));
77         }
78
79         free(fullpath);
80
81         return 0;
82 }
83
84 static const char *_get_db_path(uid_t uid) {
85         const char *db_path = NULL;
86         if (uid != GLOBAL_USER && uid != ROOT_UID) {
87                 tzplatform_set_user(uid);
88                 db_path = tzplatform_getenv(TZ_USER_DB);
89                 tzplatform_reset_user();
90         } else {
91                 db_path = tzplatform_getenv(TZ_SYS_DB);
92         }
93         return db_path;
94 }
95
96 static int __attach_and_create_view(sqlite3 *handle, const char *db, const char *tables[], uid_t uid)
97 {
98         int i;
99         char *err;
100         char query[MAX_QUERY_LEN];
101
102         if (uid != GLOBAL_USER && uid != ROOT_UID) {
103                 snprintf(query, sizeof(query), "ATTACH DATABASE '%s' AS Global", db);
104                 if (SQLITE_OK != sqlite3_exec(handle, query, NULL, NULL, &err)) {
105                         _LOGD("Don't execute query = %s error message = %s\n", query, err);
106                         sqlite3_free(err);
107                         return SQLITE_ERROR;
108                 }
109         }
110
111         for (i = 0; tables[i]; i++) {
112                 if (uid != GLOBAL_USER && uid != ROOT_UID)
113                         snprintf(query, sizeof(query), "CREATE TEMP VIEW '%s' AS SELECT * \
114                                         FROM (SELECT *,0 AS for_all_users FROM main.'%s' UNION \
115                                         SELECT *,1 AS for_all_users FROM Global.'%s')",
116                                         tables[i], tables[i], tables[i]);
117                 else
118                         snprintf(query, sizeof(query), "CREATE TEMP VIEW '%s' AS SELECT * \
119                                         FROM (SELECT *,1 AS for_all_users FROM main.'%s')",
120                                         tables[i], tables[i]);
121                 if (SQLITE_OK != sqlite3_exec(handle, query, NULL, NULL, &err)) {
122                         _LOGD("Don't execute query = %s error message = %s\n", query, err);
123                         sqlite3_free(err);
124                 }
125         }
126
127         return SQLITE_OK;
128 }
129
130 static int __exec_db_query(sqlite3 *db, char *query, sqlite_query_callback callback, void *data)
131 {
132         char *error_message = NULL;
133         int ret = sqlite3_exec(db, query, callback, data, &error_message);
134         if (SQLITE_OK != ret) {
135                 _LOGE("Don't execute query = %s error message = %s   ret = %d\n", query,
136                        error_message, ret);
137                 sqlite3_free(error_message);
138                 return -1;
139         }
140         sqlite3_free(error_message);
141         return 0;
142 }
143
144 int _check_create_cert_db(sqlite3 *certdb)
145 {
146         int ret = 0;
147         ret = __exec_db_query(certdb, QUERY_CREATE_TABLE_PACKAGE_CERT_INDEX_INFO, NULL, NULL);
148         if (ret < 0)
149                 return ret;
150         ret = __exec_db_query(certdb, QUERY_CREATE_TABLE_PACKAGE_CERT_INFO, NULL, NULL);
151         return ret;
152 }
153 static gid_t _get_gid(const char *name)
154 {
155         char buf[BUFSIZE];
156         struct group entry;
157         struct group *ge;
158         int ret;
159
160         ret = getgrnam_r(name, &entry, buf, sizeof(buf), &ge);
161         if (ret || ge == NULL) {
162                 _LOGE("fail to get gid of %s", name);
163                 return -1;
164         }
165
166         return entry.gr_gid;
167 }
168
169 API const char *getIconPath(uid_t uid)
170 {
171         const char *path = NULL;
172         uid_t uid_caller = getuid();
173         gid_t gid = ROOT_UID;
174
175         if (uid != GLOBAL_USER && uid != ROOT_UID) {
176                 tzplatform_set_user(uid);
177                 path = tzplatform_mkpath(TZ_USER_ICONS, "/");
178                 gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
179                 tzplatform_reset_user();
180         } else {
181                 path = tzplatform_mkpath(TZ_SYS_RW_ICONS, "/");
182         }
183
184         // just allow certain users to create the icon directory if needed.
185         if (uid_caller == ROOT_UID || uid_caller == uid)
186                 _mkdir_for_user(path, uid, gid);
187
188         return path;
189 }
190
191 API const char *getUserPkgParserDBPath(void)
192 {
193         return getUserPkgParserDBPathUID(GLOBAL_USER);
194 }
195
196 API const char *getUserPkgParserDBPathUID(uid_t uid)
197 {
198         const char *pkgmgr_parser_db = NULL;
199         uid_t uid_caller = getuid();
200         gid_t gid = ROOT_UID;
201
202         if (uid != GLOBAL_USER && uid != ROOT_UID) {
203                 tzplatform_set_user(uid);
204                 pkgmgr_parser_db = tzplatform_mkpath(TZ_USER_DB, ".pkgmgr_parser.db");
205                 gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
206                 tzplatform_reset_user();
207         } else {
208                 pkgmgr_parser_db = tzplatform_mkpath(TZ_SYS_DB, ".pkgmgr_parser.db");
209         }
210
211         // just allow certain users to create the dbspace directory if needed.
212         if (uid_caller == ROOT_UID || uid_caller == uid) {
213                 const char *db_path = _get_db_path(uid);
214                 _mkdir_for_user(db_path, uid, gid);
215         }
216
217         return pkgmgr_parser_db;
218 }
219
220 API const char *getUserPkgCertDBPath(void)
221 {
222          return getUserPkgCertDBPathUID(GLOBAL_USER);
223 }
224
225 API const char *getUserPkgCertDBPathUID(uid_t uid)
226 {
227         const char *pkgmgr_cert_db = NULL;
228         uid_t uid_caller = getuid();
229         gid_t gid = ROOT_UID;
230
231         if (uid != GLOBAL_USER && uid != ROOT_UID) {
232                 tzplatform_set_user(uid);
233                 pkgmgr_cert_db = tzplatform_mkpath(TZ_USER_DB, ".pkgmgr_cert.db");
234                 gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
235                 tzplatform_reset_user();
236         } else {
237                 pkgmgr_cert_db = tzplatform_mkpath(TZ_SYS_DB, ".pkgmgr_cert.db");
238         }
239
240         // just allow certain users to create the dbspace directory if needed.
241         if (uid_caller == ROOT_UID || uid_caller == uid) {
242                 const char *db_path = _get_db_path(uid);
243                 _mkdir_for_user(db_path, uid, gid);
244         }
245
246         return pkgmgr_cert_db;
247 }
248
249 API const char *getUserDesktopPath(uid_t uid)
250 {
251         const char *path = NULL;
252         uid_t uid_caller = getuid();
253         gid_t gid = ROOT_UID;
254
255         if (uid != GLOBAL_USER && uid != ROOT_UID) {
256                 tzplatform_set_user(uid);
257                 path = tzplatform_mkpath(TZ_USER_DESKTOP, "/");
258                 gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
259                 tzplatform_reset_user();
260         } else {
261                 path = tzplatform_mkpath(TZ_SYS_RW_DESKTOP_APP, "/");
262         }
263
264         // just allow certain users to create the icon directory if needed.
265         if (uid_caller == ROOT_UID || uid_caller == uid)
266                 _mkdir_for_user(path, uid, gid);
267
268         return path;
269 }
270
271 API const char *getUserManifestPath(uid_t uid)
272 {
273         const char *path = NULL;
274         uid_t uid_caller = getuid();
275         gid_t gid = ROOT_UID;
276
277         if (uid != GLOBAL_USER && uid != ROOT_UID) {
278                 tzplatform_set_user(uid);
279                 path = tzplatform_mkpath(TZ_USER_PACKAGES, "/");
280                 gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
281                 tzplatform_reset_user();
282         } else {
283                 path = tzplatform_mkpath(TZ_SYS_RW_PACKAGES, "/");
284         }
285
286         // just allow certain users to create the icon directory if needed.
287         if (uid_caller == ROOT_UID || uid_caller == uid)
288                 _mkdir_for_user(path, uid, gid);
289
290         return path;
291 }
292
293 int __close_manifest_db(void)
294 {
295         if (manifest_db.ref) {
296                 if (--manifest_db.ref == 0)
297                         sqlite3_close(GET_DB(manifest_db));
298                 return 0;
299         }
300         return -1;
301 }
302
303 static const char *parserdb_tables[] = {
304         "package_app_app_category",
305         "package_app_info",
306         "package_app_app_control",
307         "package_app_localized_info",
308         "package_app_app_metadata",
309         "package_app_share_allowed",
310         "package_app_app_permission",
311         "package_app_share_request",
312         "package_app_app_svc",
313         "package_info",
314         "package_app_data_control",
315         "package_localized_info",
316         "package_app_icon_section_info",
317         "package_privilege_info",
318         "package_app_image_info",
319         NULL
320 };
321
322 int __open_manifest_db(uid_t uid)
323 {
324         int ret = -1;
325         if (manifest_db.ref) {
326                 manifest_db.ref ++;
327                 return 0;
328         }
329         const char* user_pkg_parser = getUserPkgParserDBPathUID(uid);
330         if (access(user_pkg_parser, F_OK) != 0) {
331                 _LOGE("Manifest DB does not exists !! try to create\n");
332
333                 if (pkgmgr_parser_check_and_create_db(uid)) {
334                         _LOGE("create db failed");
335                         return -1;
336                 }
337
338                 if (pkgmgr_parser_initialize_db(uid)) {
339                         _LOGE("initialize db failed");
340                         return -1;
341                 }
342         }
343
344         ret = db_util_open_with_options(user_pkg_parser, &GET_DB(manifest_db),
345                         SQLITE_OPEN_READONLY, NULL);
346         retvm_if(ret != SQLITE_OK, -1, "connect db [%s] failed!\n", user_pkg_parser);
347         manifest_db.ref ++;
348         ret = __attach_and_create_view(GET_DB(manifest_db), MANIFEST_DB, parserdb_tables, uid);
349         retvm_if(ret != SQLITE_OK, -1, "attach db [%s] failed!\n", user_pkg_parser);
350
351         return 0;
352 }
353
354 int __close_cert_db(void)
355 {
356         if (cert_db.ref) {
357                 if (--cert_db.ref == 0)
358                         sqlite3_close_v2(GET_DB(cert_db));
359                         return 0;
360         }
361         _LOGE("Certificate DB is already closed !!\n");
362         return -1;
363 }
364
365 static const char *certdb_tables[] = {
366         "package_cert_index_info",
367         "package_cert_info",
368         NULL
369 };
370
371 int __open_cert_db(uid_t uid, char* mode)
372 {
373         int ret = -1;
374         if (cert_db.ref) {
375                 cert_db.ref ++;
376                 return 0;
377         }
378
379         const char* user_cert_parser = getUserPkgCertDBPathUID(uid);
380         if (access(user_cert_parser, F_OK) == 0) {
381                 ret = db_util_open_with_options(user_cert_parser, &GET_DB(cert_db),
382                                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
383                 retvm_if(ret != SQLITE_OK, -1, "connect db [%s] failed!\n", user_cert_parser);
384                 cert_db.ref ++;
385                 if ((strcmp(mode, "w") != 0)) {
386                         ret = __attach_and_create_view(GET_DB(cert_db), CERT_DB, certdb_tables, uid);
387                         retvm_if(ret != SQLITE_OK, -1, "attach db [%s] failed!\n", user_cert_parser);
388                 }
389                 return 0;
390         }
391         _LOGE("Cert DB does not exists !!\n");
392         return -1;
393 }
394
395 void _save_column_str(sqlite3_stmt *stmt, int idx, const char **str)
396 {
397         const char *val;
398
399         val = (const char *)sqlite3_column_text(stmt, idx);
400         if (val)
401                 *str = strdup(val);
402 }
403
404 API int pkgmgrinfo_pkginfo_set_state_enabled(const char *pkgid, bool enabled)
405 {
406         /* Should be implemented later */
407         return 0;
408 }
409
410 API int pkgmgrinfo_appinfo_set_usr_state_enabled(const char *appid, bool enabled, uid_t uid)
411 {
412         int ret;
413         char query[MAX_QUERY_LEN] = {'\0'};
414         char *error_message;
415
416         retvm_if(appid == NULL, PMINFO_R_EINVAL, "appid is NULL\n");
417
418         /* Open db.*/
419         ret = __open_manifest_db(uid);
420         if (ret != SQLITE_OK) {
421                 _LOGE("connect db [%s] failed!\n", getUserPkgParserDBPathUID(uid));
422                 return PMINFO_R_ERROR;
423         }
424
425         /*Begin transaction*/
426         ret = sqlite3_exec(GET_DB(manifest_db), "BEGIN EXCLUSIVE", NULL, NULL, NULL);
427         if (ret != SQLITE_OK) {
428                 _LOGE("Failed to begin transaction\n");
429                 __close_manifest_db();
430                 return PMINFO_R_ERROR;
431         }
432         _LOGD("Transaction Begin\n");
433
434         memset(query, '\0', MAX_QUERY_LEN);
435         snprintf(query, MAX_QUERY_LEN,
436                 "update package_app_info set app_enabled='%s' where app_id='%s'", enabled?"true":"false", appid);
437
438         if (SQLITE_OK !=
439             sqlite3_exec(GET_DB(manifest_db), query, NULL, NULL, &error_message)) {
440                 _LOGE("Don't execute query = %s error message = %s\n", query,
441                        error_message);
442                 sqlite3_free(error_message);
443                 return PMINFO_R_ERROR;
444         }
445         sqlite3_free(error_message);
446
447         /*Commit transaction*/
448         ret = sqlite3_exec(GET_DB(manifest_db), "COMMIT", NULL, NULL, NULL);
449         if (ret != SQLITE_OK) {
450                 _LOGE("Failed to commit transaction. Rollback now\n");
451                 sqlite3_exec(GET_DB(manifest_db), "ROLLBACK", NULL, NULL, NULL);
452                 __close_manifest_db();
453                 return PMINFO_R_ERROR;
454         }
455         _LOGD("Transaction Commit and End\n");
456         __close_manifest_db();
457         return PMINFO_R_OK;
458 }
459
460 API int pkgmgrinfo_appinfo_set_state_enabled(const char *appid, bool enabled)
461 {
462         return pkgmgrinfo_appinfo_set_usr_state_enabled(appid, enabled, GLOBAL_USER);
463 }
464
465 API int pkgmgrinfo_appinfo_set_usr_default_label(const char *appid, const char *label, uid_t uid)
466 {
467         int ret;
468         char query[MAX_QUERY_LEN] = {'\0'};
469         char *error_message;
470
471         retvm_if(appid == NULL, PMINFO_R_EINVAL, "appid is NULL\n");
472
473         ret = __open_manifest_db(uid);
474         if (ret == -1) {
475                 _LOGE("Fail to open manifest DB\n");
476                 return PMINFO_R_ERROR;
477         }
478
479         /*Begin transaction*/
480         ret = sqlite3_exec(GET_DB(manifest_db), "BEGIN EXCLUSIVE", NULL, NULL, NULL);
481         if (ret != SQLITE_OK) {
482                 _LOGE("Failed to begin transaction\n");
483                 __close_manifest_db();
484                 return PMINFO_R_ERROR;
485         }
486         _LOGD("Transaction Begin\n");
487
488         memset(query, '\0', MAX_QUERY_LEN);
489         snprintf(query, MAX_QUERY_LEN,
490                 "update package_app_localized_info set app_label='%s' where app_id='%s' and app_locale='No Locale'", label, appid);
491
492         if (SQLITE_OK !=
493             sqlite3_exec(GET_DB(manifest_db), query, NULL, NULL, &error_message)) {
494                 _LOGE("Don't execute query = %s error message = %s\n", query,
495                        error_message);
496                 sqlite3_free(error_message);
497                 return PMINFO_R_ERROR;
498         }
499
500         /*Commit transaction*/
501         ret = sqlite3_exec(GET_DB(manifest_db), "COMMIT", NULL, NULL, NULL);
502         if (ret != SQLITE_OK) {
503                 _LOGE("Failed to commit transaction. Rollback now\n");
504                 sqlite3_exec(GET_DB(manifest_db), "ROLLBACK", NULL, NULL, NULL);
505                 __close_manifest_db();
506                 return PMINFO_R_ERROR;
507         }
508         _LOGD("Transaction Commit and End\n");
509         __close_manifest_db();
510         return PMINFO_R_OK;
511 }
512
513 API int pkgmgrinfo_appinfo_set_default_label(const char *appid, const char *label)
514 {
515         return pkgmgrinfo_appinfo_set_usr_default_label(appid, label, GLOBAL_USER);
516 }
517
518 API int pkgmgrinfo_appinfo_set_usr_guestmode_visibility(pkgmgrinfo_appinfo_h handle, uid_t uid, bool status)
519 {
520         const char *val;
521         int ret;
522         char query[MAX_QUERY_LEN] = {'\0'};
523         char *errmsg;
524         sqlite3 *pkgmgr_parser_db;
525
526         retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL\n");
527
528         pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
529         val = info->uiapp_info->guestmode_visibility;
530         if (val) {
531                 ret = db_util_open_with_options(getUserPkgParserDBPathUID(uid), &pkgmgr_parser_db,
532                                 SQLITE_OPEN_READWRITE, NULL);
533                 if (ret != SQLITE_OK) {
534                         _LOGE("DB Open Failed\n");
535                         return PMINFO_R_ERROR;
536                 }
537
538                 /*TODO: Write to DB here*/
539                 if (status == true)
540                         snprintf(query, MAX_QUERY_LEN, "update package_app_info set app_guestmodevisibility = 'true' where app_id = '%s'", (char *)info->uiapp_info->appid);
541                 else
542                         snprintf(query, MAX_QUERY_LEN, "update package_app_info set app_guestmodevisibility = 'false' where app_id = '%s'", (char *)info->uiapp_info->appid);
543
544                 ret = sqlite3_exec(pkgmgr_parser_db, query, NULL, NULL, &errmsg);
545                 sqlite3_close(pkgmgr_parser_db);
546                 if (ret != SQLITE_OK) {
547                         _LOGE("DB update [%s] failed, error message = %s\n", query, errmsg);
548                         free(errmsg);
549                         return PMINFO_R_ERROR;
550                 }
551         }
552         return PMINFO_R_OK;
553 }
554
555 API int pkgmgrinfo_appinfo_set_guestmode_visibility(pkgmgrinfo_appinfo_h handle, bool status)
556 {
557         return pkgmgrinfo_appinfo_set_usr_guestmode_visibility(handle, GLOBAL_USER, status);
558 }