Retrieve tizenglobalapp uid with tzplatform_getuid
[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 <tzplatform_config.h>
35 #include "ail_private.h"
36 #include "ail_db.h"
37
38 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
39 #define BUFSIZE 4096
40 #define QUERY_ATTACH "attach database '%s' as Global"
41 #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)"
42
43 #define QUERY_CREATE_VIEW_LOCAL "CREATE temp VIEW localname as select distinct * from (select  * from main.localname m union select * from Global.localname g)"
44
45 #define retv_with_dbmsg_if(expr, val) do { \
46         if (expr) { \
47                 _E("db_info.dbUserro: %s", sqlite3_errmsg(db_info.dbUserro)); \
48                 _E("db_info.dbGlobalro: %s", sqlite3_errmsg(db_info.dbGlobalro)); \
49                 _E("db_info.dbUserrw: %s", sqlite3_errmsg(db_info.dbUserrw)); \
50                 _E("db_info.dbGlobalrw: %s", sqlite3_errmsg(db_info.dbGlobalrw)); \
51                 _E("db_info.dbUserro errcode: %d", sqlite3_extended_errcode(db_info.dbUserro)); \
52                 _E("db_info.dbGlobalro errcode: %d", sqlite3_extended_errcode(db_info.dbGlobalro)); \
53                 _E("db_info.dbUserrw errcode: %d", sqlite3_extended_errcode(db_info.dbUserrw)); \
54                 _E("db_info.dbGlobalrw errcode: %d", sqlite3_extended_errcode(db_info.dbGlobalrw)); \
55                 return (val); \
56         } \
57 } while (0)
58
59 static __thread struct {
60         sqlite3         *dbUserro;
61         sqlite3         *dbGlobalro;
62         sqlite3         *dbUserrw;
63         sqlite3         *dbGlobalrw;
64 } db_info = {
65         .dbUserro = NULL,
66         .dbGlobalro = NULL,
67         .dbUserrw = NULL,
68         .dbGlobalrw = NULL
69 };
70   static __thread      sqlite3         *dbInit = NULL;
71
72 static int ail_db_change_perm(const char *db_file)
73 {
74         char buf[BUFSIZE];
75         char journal_file[BUFSIZE];
76         char *files[3];
77         int ret, i;
78         struct group *grpinfo = NULL;
79         const char *name = "users";
80
81         files[0] = (char *)db_file;
82         files[1] = journal_file;
83         files[2] = NULL;
84
85         retv_if(!db_file, AIL_ERROR_FAIL);
86         if(getuid()) //At this time we should be root to apply this
87                         return AIL_ERROR_OK;
88
89         snprintf(journal_file, sizeof(journal_file), "%s%s", db_file, "-journal");
90
91         for (i = 0; files[i]; i++) {
92                 grpinfo = getgrnam(name);
93                 if(grpinfo == NULL)
94                         _E("getgrnam(users) returns NULL !");
95
96                 // Compare git_t type and not group name
97                 ret = chown(files[i], OWNER_ROOT, grpinfo->gr_gid);
98                 if (ret == -1) {
99                         strerror_r(errno, buf, sizeof(buf));
100                         _E("FAIL : chown %s %d.%d, because %s", db_file, OWNER_ROOT, grpinfo->gr_gid, buf);
101                         return AIL_ERROR_FAIL;
102                 }
103
104                 ret = chmod(files[i], S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
105                 if (ret == -1) {
106                         strerror_r(errno, buf, sizeof(buf));
107                         _E("FAIL : chmod %s 0664, because %s", db_file, buf);
108                         return AIL_ERROR_FAIL;
109                 }
110         }
111
112         return AIL_ERROR_OK;
113 }
114
115 char* ail_get_icon_path(uid_t uid)
116 {
117         char *result = NULL;
118         struct group *grpinfo = NULL;
119         char *dir = NULL;
120         struct passwd *userinfo = getpwuid(uid);
121
122         if (uid != GLOBAL_USER) {
123
124                 if (userinfo == NULL) {
125                         _E("getpwuid(%d) returns NULL !", uid);
126                         return NULL;
127                 }
128                 grpinfo = getgrnam("users");
129                 if (grpinfo == NULL) {
130                         _E("getgrnam(users) returns NULL !");
131                         return NULL;
132                 }
133                 // Compare git_t type and not group name
134                 if (grpinfo->gr_gid != userinfo->pw_gid) {
135                         _E("UID [%d] does not belong to 'users' group!", uid);
136                         return NULL;
137                 }
138                 asprintf(&result, "%s/.applications/icons/", userinfo->pw_dir);
139         } else {
140                 result = tzplatform_mkpath(TZ_SYS_RW_ICONS, "/");
141         }
142         int ret;
143         mkdir(result, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
144         if (getuid() == OWNER_ROOT) {
145                 ret = chown(result, uid, grpinfo->gr_gid);
146                 if (ret == -1) {
147                         char buf[BUFSIZE];
148                         strerror_r(errno, buf, sizeof(buf));
149                         _E("FAIL : chown %s %d.%d, because %s", result, uid, grpinfo->gr_gid, buf);
150                 }
151         }
152         return result;
153 }
154
155 static char* ail_get_app_DB(uid_t uid)
156 {
157         char *result = NULL;
158         char *journal = NULL;
159         struct group *grpinfo = NULL;
160         char *dir = NULL;
161         struct passwd *userinfo = getpwuid(uid);
162
163         if (uid != GLOBAL_USER) {
164
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, "%s/.applications/dbspace/.app_info.db", userinfo->pw_dir);
180                 asprintf(&journal, "%s/.applications/dbspace/.app_info.db-journal", userinfo->pw_dir);
181         } else {
182                         result = strdup(APP_INFO_DB_FILE);
183                         journal = strdup(APP_INFO_DB_FILE_JOURNAL);
184         }
185         char *temp = strdup(result);
186         dir = strrchr(temp, '/');
187         if(!dir)
188         {
189                 free(temp);
190                 return result;
191         }
192         *dir = 0;
193         if ((uid != GLOBAL_USER)||((uid == GLOBAL_USER)&& (geteuid() == 0 ))) {
194                 int ret;
195                 mkdir(temp, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
196                 if (getuid() == OWNER_ROOT) {
197                         ret = chown(dir + 1, uid, grpinfo->gr_gid);
198                         if (ret == -1) {
199                                 char buf[BUFSIZE];
200                                 strerror_r(errno, buf, sizeof(buf));
201                                 _E("FAIL : chown %s %d.%d, because %s", dir + 1, uid, grpinfo->gr_gid, buf);
202                         }
203         }
204         }
205         free(temp);
206         return result;
207 }
208
209 char* al_get_desktop_path(uid_t uid)
210 {
211         char *result = NULL;
212         struct group *grpinfo = NULL;
213         char *dir = NULL;
214         struct passwd *userinfo = getpwuid(uid);
215
216         if (uid != GLOBAL_USER) {
217
218                 if (userinfo == NULL) {
219                         _E("getpwuid(%d) returns NULL !", uid);
220                         return NULL;
221                 }
222                 grpinfo = getgrnam("users");
223                 if (grpinfo == NULL) {
224                         _E("getgrnam(users) returns NULL !");
225                         return NULL;
226                 }
227                 // Compare git_t type and not group name
228                 if (grpinfo->gr_gid != userinfo->pw_gid) {
229                         _E("UID [%d] does not belong to 'users' group!", uid);
230                         return NULL;
231                 }
232                 asprintf(&result, "%s/.applications/desktop/", userinfo->pw_dir);
233         } else {
234                 result = tzplatform_mkpath(TZ_SYS_RW_DESKTOP_APP, "/");
235         }
236         if ((uid != GLOBAL_USER)||((uid == GLOBAL_USER)&& (geteuid() == 0 ))) {
237                 int ret;
238                 mkdir(result, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
239                 ret = chown(result, uid, grpinfo->gr_gid);
240                 if (ret == -1) {
241                         char buf[BUFSIZE];
242                         strerror_r(errno, buf, sizeof(buf));
243                         _E("FAIL : chown %s %d.%d, because %s", result, uid, grpinfo->gr_gid, buf);
244                 }
245         }
246         return result;
247 }
248
249
250 static ail_error_e db_do_prepare(sqlite3 *db, const char *query, sqlite3_stmt **stmt)
251 {
252         int ret;
253
254         retv_if(!query, AIL_ERROR_INVALID_PARAMETER);
255         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
256         retv_if(!db, AIL_ERROR_DB_FAILED);
257
258         ret = sqlite3_prepare_v2(db, query, strlen(query), stmt, NULL);
259         if (ret != SQLITE_OK) {
260                 _E("%s\n", sqlite3_errmsg(db));
261                 return AIL_ERROR_DB_FAILED;
262         } else
263                 return AIL_ERROR_OK;
264 }
265
266 ail_error_e db_open(db_open_mode mode, uid_t uid)
267 {
268         int ret;
269         int changed = 0;
270         int i;
271         const char *tbls[3] = {
272                 "CREATE TABLE app_info "
273                 "(package TEXT PRIMARY KEY, "
274                 "exec TEXT DEFAULT 'No Exec', "
275                 "name TEXT DEFAULT 'No Name', "
276                 "type TEXT DEFAULT 'Application', "
277                 "icon TEXT DEFAULT 'No Icon', "
278                 "categories TEXT, "
279                 "version TEXT, "
280                 "mimetype TEXT, "
281                 "x_slp_service TEXT, "
282                 "x_slp_packagetype TEXT, "
283                 "x_slp_packagecategories TEXT, "
284                 "x_slp_packageid TEXT, "
285                 "x_slp_uri TEXT, "
286                 "x_slp_svc TEXT, "
287                 "x_slp_exe_path TEXT, "
288                 "x_slp_appid TEXT, "
289                 "x_slp_pkgid TEXT, "
290                 "x_slp_domain TEXT, "
291                 "x_slp_submodemainid TEXT, "
292                 "x_slp_installedstorage TEXT, "
293                 "x_slp_baselayoutwidth INTEGER DEFAULT 0, "
294                 "x_slp_installedtime INTEGER DEFAULT 0, "
295                 "nodisplay INTEGER DEFAULT 0, "
296                 "x_slp_taskmanage INTEGER DEFAULT 1, "
297                 "x_slp_multiple INTEGER DEFAULT 0, "
298                 "x_slp_removable INTEGER DEFAULT 1, "
299                 "x_slp_ishorizontalscale INTEGER DEFAULT 0, "
300                 "x_slp_enabled INTEGER DEFAULT 1, "
301                 "x_slp_submode INTEGER DEFAULT 0, "
302                 "desktop TEXT UNIQUE NOT NULL);",
303                 "CREATE TABLE localname (package TEXT NOT NULL, "
304                 "locale TEXT NOT NULL, "
305                 "name TEXT NOT NULL, "
306                 "x_slp_pkgid TEXT NOT NULL, PRIMARY KEY (package, locale));",
307
308                 NULL
309         };
310
311         if (access(ail_get_app_DB(uid), F_OK)) {
312                 if (AIL_ERROR_OK == db_util_open_with_options(ail_get_app_DB(uid), &dbInit, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL))
313                 {
314                         for (i = 0; tbls[i] != NULL; i++) {
315                                 ret = do_db_exec(tbls[i], dbInit);
316                                 retv_if(ret != AIL_ERROR_OK, AIL_ERROR_DB_FAILED);
317                         }
318                         if(AIL_ERROR_OK != ail_db_change_perm(ail_get_app_DB(uid))) {
319                                 _E("Failed to change permission\n");
320                 }
321                 } else {
322                         dbInit = NULL;
323                         _E("Failed to create table %s\n", ail_get_app_DB(uid));
324                 }
325         }
326         if(dbInit) {
327                 ret = sqlite3_close(dbInit);
328                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
329                 dbInit = NULL;
330         }
331         if(mode & DB_OPEN_RO) {
332                 if(uid != GLOBAL_USER) {
333                         if (!db_info.dbUserro) {
334                                 db_util_open_with_options(ail_get_app_DB(uid), &db_info.dbUserro, SQLITE_OPEN_READONLY, NULL);
335                                 char query_attach[AIL_SQL_QUERY_MAX_LEN];
336                                 char query_view_app[AIL_SQL_QUERY_MAX_LEN];
337                                 char query_view_local[AIL_SQL_QUERY_MAX_LEN];
338                                 snprintf(query_attach, AIL_SQL_QUERY_MAX_LEN, QUERY_ATTACH, ail_get_app_DB(GLOBAL_USER));
339                                 if (db_exec_usr_ro(query_attach) < 0) {
340                                         _D("executing query_attach : %s", query_attach );
341                                         return AIL_ERROR_DB_FAILED;
342                                 }
343                                 snprintf(query_view_app, AIL_SQL_QUERY_MAX_LEN, QUERY_CREATE_VIEW_APP);
344                                 if (db_exec_usr_ro(query_view_app) < 0) {
345                                         _D("executing query_attach : %s", query_view_app );
346                                         return AIL_ERROR_DB_FAILED;
347                                 }
348
349                                 snprintf(query_view_local, AIL_SQL_QUERY_MAX_LEN, QUERY_CREATE_VIEW_LOCAL);
350                                 if (db_exec_usr_ro(query_view_local) < 0) {
351                                         _D("executing query_attach : %s", query_view_local );
352                                         return AIL_ERROR_DB_FAILED;
353                                 }
354                         }
355                 } else {
356                         if (!db_info.dbGlobalro) {
357                                 ret = db_util_open_with_options(ail_get_app_DB(GLOBAL_USER), &db_info.dbGlobalro, SQLITE_OPEN_READONLY, NULL);
358                                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
359                         }
360                 }
361  }
362         if(mode & DB_OPEN_RW) {
363                 if(uid != GLOBAL_USER) {
364                         if(!db_info.dbUserrw){
365                                 ret = db_util_open(ail_get_app_DB(uid), &db_info.dbUserrw, 0);
366                         }
367                 } else {
368                         if(!db_info.dbGlobalrw){
369                                 ret = db_util_open(ail_get_app_DB(GLOBAL_USER), &db_info.dbGlobalrw, 0);
370                         }
371                 }
372                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
373         }
374
375         return AIL_ERROR_OK;
376 }
377
378
379 ail_error_e db_prepare(const char *query, sqlite3_stmt **stmt)
380 {
381         return db_do_prepare(db_info.dbUserro, query, stmt);
382 }
383
384 ail_error_e db_prepare_globalro(const char *query, sqlite3_stmt **stmt)
385 {
386         return db_do_prepare(db_info.dbGlobalro, query, stmt);
387 }
388
389 ail_error_e db_prepare_rw(const char *query, sqlite3_stmt **stmt)
390 {
391         return db_do_prepare(db_info.dbUserrw, query, stmt);
392 }
393
394
395 ail_error_e db_prepare_globalrw(const char *query, sqlite3_stmt **stmt)
396 {
397         return db_do_prepare(db_info.dbGlobalrw, query, stmt);
398 }
399
400
401 ail_error_e db_bind_bool(sqlite3_stmt *stmt, int idx, bool value)
402 {
403         int ret;
404
405         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
406
407         ret = sqlite3_bind_int(stmt, idx, (int) value);
408         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
409
410         return AIL_ERROR_OK;
411 }
412
413
414
415 ail_error_e db_bind_int(sqlite3_stmt *stmt, int idx, int value)
416 {
417         int ret;
418
419         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
420
421         ret = sqlite3_bind_int(stmt, idx, value);
422         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
423
424         return AIL_ERROR_OK;
425 }
426
427 ail_error_e db_bind_text(sqlite3_stmt *stmt, int idx, char* value)
428 {
429         int ret;
430
431         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
432
433         ret = sqlite3_bind_text(stmt, idx, value, strlen(value), 0);
434         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
435
436         return AIL_ERROR_OK;
437 }
438
439
440 ail_error_e db_step(sqlite3_stmt *stmt)
441 {
442         int ret;
443
444         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
445
446         ret = sqlite3_step(stmt);
447         switch (ret) {
448                 case SQLITE_DONE:
449                         return AIL_ERROR_NO_DATA;
450                 case SQLITE_ROW:
451                         return AIL_ERROR_OK;
452         }
453
454         retv_with_dbmsg_if(1, AIL_ERROR_DB_FAILED);
455 }
456
457
458
459 ail_error_e db_column_bool(sqlite3_stmt *stmt, int index, bool *value)
460 {
461         int out_val;
462
463         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
464         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
465
466         out_val = sqlite3_column_int(stmt, index);
467         *value = (out_val == 1)? true:false;
468
469         return AIL_ERROR_OK;
470 }
471
472
473
474 ail_error_e db_column_int(sqlite3_stmt *stmt, int index, int *value)
475 {
476         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
477         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
478
479         *value = sqlite3_column_int(stmt, index);
480
481         return AIL_ERROR_OK;
482 }
483
484
485
486 ail_error_e db_column_str(sqlite3_stmt *stmt, int index, char **str)
487 {
488         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
489         retv_if(!str, AIL_ERROR_INVALID_PARAMETER);
490
491         *str = (char *)sqlite3_column_text(stmt, index);
492
493         return AIL_ERROR_OK;
494 }
495
496
497
498 ail_error_e db_reset(sqlite3_stmt *stmt)
499 {
500         int ret;
501
502         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
503
504         sqlite3_clear_bindings(stmt);
505
506         ret = sqlite3_reset(stmt);
507         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
508
509         return AIL_ERROR_OK;
510 }
511
512
513
514 ail_error_e db_finalize(sqlite3_stmt *stmt)
515 {
516         int ret;
517
518         retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
519
520         ret = sqlite3_finalize(stmt);
521         retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
522
523         return AIL_ERROR_OK;
524 }
525
526
527
528 ail_error_e do_db_exec(const char *query, sqlite3 * fileSQL)
529 {
530         int ret;
531         char *errmsg;
532
533         retv_if(!query, AIL_ERROR_INVALID_PARAMETER);
534         retv_if(!fileSQL, AIL_ERROR_DB_FAILED);
535
536         ret = sqlite3_exec(fileSQL, query, NULL, NULL, &errmsg);
537         if (ret != SQLITE_OK) {
538                 _E("Cannot execute this query - %s. because %s",
539                                 query, errmsg? errmsg:"uncatched error");
540                 sqlite3_free(errmsg);
541                 return AIL_ERROR_DB_FAILED;
542         }
543
544         return AIL_ERROR_OK;
545 }
546
547
548
549 ail_error_e db_exec_usr_rw(const char *query)
550 {
551         return do_db_exec(query, db_info.dbUserrw);
552 }
553
554
555 ail_error_e db_exec_usr_ro(const char *query)
556 {
557         return do_db_exec(query, db_info.dbUserro);
558 }
559
560 ail_error_e db_exec_glo_ro(const char *query)
561 {
562         return do_db_exec(query, db_info.dbGlobalro);
563 }
564
565 ail_error_e db_exec_glo_rw(const char *query)
566 {
567         return do_db_exec(query, db_info.dbGlobalrw);
568 }
569
570
571 ail_error_e db_close(void)
572 {
573         int ret;
574
575         if(db_info.dbUserro) {
576                 ret = sqlite3_close(db_info.dbUserro);
577                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
578
579                 db_info.dbUserro = NULL;
580         }
581         if(db_info.dbGlobalrw) {
582                 ret = sqlite3_close(db_info.dbGlobalrw);
583                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
584
585                 db_info.dbGlobalrw = NULL;
586         }
587         if(db_info.dbUserrw) {
588                 ret = sqlite3_close(db_info.dbUserrw);
589                 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
590
591                 db_info.dbUserrw = NULL;
592         }
593
594         return AIL_ERROR_OK;
595 }
596
597 EXPORT_API ail_error_e ail_db_close(void)
598 {
599         return db_close();
600 }
601
602 int db_exec_sqlite_query(char *query, sqlite_query_callback callback, void *data)
603 {
604         char *error_message = NULL;
605         if(db_info.dbGlobalro) {
606                 if (SQLITE_OK !=
607                         sqlite3_exec(db_info.dbGlobalro, query, callback, data, &error_message)) {
608                         _E("Don't execute query = %s error message = %s\n", query,
609                                 error_message);
610                         sqlite3_free(error_message);
611                         return -1;
612                 }
613         }
614         if(db_info.dbUserro) {
615                 if (SQLITE_OK !=
616                         sqlite3_exec(db_info.dbUserro, query, callback, data, &error_message)) {
617                         _E("Don't execute query = %s error message = %s\n", query,
618                                 error_message);
619                         sqlite3_free(error_message);
620                         return -1;
621                 }
622         }
623         sqlite3_free(error_message);
624         return 0;
625 }
626
627 // End of file.