Merge "Add robustness to mkdir" into tizen
[platform/core/appfw/ail.git] / src / ail_db.c
index 474f453..462c545 100755 (executable)
 #include <pwd.h>
 #include <sys/smack.h>
 #include <sys/stat.h>
+#include <tzplatform_config.h>
 #include "ail_private.h"
 #include "ail_db.h"
 
-#define GLOBAL_USER    0 //#define     tzplatform_getenv(TZ_GLOBAL) //TODO
+#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
 #define BUFSIZE 4096
 #define QUERY_ATTACH "attach database '%s' as Global"
 #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)"
 
 #define QUERY_CREATE_VIEW_LOCAL "CREATE temp VIEW localname as select distinct * from (select  * from main.localname m union select * from Global.localname g)"
 
+#define SET_SMACK_LABEL(x,uid) \
+       if(smack_setlabel((x), (((uid) == GLOBAL_USER)?"*":"User"), SMACK_LABEL_ACCESS)) _E("failed chsmack -a \"User/*\" %s", x); \
+       else _D("chsmack -a \"User/*\" %s", x);
+       
+       
 #define retv_with_dbmsg_if(expr, val) do { \
        if (expr) { \
                _E("db_info.dbUserro: %s", sqlite3_errmsg(db_info.dbUserro)); \
@@ -68,35 +74,34 @@ static __thread struct {
 };
   static __thread      sqlite3         *dbInit = NULL;
 
-static int ail_db_change_perm(const char *db_file)
+static int ail_db_change_perm(const char *db_file, uid_t uid)
 {
        char buf[BUFSIZE];
        char journal_file[BUFSIZE];
        char *files[3];
        int ret, i;
-       struct group *grpinfo = NULL;
-       const char *name = "users";
-
+       struct passwd *userinfo = NULL;
        files[0] = (char *)db_file;
        files[1] = journal_file;
        files[2] = NULL;
 
        retv_if(!db_file, AIL_ERROR_FAIL);
-       if(getuid()) //At this time we should be root to apply this
+       if(getuid() != OWNER_ROOT) //At this time we should be root to apply this
                        return AIL_ERROR_OK;
-
+    userinfo = getpwuid(uid);
+    if (!userinfo) {
+               _E("FAIL: user %d doesn't exist", uid);
+               return AIL_ERROR_FAIL;
+       }
        snprintf(journal_file, sizeof(journal_file), "%s%s", db_file, "-journal");
 
        for (i = 0; files[i]; i++) {
-               grpinfo = getgrnam(name);
-               if(grpinfo == NULL)
-                       _E("getgrnam(users) returns NULL !");
-
                // Compare git_t type and not group name
-               ret = chown(files[i], OWNER_ROOT, grpinfo->gr_gid);
+               ret = chown(files[i], uid, userinfo->pw_gid);
+               SET_SMACK_LABEL(files[i],uid)
                if (ret == -1) {
                        strerror_r(errno, buf, sizeof(buf));
-                       _E("FAIL : chown %s %d.%d, because %s", db_file, OWNER_ROOT, grpinfo->gr_gid, buf);
+                       _E("FAIL : chown %s %d.%d, because %s", db_file, uid, userinfo->pw_gid, buf);
                        return AIL_ERROR_FAIL;
                }
 
@@ -118,8 +123,11 @@ char* ail_get_icon_path(uid_t uid)
        char *dir = NULL;
        struct passwd *userinfo = getpwuid(uid);
 
+       if (uid == 0) {
+               _E("FAIL : Root is not allowed user! please fix it replacing with DEFAULT_USER");
+               return NULL;
+       }
        if (uid != GLOBAL_USER) {
-
                if (userinfo == NULL) {
                        _E("getpwuid(%d) returns NULL !", uid);
                        return NULL;
@@ -137,37 +145,44 @@ char* ail_get_icon_path(uid_t uid)
                asprintf(&result, "%s/.applications/icons/", userinfo->pw_dir);
        } else {
                result = tzplatform_mkpath(TZ_SYS_RW_ICONS, "/");
-               grpinfo = getgrnam("root");
-               if (grpinfo == NULL) {
-                       _E("getgrnam(root) returns NULL !");
-                       return NULL;
-                       }
-                       if (grpinfo->gr_gid != userinfo->pw_gid) {
-                               _E("UID [%d] does not belong to 'root' group!", uid);
-                               return NULL;
-                       }
        }
-       int ret;
-       mkdir(result, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
-       ret = chown(result, uid, grpinfo->gr_gid);
-       if (ret == -1) {
-               char buf[BUFSIZE];
-               strerror_r(errno, buf, sizeof(buf));
-               _E("FAIL : chown %s %d.%d, because %s", result, uid, grpinfo->gr_gid, buf);
+       int ret = mkdir(result, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
+       if (ret == -1 && errno != EEXIST) {
+               _E("FAIL : to create directory %s %d", result, errno);
+       } else if (getuid() == OWNER_ROOT) {
+               ret = chown(result, uid, ((grpinfo)?grpinfo->gr_gid:0));
+               SET_SMACK_LABEL(result,uid)
+               if (ret == -1) {
+                       char buf[BUFSIZE];
+                       strerror_r(errno, buf, sizeof(buf));
+                       _E("FAIL : chown %s %d.%d, because %s", result, uid, ((grpinfo)?grpinfo->gr_gid:0), buf);
+               }
        }
        return result;
 }
 
-static char* ail_get_app_DB(uid_t uid)
+char* ail_get_app_DB_journal(uid_t uid)
+{
+
+       char *app_path = ail_get_app_DB(uid);
+       char* result = NULL;
+
+       asprintf(&result, "%s-journal", app_path);
+       return  result;
+}
+
+char* ail_get_app_DB(uid_t uid)
 {
        char *result = NULL;
-       char *journal = NULL;
        struct group *grpinfo = NULL;
        char *dir = NULL;
        struct passwd *userinfo = getpwuid(uid);
 
+       if (uid == 0) {
+               _E("FAIL : Root is not allowed! switch to DEFAULT_USER");
+               return NULL;
+       }
        if (uid != GLOBAL_USER) {
-
                if (userinfo == NULL) {
                        _E("getpwuid(%d) returns NULL !", uid);
                        return NULL;
@@ -183,19 +198,8 @@ static char* ail_get_app_DB(uid_t uid)
                        return NULL;
                }
                asprintf(&result, "%s/.applications/dbspace/.app_info.db", userinfo->pw_dir);
-               asprintf(&journal, "%s/.applications/dbspace/.app_info.db-journal", userinfo->pw_dir);
        } else {
-               grpinfo = getgrnam("root");
-               if (grpinfo == NULL) {
-                       _E("getgrnam(root) returns NULL !");
-                       return NULL;
-                       }
-                       if (grpinfo->gr_gid != userinfo->pw_gid) {
-                               _E("UID [%d] does not belong to 'root' group!", uid);
-                               return NULL;
-                       }
                        result = strdup(APP_INFO_DB_FILE);
-                       journal = strdup(APP_INFO_DB_FILE_JOURNAL);
        }
        char *temp = strdup(result);
        dir = strrchr(temp, '/');
@@ -205,29 +209,34 @@ static char* ail_get_app_DB(uid_t uid)
                return result;
        }
        *dir = 0;
-       if ((uid != GLOBAL_USER)||((uid == GLOBAL_USER)&& (geteuid() == 0 ))) {
-               int ret;
-               mkdir(temp, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
-               ret = chown(dir + 1, uid, grpinfo->gr_gid);
-               if (ret == -1) {
-                       char buf[BUFSIZE];
-                       strerror_r(errno, buf, sizeof(buf));
-                       _E("FAIL : chown %s %d.%d, because %s", dir + 1, uid, grpinfo->gr_gid, buf);
+               int ret = mkdir(temp, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
+               if (ret == -1 && errno != EEXIST) {
+                       _E("FAIL : to create directory %s %d", temp, errno);
+               } else if (getuid() == OWNER_ROOT) {
+                       ret = chown(temp, uid, ((grpinfo)?grpinfo->gr_gid:0));
+                       SET_SMACK_LABEL(temp,uid)
+                       if (ret == -1) {
+                               char buf[BUFSIZE];
+                               strerror_r(errno, buf, sizeof(buf));
+                               _E("FAIL : chown %s %d.%d, because %s", temp, uid, ((grpinfo)?grpinfo->gr_gid:0), buf);
+                       }
                }
-       }
        free(temp);
        return result;
 }
 
-char* al_get_desktop_path(uid_t uid)
+char* ail_get_desktop_path(uid_t uid)
 {
        char *result = NULL;
        struct group *grpinfo = NULL;
        char *dir = NULL;
        struct passwd *userinfo = getpwuid(uid);
 
+       if (uid == 0) {
+               _E("FAIL : Root is not allowed user! please fix it replacing with DEFAULT_USER");
+               return NULL;
+       }
        if (uid != GLOBAL_USER) {
-
                if (userinfo == NULL) {
                        _E("getpwuid(%d) returns NULL !", uid);
                        return NULL;
@@ -244,27 +253,20 @@ char* al_get_desktop_path(uid_t uid)
                }
                asprintf(&result, "%s/.applications/desktop/", userinfo->pw_dir);
        } else {
-               grpinfo = getgrnam("root");
-               if (grpinfo == NULL) {
-                       _E("getgrnam(root) returns NULL !");
-                       return NULL;
-               }
-               if (grpinfo->gr_gid != userinfo->pw_gid) {
-                       _E("UID [%d] does not belong to 'root' group!", uid);
-                       return NULL;
-               }
                result = tzplatform_mkpath(TZ_SYS_RW_DESKTOP_APP, "/");
        }
-       if ((uid != GLOBAL_USER)||((uid == GLOBAL_USER)&& (geteuid() == 0 ))) {
-               int ret;
-               mkdir(result, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
-               ret = chown(result, uid, grpinfo->gr_gid);
-               if (ret == -1) {
-                       char buf[BUFSIZE];
-                       strerror_r(errno, buf, sizeof(buf));
-                       _E("FAIL : chown %s %d.%d, because %s", result, uid, grpinfo->gr_gid, buf);
+               int ret = mkdir(result, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
+               if (ret == -1 && errno != EEXIST) {
+                       _E("FAIL : to create directory %s %d", result, errno);
+               } else if (getuid() == OWNER_ROOT) {
+                       ret = chown(result, uid, ((grpinfo)?grpinfo->gr_gid:0));
+                       SET_SMACK_LABEL(result,uid)
+                       if (ret == -1) {
+                               char buf[BUFSIZE];
+                               strerror_r(errno, buf, sizeof(buf));
+                               _E("FAIL : chown %s %d.%d, because %s", result, uid, ((grpinfo)?grpinfo->gr_gid:0), buf);
+                       }
                }
-       }
        return result;
 }
 
@@ -330,19 +332,22 @@ ail_error_e db_open(db_open_mode mode, uid_t uid)
                NULL
        };
 
-       if (access(ail_get_app_DB(uid), F_OK)) {
-               if (AIL_ERROR_OK == db_util_open_with_options(ail_get_app_DB(uid), &dbInit, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL))
+       char *db = ail_get_app_DB(uid);
+       char *global_db = ail_get_app_DB(GLOBAL_USER);
+
+       if (access(db, F_OK)) {
+               if (AIL_ERROR_OK == db_util_open_with_options(db, &dbInit, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL))
                {
                        for (i = 0; tbls[i] != NULL; i++) {
                                ret = do_db_exec(tbls[i], dbInit);
                                retv_if(ret != AIL_ERROR_OK, AIL_ERROR_DB_FAILED);
                        }
-                       if(AIL_ERROR_OK != ail_db_change_perm(ail_get_app_DB(uid))) {
+                       if(getuid() == OWNER_ROOT && AIL_ERROR_OK != ail_db_change_perm(db, uid)) {
                                _E("Failed to change permission\n");
-               }
+                       }
                } else {
                        dbInit = NULL;
-                       _E("Failed to create table %s\n", ail_get_app_DB(uid));
+                       _E("Failed to create table %s\n", db);
                }
        }
        if(dbInit) {
@@ -353,48 +358,57 @@ ail_error_e db_open(db_open_mode mode, uid_t uid)
        if(mode & DB_OPEN_RO) {
                if(uid != GLOBAL_USER) {
                        if (!db_info.dbUserro) {
-                               db_util_open_with_options(ail_get_app_DB(uid), &db_info.dbUserro, SQLITE_OPEN_READONLY, NULL);
+                               db_util_open_with_options(db, &db_info.dbUserro, SQLITE_OPEN_READONLY, NULL);
                                char query_attach[AIL_SQL_QUERY_MAX_LEN];
                                char query_view_app[AIL_SQL_QUERY_MAX_LEN];
                                char query_view_local[AIL_SQL_QUERY_MAX_LEN];
-                               snprintf(query_attach, AIL_SQL_QUERY_MAX_LEN, QUERY_ATTACH, ail_get_app_DB(GLOBAL_USER));
+                               snprintf(query_attach, AIL_SQL_QUERY_MAX_LEN, QUERY_ATTACH, global_db);
                                if (db_exec_usr_ro(query_attach) < 0) {
                                        _D("executing query_attach : %s", query_attach );
-                                       return AIL_ERROR_DB_FAILED;
+                                       goto error;
                                }
                                snprintf(query_view_app, AIL_SQL_QUERY_MAX_LEN, QUERY_CREATE_VIEW_APP);
                                if (db_exec_usr_ro(query_view_app) < 0) {
                                        _D("executing query_attach : %s", query_view_app );
-                                       return AIL_ERROR_DB_FAILED;
+                                       goto error;
                                }
 
                                snprintf(query_view_local, AIL_SQL_QUERY_MAX_LEN, QUERY_CREATE_VIEW_LOCAL);
                                if (db_exec_usr_ro(query_view_local) < 0) {
                                        _D("executing query_attach : %s", query_view_local );
-                                       return AIL_ERROR_DB_FAILED;
+                                       goto error;
                                }
                        }
                } else {
                        if (!db_info.dbGlobalro) {
-                               ret = db_util_open_with_options(ail_get_app_DB(GLOBAL_USER), &db_info.dbGlobalro, SQLITE_OPEN_READONLY, NULL);
+                               ret = db_util_open_with_options(global_db, &db_info.dbGlobalro, SQLITE_OPEN_READONLY, NULL);
                                retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
                        }
                }
- }
      }
        if(mode & DB_OPEN_RW) {
                if(uid != GLOBAL_USER) {
                        if(!db_info.dbUserrw){
-                               ret = db_util_open(ail_get_app_DB(uid), &db_info.dbUserrw, 0);
+                               ret = db_util_open(db, &db_info.dbUserrw, 0);
                        }
                } else {
                        if(!db_info.dbGlobalrw){
-                               ret = db_util_open(ail_get_app_DB(GLOBAL_USER), &db_info.dbGlobalrw, 0);
+                               ret = db_util_open(global_db, &db_info.dbGlobalrw, 0);
                        }
                }
                retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
        }
 
+       free(global_db);
+       free(db);
+
        return AIL_ERROR_OK;
+
+error:
+       free(global_db);
+       free(db);
+
+       return AIL_ERROR_DB_FAILED;
 }
 
 
@@ -550,7 +564,7 @@ ail_error_e db_finalize(sqlite3_stmt *stmt)
 ail_error_e do_db_exec(const char *query, sqlite3 * fileSQL)
 {
        int ret;
-       char *errmsg;
+       char *errmsg = NULL;
 
        retv_if(!query, AIL_ERROR_INVALID_PARAMETER);
        retv_if(!fileSQL, AIL_ERROR_DB_FAILED);
@@ -559,7 +573,8 @@ ail_error_e do_db_exec(const char *query, sqlite3 * fileSQL)
        if (ret != SQLITE_OK) {
                _E("Cannot execute this query - %s. because %s",
                                query, errmsg? errmsg:"uncatched error");
-               sqlite3_free(errmsg);
+               if(errmsg)
+                       sqlite3_free(errmsg);
                return AIL_ERROR_DB_FAILED;
        }