Add sending wakeup wakeup signal to resourced
[platform/core/appfw/pkgmgr-info.git] / src / pkgmgrinfo_db.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <ctype.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <grp.h>
11 #include <dirent.h>
12 #include <libgen.h>
13
14 #include <sqlite3.h>
15
16 #include <tzplatform_config.h>
17 #include <db-util.h>
18
19 #include "pkgmgr-info.h"
20 #include "pkgmgrinfo_debug.h"
21 #include "pkgmgrinfo_private.h"
22 #include "pkgmgr_parser.h"
23 #include "pkgmgr_parser_db.h"
24
25 typedef int (*sqlite_query_callback)(void *data, int ncols, char **coltxt, char **colname);
26
27 static int _mkdir_for_user(const char* dir, uid_t uid, gid_t gid)
28 {
29         int ret;
30         char *fullpath;
31         char *subpath;
32         char buf[1024];
33         int fd;
34         struct stat sb;
35
36         fullpath = strdup(dir);
37         if (fullpath == NULL)
38                 return -1;
39         subpath = dirname(fullpath);
40         if (strlen(subpath) > 1 && strcmp(subpath, fullpath) != 0) {
41                 ret = _mkdir_for_user(fullpath, uid, gid);
42                 if (ret == -1) {
43                         free(fullpath);
44                         return ret;
45                 }
46         }
47
48         ret = mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
49         if (ret && errno != EEXIST) {
50                 free(fullpath);
51                 return ret;
52         } else if (ret && errno == EEXIST) {
53                 free(fullpath);
54                 return 0;
55         }
56
57         if (getuid() == ROOT_UID) {
58                 fd = open(dir, O_RDONLY);
59                 if (fd == -1) {
60                         _LOGE("FAIL : open %s : %s", dir,
61                                         strerror_r(errno, buf, sizeof(buf)));
62                         free(fullpath);
63                         return -1;
64                 }
65                 ret = fstat(fd, &sb);
66                 if (ret == -1) {
67                         _LOGE("FAIL : fstat %s : %s", dir,
68                                         strerror_r(errno, buf, sizeof(buf)));
69                         close(fd);
70                         free(fullpath);
71                         return -1;
72                 }
73                 if (S_ISLNK(sb.st_mode)) {
74                         _LOGE("FAIL : %s is symlink!", dir);
75                         close(fd);
76                         free(fullpath);
77                         return -1;
78                 }
79                 ret = fchown(fd, uid, gid);
80                 if (ret == -1) {
81                         _LOGE("FAIL : fchown %s %d.%d, because %s", dir, uid,
82                                         gid, strerror_r(errno, buf, sizeof(buf)));
83                         close(fd);
84                         free(fullpath);
85                         return -1;
86                 }
87                 close(fd);
88         }
89
90         free(fullpath);
91
92         return 0;
93 }
94
95 static char *_get_db_path(uid_t uid)
96 {
97         const char *db_path;
98         char path[PATH_MAX];
99
100         db_path = tzplatform_getenv(TZ_SYS_DB);
101         if (db_path == NULL) {
102                 _LOGE("Failed to get TZ_SYS_DB path");
103                 return NULL;
104         }
105
106         if (uid == GLOBAL_USER || uid == ROOT_UID)
107                 return strdup(db_path);
108
109         snprintf(path, sizeof(path), "%s/user/%d", db_path, uid);
110
111         return strdup(path);
112 }
113
114 int _check_create_cert_db(void)
115 {
116         return pkgmgr_parser_initialize_cert_db();
117 }
118
119 static gid_t _get_gid(const char *name)
120 {
121         char buf[BUFSIZE];
122         struct group entry;
123         struct group *ge;
124         int ret;
125
126         ret = getgrnam_r(name, &entry, buf, sizeof(buf), &ge);
127         if (ret || ge == NULL) {
128                 _LOGE("fail to get gid of %s", name);
129                 return -1;
130         }
131
132         return entry.gr_gid;
133 }
134
135 API const char *getIconPath(uid_t uid, bool readonly)
136 {
137         const char *path = NULL;
138         uid_t uid_caller = getuid();
139         gid_t gid = ROOT_UID;
140
141         if (uid != GLOBAL_USER && uid != ROOT_UID) {
142                 _LOGD("not supported target user");
143                 return NULL;
144         }
145
146         if (readonly)
147                 path = tzplatform_mkpath(TZ_SYS_RO_ICONS, "/");
148
149         /* just allow certain users to create the icon directory if needed. */
150         if (path && (uid_caller == ROOT_UID  ||
151                 uid_caller == APPFW_UID || uid_caller == uid))
152                 _mkdir_for_user(path, uid, gid);
153
154         return path;
155 }
156
157 API char *getUserPkgParserDBPath(void)
158 {
159         return getUserPkgParserDBPathUID(_getuid());
160 }
161
162 API char *getUserPkgParserDBPathUID(uid_t uid)
163 {
164         char pkgmgr_parser_db[PATH_MAX];
165         uid_t uid_caller = getuid();
166         gid_t gid = ROOT_UID;
167         char *db_path;
168
169         db_path = _get_db_path(uid);
170         if (db_path == NULL) {
171                 _LOGE("Failed to get db path %d", uid);
172                 return NULL;
173         }
174         snprintf(pkgmgr_parser_db, sizeof(pkgmgr_parser_db),
175                         "%s/.pkgmgr_parser.db", db_path);
176         if (access(db_path, F_OK) != 0) {
177                 if (uid != GLOBAL_USER && uid != ROOT_UID) {
178                         tzplatform_set_user(uid);
179                         gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
180                         tzplatform_reset_user();
181                 }
182                 /* just allow certain users to create the dbspace directory if needed. */
183                 if (uid_caller == ROOT_UID || uid_caller == APPFW_UID ||
184                                 uid_caller == uid)
185                         _mkdir_for_user(db_path, uid, gid);
186         }
187         free(db_path);
188
189         return strdup(pkgmgr_parser_db);
190 }
191
192 API char *getUserPkgCertDBPath(void)
193 {
194         char *db_path;
195         char pkgmgr_cert_db[PATH_MAX];
196
197         db_path = _get_db_path(GLOBAL_USER);
198         snprintf(pkgmgr_cert_db, sizeof(pkgmgr_cert_db),
199                         "%s/.pkgmgr_cert.db", db_path);
200         free(db_path);
201
202         return strdup(pkgmgr_cert_db);
203 }
204
205 API const char *getUserManifestPath(uid_t uid, bool readonly)
206 {
207         const char *path = NULL;
208         uid_t uid_caller = getuid();
209         gid_t gid = ROOT_UID;
210
211         if (uid != GLOBAL_USER && uid != ROOT_UID) {
212                 tzplatform_set_user(uid);
213                 path = tzplatform_mkpath(TZ_USER_PACKAGES, "/");
214                 gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
215                 tzplatform_reset_user();
216         } else {
217                 if (readonly)
218                         path = tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/");
219                 else
220                         path = tzplatform_mkpath(TZ_SYS_RW_PACKAGES, "/");
221         }
222
223         /* just allow certain users to create the icon directory if needed. */
224         if (uid_caller == ROOT_UID || uid_caller == APPFW_UID || uid_caller == uid)
225                 _mkdir_for_user(path, uid, gid);
226
227         return path;
228 }
229
230 void _save_column_int(sqlite3_stmt *stmt, int idx, int *i)
231 {
232         *i = sqlite3_column_int(stmt, idx);
233 }
234
235 inline void _save_column_str(sqlite3_stmt *stmt, int idx, char **str)
236 {
237         const char *val;
238
239         val = (const char *)sqlite3_column_text(stmt, idx);
240         if (val)
241                 *str = strdup(val);
242 }
243
244 API int pkgmgrinfo_pkginfo_set_usr_installed_storage(const char *pkgid, INSTALL_LOCATION location, const char *external_pkg_path, uid_t uid)
245 {
246         retvm_if(pkgid == NULL, PMINFO_R_EINVAL, "pkgid is NULL\n");
247         int ret = -1;
248         sqlite3 *pkgmgr_parser_db = NULL;
249         char *query = NULL;
250         char *db_path;
251         const char *location_str;
252
253         db_path = getUserPkgParserDBPathUID(uid);
254         if (db_path == NULL) {
255                 _LOGE("Failed to get pkg parser db path - %d", uid);
256                 return PMINFO_R_ERROR;
257         }
258
259         ret = db_util_open_with_options(db_path, &pkgmgr_parser_db,
260                         SQLITE_OPEN_READWRITE, NULL);
261         if (ret != SQLITE_OK) {
262                 _LOGE("connect db failed!");
263                 free(db_path);
264                 return PMINFO_R_ERROR;
265         }
266         free(db_path);
267
268         /*Begin transaction*/
269         /* Setting Manifest DB */
270         ret = sqlite3_exec(pkgmgr_parser_db, "BEGIN EXCLUSIVE", NULL, NULL, NULL);
271         tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to begin transaction\n");
272         _LOGD("Transaction Begin\n");
273
274         if (location == INSTALL_INTERNAL)
275                 location_str = "installed_internal";
276         else if (location == INSTALL_EXTERNAL)
277                 location_str = "installed_external";
278         else
279                 location_str = "installed_extended";
280         /* pkgcakge_info table */
281         query = sqlite3_mprintf(
282                         "update package_info set installed_storage=%Q, external_path=%Q where package=%Q",
283                         location_str, external_pkg_path, pkgid);
284
285         ret = sqlite3_exec(pkgmgr_parser_db, query, NULL, NULL, NULL);
286         tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query);
287         sqlite3_free(query);
288
289         /* package_app_info table */
290         query = sqlite3_mprintf(
291                         "update package_app_info set app_installed_storage=%Q, app_external_path=%Q where package=%Q",
292                         location_str, external_pkg_path, pkgid);
293
294         ret = sqlite3_exec(pkgmgr_parser_db, query, NULL, NULL, NULL);
295         tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query);
296
297         /*Commit transaction*/
298         ret = sqlite3_exec(pkgmgr_parser_db, "COMMIT", NULL, NULL, NULL);
299         if (ret != SQLITE_OK) {
300                 _LOGE("Failed to commit transaction. Rollback now\n");
301                 ret = sqlite3_exec(pkgmgr_parser_db, "ROLLBACK", NULL, NULL, NULL);
302                 tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query);
303         }
304         _LOGD("Transaction Commit and End\n");
305
306         ret = PMINFO_R_OK;
307 catch:
308         sqlite3_close(pkgmgr_parser_db);
309         sqlite3_free(query);
310         return ret;
311 }
312
313 API int pkgmgrinfo_pkginfo_set_installed_storage(const char *pkgid, INSTALL_LOCATION location, const char *external_pkg_path)
314 {
315         return pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid, location, external_pkg_path, _getuid());
316 }