Fix (run application with) xwalk-launcher
[platform/core/appfw/ail.git] / src / ail_db.c
1 /*
2  * ail
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <db-util.h>
28 #include <errno.h>
29 #include <glib.h>
30 #include <grp.h>
31 #include <pwd.h>
32 #include <sys/smack.h>
33 #include <sys/stat.h>
34 #include "ail_private.h"
35 #include "ail_db.h"
36
37 #define GLOBAL_USER     0 //#define     tzplatform_getenv(TZ_GLOBAL) //TODO
38 #define BUFSIZE 4096
39 #define QUERY_ATTACH "attach database '%s' as Global"
40 #define QUERY_CREATE_VIEW_APP "CREATE temp VIEW app_info as select distinct * from (select  * from main.app_info m union select * from Global.app_info g)"
41
42 #define QUERY_CREATE_VIEW_LOCAL "CREATE temp VIEW localname as select distinct * from (select  * from main.localname m union select * from Global.localname g)"
43
44 #define retv_with_dbmsg_if(expr, val) do { \
45         if (expr) { \
46                 _E("db_info.dbUserro: %s", sqlite3_errmsg(db_info.dbUserro)); \
47                 _E("db_info.dbGlobalro: %s", sqlite3_errmsg(db_info.dbGlobalro)); \
48                 _E("db_info.dbUserrw: %s", sqlite3_errmsg(db_info.dbUserrw)); \
49                 _E("db_info.dbGlobalrw: %s", sqlite3_errmsg(db_info.dbGlobalrw)); \
50                 _E("db_info.dbUserro errcode: %d", sqlite3_extended_errcode(db_info.dbUserro)); \
51                 _E("db_info.dbGlobalro errcode: %d", sqlite3_extended_errcode(db_info.dbGlobalro)); \
52                 _E("db_info.dbUserrw errcode: %d", sqlite3_extended_errcode(db_info.dbUserrw)); \
53                 _E("db_info.dbGlobalrw errcode: %d", sqlite3_extended_errcode(db_info.dbGlobalrw)); \
54                 return (val); \
55         } \
56 } while (0)
57
58 static __thread struct {
59         sqlite3         *dbUserro;
60         sqlite3         *dbGlobalro;
61         sqlite3         *dbUserrw;
62         sqlite3         *dbGlobalrw;
63 } db_info = {
64         .dbUserro = NULL,
65         .dbGlobalro = NULL,
66         .dbUserrw = NULL,
67         .dbGlobalrw = NULL
68 };
69   static __thread      sqlite3         *dbInit = NULL;
70
71 static int ail_db_change_perm(const char *db_file)
72 {
73         char buf[BUFSIZE];
74         char journal_file[BUFSIZE];
75         char *files[3];
76         int ret, i;
77         struct group *grpinfo = NULL;
78         const char *name = "users";
79
80         files[0] = (char *)db_file;
81         files[1] = journal_file;
82         files[2] = NULL;
83
84         retv_if(!db_file, AIL_ERROR_FAIL);
85         if(getuid()) //At this time we should be root to apply this
86                         return AIL_ERROR_OK;
87
88         snprintf(journal_file, sizeof(journal_file), "%s%s", db_file, "-journal");
89
90         for (i = 0; files[i]; i++) {
91                 grpinfo = getgrnam(name);
92                 if(grpinfo == NULL)
93                         _E("getgrnam(users) returns NULL !");
94
95                 // Compare git_t type and not group name
96                 ret = chown(files[i], OWNER_ROOT, grpinfo->gr_gid);
97                 if (ret == -1) {
98                         strerror_r(errno, buf, sizeof(buf));
99                         _E("FAIL : chown %s %d.%d, because %s", db_file, OWNER_ROOT, grpinfo->gr_gid, buf);
100                         return AIL_ERROR_FAIL;
101                 }
102
103                 ret = chmod(files[i], S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
104                 if (ret == -1) {
105                         strerror_r(errno, buf, sizeof(buf));
106                         _E("FAIL : chmod %s 0664, because %s", db_file, buf);
107                         return AIL_ERROR_FAIL;
108                 }
109         }
110
111         return AIL_ERROR_OK;
112 }
113
114 char* ail_get_icon_path(uid_t uid)
115 {
116         char *result_psswd = NULL;
117         if(uid == GLOBAL_USER)
118         {
119                 result_psswd = tzplatform_getenv(TZ_SYS_RW_ICONS);
120         }
121         else
122         {
123                 const char *name = "users";
124                 struct passwd *userinfo = NULL;
125                 struct group *grpinfo = NULL;
126
127                 userinfo = getpwuid(uid);
128                 if(userinfo == NULL) {
129                         _E("getpwuid(%d) returns NULL !", uid);
130                         return NULL;
131                 }
132                 
133                 grpinfo = getgrnam(name);
134                 if(grpinfo == NULL) {
135                         _E("getgrnam(users) returns NULL !");
136                         return NULL;
137                 }
138                 // Compare git_t type and not group name
139                 if (grpinfo->gr_gid != userinfo->pw_gid) {
140                         _E("UID [%d] does not belong to 'users' group!", uid);
141                         return NULL;
142                 }
143                 result_psswd = tzplatform_getenv(TZ_USER_ICONS);
144         }
145         return result_psswd;
146 }
147
148 static char* ail_get_app_DB(uid_t uid)
149 {
150         char *result_psswd = NULL;
151         struct group *grpinfo = NULL;
152         char * dir = NULL;
153         if(uid == GLOBAL_USER)
154         {
155                 result_psswd = strdup(APP_INFO_DB_FILE);
156                 grpinfo = getgrnam("root");
157                 if(grpinfo == NULL) {
158                         _E("getgrnam(users) returns NULL !");
159                         return NULL;
160                 }
161         }
162         else
163         {
164                 struct passwd *userinfo = getpwuid(uid);
165                 if(userinfo == NULL) {
166                         _E("getpwuid(%d) returns NULL !", uid);
167                         return NULL;
168                 }
169                 grpinfo = getgrnam("users");
170                 if(grpinfo == NULL) {
171                         _E("getgrnam(users) returns NULL !");
172                         return NULL;
173                 }
174                 // Compare git_t type and not group name
175                 if (grpinfo->gr_gid != userinfo->pw_gid) {
176                         _E("UID [%d] does not belong to 'users' group!", uid);
177                         return NULL;
178                 }
179                 asprintf(&result_psswd, "%s/.applications/dbspace/.app_info.db", userinfo->pw_dir);
180         }
181
182         dir = strrchr(result_psswd, '/');
183         if(!dir)
184                 return result_psswd;
185
186         //Control if db exist create otherwise 
187         if(access(dir + 1, F_OK)) {
188                 int ret;
189                 mkdir(dir + 1, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
190                 ret = chown(dir + 1, uid, grpinfo->gr_gid);
191                 if (ret == -1) {
192                         char buf[BUFSIZE];
193                         strerror_r(errno, buf, sizeof(buf));
194                         _E("FAIL : chown %s %d.%d, because %s", dir + 1, uid, grpinfo->gr_gid, buf);
195                 }
196     /* chsmack */
197     if(smack_setlabel(result_psswd, "_", SMACK_LABEL_ACCESS))
198           {
199                   _E("failed chsmack -a \"_\" %s", result_psswd);
200           } else {
201                   _D("chsmack -a \"_\" %s", result_psswd);
202           }
203         }
204         return result_psswd;
205 }
206
207 static ail_error_e db_do_prepare(sqlite3 *db, const char *query, sqlite3_stmt **stmt)
208 {
209         int ret;
210
211         retv_if(!query, AIL_ERROR_INVALID_PARAMETER);
212         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
213         retv_if(!db, AIL_ERROR_DB_FAILED);
214
215         ret = sqlite3_prepare_v2(db, query, strlen(query), stmt, NULL);
216         if (ret != SQLITE_OK) {
217                 _E("%s\n", sqlite3_errmsg(db));
218                 return AIL_ERROR_DB_FAILED;
219         } else
220                 return AIL_ERROR_OK;
221 }
222
223 ail_error_e db_open(db_open_mode mode, uid_t uid)
224 {
225         int ret;
226         int changed = 0;
227         int i;
228         const char *tbls[3] = {
229                 "CREATE TABLE app_info "
230                 "(package TEXT PRIMARY KEY, "
231                 "exec TEXT DEFAULT 'No Exec', "
232                 "name TEXT DEFAULT 'No Name', "
233                 "type TEXT DEFAULT 'Application', "
234                 "icon TEXT DEFAULT 'No Icon', "
235                 "categories TEXT, "
236                 "version TEXT, "
237                 "mimetype TEXT, "
238                 "x_slp_service TEXT, "
239                 "x_slp_packagetype TEXT, "
240                 "x_slp_packagecategories TEXT, "
241                 "x_slp_packageid TEXT, "
242                 "x_slp_uri TEXT, "
243                 "x_slp_svc TEXT, "
244                 "x_slp_exe_path TEXT, "
245                 "x_slp_appid TEXT, "
246                 "x_slp_pkgid TEXT, "
247                 "x_slp_domain TEXT, "
248                 "x_slp_submodemainid TEXT, "
249                 "x_slp_installedstorage TEXT, "
250                 "x_slp_baselayoutwidth INTEGER DEFAULT 0, "
251                 "x_slp_installedtime INTEGER DEFAULT 0, "
252                 "nodisplay INTEGER DEFAULT 0, "
253                 "x_slp_taskmanage INTEGER DEFAULT 1, "
254                 "x_slp_multiple INTEGER DEFAULT 0, "
255                 "x_slp_removable INTEGER DEFAULT 1, "
256                 "x_slp_ishorizontalscale INTEGER DEFAULT 0, "
257                 "x_slp_enabled INTEGER DEFAULT 1, "
258                 "x_slp_submode INTEGER DEFAULT 0, "
259                 "desktop TEXT UNIQUE NOT NULL);",
260                 "CREATE TABLE localname (package TEXT NOT NULL, "
261                 "locale TEXT NOT NULL, "
262                 "name TEXT NOT NULL, "
263                 "x_slp_pkgid TEXT NOT NULL, PRIMARY KEY (package, locale));",
264
265                 NULL
266         };
267
268         if (access(ail_get_app_DB(uid), F_OK)) {
269                 if (AIL_ERROR_OK == db_util_open_with_options(ail_get_app_DB(uid), &dbInit, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL))
270                 {
271                         for (i = 0; tbls[i] != NULL; i++) {
272                                 ret = do_db_exec(tbls[i], dbInit);
273                                 retv_if(ret != AIL_ERROR_OK, AIL_ERROR_DB_FAILED);
274                         }
275                 } else {
276                         dbInit = NULL;
277                         _E("Failed to create table %s\n",ail_get_app_DB(uid));
278                 }
279         }
280         if(dbInit) {
281                 if(AIL_ERROR_OK != ail_db_change_perm(ail_get_app_DB(uid))) {
282                                 _E("Failed to change permission\n");
283                 }
284                 ret = sqlite3_close(dbInit);
285                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
286                 dbInit = NULL;
287         }
288         if(mode & DB_OPEN_RO) {
289                 if (!db_info.dbUserro) {
290                         db_util_open_with_options(ail_get_app_DB(uid), &db_info.dbUserro, SQLITE_OPEN_READONLY, NULL);
291                         char query_attach[AIL_SQL_QUERY_MAX_LEN];
292                         char query_view_app[AIL_SQL_QUERY_MAX_LEN];
293                         char query_view_local[AIL_SQL_QUERY_MAX_LEN];
294                         snprintf(query_attach, AIL_SQL_QUERY_MAX_LEN, QUERY_ATTACH, ail_get_app_DB(GLOBAL_USER));
295                         _E("info : execute query_attach : %s", query_attach );
296                         if (db_exec_usr_ro(query_attach) < 0) {
297                                 return AIL_ERROR_DB_FAILED;
298                         }
299                         snprintf(query_view_app, AIL_SQL_QUERY_MAX_LEN, QUERY_CREATE_VIEW_APP);
300                         _E("info : execute query_attach : %s", query_view_app );
301                         if (db_exec_usr_ro(query_view_app) < 0) {
302                                 return AIL_ERROR_DB_FAILED;
303                         }
304
305                         snprintf(query_view_local, AIL_SQL_QUERY_MAX_LEN, QUERY_CREATE_VIEW_LOCAL);
306                         _E("info : execute query_attach : %s", query_view_local );
307                         if (db_exec_usr_ro(query_view_local) < 0) {
308                                 return AIL_ERROR_DB_FAILED;
309                         }
310                 }
311                 if (!db_info.dbGlobalro) {
312                                 ret = db_util_open_with_options(ail_get_app_DB(GLOBAL_USER), &db_info.dbGlobalro, SQLITE_OPEN_READONLY, NULL);
313                                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
314                         }
315         }
316
317         if(mode & DB_OPEN_RW) {
318                 //if (__is_admin) {
319                 if(uid != GLOBAL_USER) {//TOCHANGETO is_admin
320                         if(!db_info.dbUserrw){
321                                 ret = db_util_open(ail_get_app_DB(uid), &db_info.dbUserrw, 0);
322                         }
323                 } else {
324                         if(!db_info.dbGlobalrw){
325                                 ret = db_util_open(ail_get_app_DB(GLOBAL_USER), &db_info.dbGlobalrw, 0);
326                         }
327                 }
328                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
329         
330                 //}
331         }
332
333         return AIL_ERROR_OK;
334 }
335
336
337 ail_error_e db_prepare(const char *query, sqlite3_stmt **stmt)
338 {
339         return db_do_prepare(db_info.dbUserro, query, stmt);
340 }
341
342 ail_error_e db_prepare_globalro(const char *query, sqlite3_stmt **stmt)
343 {
344         return db_do_prepare(db_info.dbGlobalro, query, stmt);
345 }
346
347 ail_error_e db_prepare_rw(const char *query, sqlite3_stmt **stmt)
348 {
349         return db_do_prepare(db_info.dbUserrw, query, stmt);
350 }
351
352
353 ail_error_e db_prepare_globalrw(const char *query, sqlite3_stmt **stmt)
354 {
355         return db_do_prepare(db_info.dbGlobalrw, query, stmt);
356 }
357
358
359 ail_error_e db_bind_bool(sqlite3_stmt *stmt, int idx, bool value)
360 {
361         int ret;
362
363         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
364
365         ret = sqlite3_bind_int(stmt, idx, (int) value);
366         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
367
368         return AIL_ERROR_OK;
369 }
370
371
372
373 ail_error_e db_bind_int(sqlite3_stmt *stmt, int idx, int value)
374 {
375         int ret;
376
377         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
378
379         ret = sqlite3_bind_int(stmt, idx, value);
380         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
381
382         return AIL_ERROR_OK;
383 }
384
385 ail_error_e db_bind_text(sqlite3_stmt *stmt, int idx, char* value)
386 {
387         int ret;
388
389         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
390
391         ret = sqlite3_bind_text(stmt, idx, value, strlen(value), 0);
392         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
393
394         return AIL_ERROR_OK;
395 }
396
397
398 ail_error_e db_step(sqlite3_stmt *stmt)
399 {
400         int ret;
401
402         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
403
404         ret = sqlite3_step(stmt);
405         switch (ret) {
406                 case SQLITE_DONE:
407                         return AIL_ERROR_NO_DATA;
408                 case SQLITE_ROW:
409                         return AIL_ERROR_OK;
410         }
411
412         retv_with_dbmsg_if(1, AIL_ERROR_DB_FAILED);
413 }
414
415
416
417 ail_error_e db_column_bool(sqlite3_stmt *stmt, int index, bool *value)
418 {
419         int out_val;
420
421         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
422         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
423
424         out_val = sqlite3_column_int(stmt, index);
425         *value = (out_val == 1)? true:false;
426
427         return AIL_ERROR_OK;
428 }
429
430
431
432 ail_error_e db_column_int(sqlite3_stmt *stmt, int index, int *value)
433 {
434         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
435         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
436
437         *value = sqlite3_column_int(stmt, index);
438
439         return AIL_ERROR_OK;
440 }
441
442
443
444 ail_error_e db_column_str(sqlite3_stmt *stmt, int index, char **str)
445 {
446         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
447         retv_if(!str, AIL_ERROR_INVALID_PARAMETER);
448
449         *str = (char *)sqlite3_column_text(stmt, index);
450
451         return AIL_ERROR_OK;
452 }
453
454
455
456 ail_error_e db_reset(sqlite3_stmt *stmt)
457 {
458         int ret;
459
460         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
461
462         sqlite3_clear_bindings(stmt);
463
464         ret = sqlite3_reset(stmt);
465         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
466
467         return AIL_ERROR_OK;
468 }
469
470
471
472 ail_error_e db_finalize(sqlite3_stmt *stmt)
473 {
474         int ret;
475
476         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
477
478         ret = sqlite3_finalize(stmt);
479         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
480
481         return AIL_ERROR_OK;
482 }
483
484
485
486 ail_error_e do_db_exec(const char *query, sqlite3 * fileSQL)
487 {
488         int ret;
489         char *errmsg;
490
491         retv_if(!query, AIL_ERROR_INVALID_PARAMETER);
492         retv_if(!fileSQL, AIL_ERROR_DB_FAILED);
493
494         ret = sqlite3_exec(fileSQL, query, NULL, NULL, &errmsg);
495         if (ret != SQLITE_OK) {
496                 _E("Cannot execute this query - %s. because %s",
497                                 query, errmsg? errmsg:"uncatched error");
498                 sqlite3_free(errmsg);
499                 return AIL_ERROR_DB_FAILED;
500         }
501
502         return AIL_ERROR_OK;
503 }
504
505
506
507 ail_error_e db_exec_usr_rw(const char *query)
508 {
509         return do_db_exec(query, db_info.dbUserrw);
510 }
511
512
513 ail_error_e db_exec_usr_ro(const char *query)
514 {
515         return do_db_exec(query, db_info.dbUserro);
516 }
517
518 ail_error_e db_exec_glo_ro(const char *query)
519 {
520         return do_db_exec(query, db_info.dbGlobalro);
521 }
522
523 ail_error_e db_exec_glo_rw(const char *query)
524 {
525         return do_db_exec(query, db_info.dbGlobalrw);
526 }
527
528
529 ail_error_e db_close(void)
530 {
531         int ret;
532
533         if(db_info.dbUserro) {
534                 ret = sqlite3_close(db_info.dbUserro);
535                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
536
537                 db_info.dbUserro = NULL;
538         }
539         if(db_info.dbGlobalrw) {
540                 ret = sqlite3_close(db_info.dbGlobalrw);
541                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
542
543                 db_info.dbGlobalrw = NULL;
544         }
545         if(db_info.dbUserrw) {
546                 ret = sqlite3_close(db_info.dbUserrw);
547                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
548
549                 db_info.dbUserrw = NULL;
550         }
551
552         return AIL_ERROR_OK;
553 }
554
555 EXPORT_API ail_error_e ail_db_close(void)
556 {
557         return db_close();
558 }
559
560 int db_exec_sqlite_query(char *query, sqlite_query_callback callback, void *data)
561 {
562         char *error_message = NULL;
563         if(db_info.dbUserro) {
564                 if (SQLITE_OK !=
565                         sqlite3_exec(db_info.dbUserro, query, callback, data, &error_message)) {
566                         _E("Don't execute query = %s error message = %s\n", query,
567                                 error_message);
568                         sqlite3_free(error_message);
569                         return -1;
570                 }
571         }
572         if(db_info.dbUserro) {
573                 if (SQLITE_OK !=
574                         sqlite3_exec(db_info.dbUserro, query, callback, data, &error_message)) {
575                         _E("Don't execute query = %s error message = %s\n", query,
576                                 error_message);
577                         sqlite3_free(error_message);
578                         return -1;
579                 }
580         }
581         sqlite3_free(error_message);
582         return 0;
583 }
584
585 // End of file.