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