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