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