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